[310/906] Global reindent

Indent parameters:
INDENT_PARAMETERS="--braces-on-if-line \
        --case-brace-indentation0 \
        --case-indentation2 \
        --braces-after-struct-decl-line \
        --line-length80 \
        --no-tabs \
        --cuddle-else \
        --dont-line-up-parentheses \
        --honour-newlines \
        --continuation-indentation4 \
        --tab-size8 \
        --indent-level2"
This commit is contained in:
David Schleef 2009-02-10 22:39:14 -08:00 committed by Matthew Waters
parent 3fbd8bbd24
commit d015d5862d
42 changed files with 5376 additions and 5424 deletions

View file

@ -25,40 +25,40 @@
#include "gstglbuffer.h" #include "gstglbuffer.h"
static GObjectClass* gst_gl_buffer_parent_class; static GObjectClass *gst_gl_buffer_parent_class;
static void static void
gst_gl_buffer_finalize (GstGLBuffer* buffer) gst_gl_buffer_finalize (GstGLBuffer * buffer)
{ {
//blocking call, put the texture in the pool //blocking call, put the texture in the pool
gst_gl_display_del_texture (buffer->display, buffer->texture, gst_gl_display_del_texture (buffer->display, buffer->texture,
buffer->width, buffer->height); buffer->width, buffer->height);
g_object_unref (buffer->display); g_object_unref (buffer->display);
GST_MINI_OBJECT_CLASS (gst_gl_buffer_parent_class)-> GST_MINI_OBJECT_CLASS (gst_gl_buffer_parent_class)->finalize (GST_MINI_OBJECT
finalize (GST_MINI_OBJECT (buffer)); (buffer));
} }
static void 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->width = 0; buffer->width = 0;
buffer->height = 0; buffer->height = 0;
buffer->texture = 0; buffer->texture = 0;
} }
static void static void
gst_gl_buffer_class_init (gpointer g_class, gpointer class_data) gst_gl_buffer_class_init (gpointer g_class, gpointer class_data)
{ {
GstMiniObjectClass* mini_object_class = GST_MINI_OBJECT_CLASS (g_class); GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
gst_gl_buffer_parent_class = g_type_class_peek_parent (g_class); gst_gl_buffer_parent_class = g_type_class_peek_parent (g_class);
mini_object_class->finalize = (GstMiniObjectFinalizeFunction) mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
gst_gl_buffer_finalize; gst_gl_buffer_finalize;
} }
@ -87,47 +87,48 @@ gst_gl_buffer_get_type (void)
} }
GstGLBuffer* GstGLBuffer *
gst_gl_buffer_new (GstGLDisplay* display, gst_gl_buffer_new (GstGLDisplay * display, gint gl_width, gint gl_height)
gint gl_width, gint gl_height)
{ {
GstGLBuffer* gl_buffer = (GstGLBuffer *) gst_mini_object_new (GST_TYPE_GL_BUFFER); GstGLBuffer *gl_buffer =
(GstGLBuffer *) gst_mini_object_new (GST_TYPE_GL_BUFFER);
gl_buffer->display = g_object_ref (display); gl_buffer->display = g_object_ref (display);
gl_buffer->width = gl_width; gl_buffer->width = gl_width;
gl_buffer->height = gl_height; gl_buffer->height = gl_height;
//it does not depends on the video format because gl buffer has always one texture. //it does not depends on the video format because gl buffer has always one texture.
//the one attached to the upload FBO //the one attached to the upload FBO
GST_BUFFER_SIZE (gl_buffer) = gst_gl_buffer_get_size (gl_width, gl_height); GST_BUFFER_SIZE (gl_buffer) = gst_gl_buffer_get_size (gl_width, gl_height);
//blocking call, generate a texture using the pool //blocking call, generate a texture using the pool
gst_gl_display_gen_texture (gl_buffer->display, &gl_buffer->texture, gl_width, gl_height) ; gst_gl_display_gen_texture (gl_buffer->display, &gl_buffer->texture, gl_width,
gl_height);
return gl_buffer; return gl_buffer;
} }
gint gint
gst_gl_buffer_get_size (gint width, gint 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_parse_caps (GstCaps* caps, gint* width, gint* height) gst_gl_buffer_parse_caps (GstCaps * caps, gint * width, gint * height)
{ {
GstStructure* structure = gst_caps_get_structure (caps, 0); GstStructure *structure = gst_caps_get_structure (caps, 0);
gboolean ret = gst_structure_has_name (structure, "video/x-raw-gl"); gboolean ret = gst_structure_has_name (structure, "video/x-raw-gl");
if (!ret)
return ret;
ret = gst_structure_get_int (structure, "width", width);
ret &= gst_structure_get_int (structure, "height", height);
if (!ret)
return ret; return ret;
ret = gst_structure_get_int (structure, "width", width);
ret &= gst_structure_get_int (structure, "height", height);
return ret;
} }

File diff suppressed because it is too large Load diff

View file

@ -31,48 +31,48 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
static GstStaticPadTemplate gst_gl_filter_src_pad_template = static GstStaticPadTemplate gst_gl_filter_src_pad_template =
GST_STATIC_PAD_TEMPLATE ("src", GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC, GST_PAD_SRC,
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_GL_VIDEO_CAPS) GST_STATIC_CAPS (GST_GL_VIDEO_CAPS)
); );
static GstStaticPadTemplate gst_gl_filter_sink_pad_template = static GstStaticPadTemplate gst_gl_filter_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_GL_VIDEO_CAPS) GST_STATIC_CAPS (GST_GL_VIDEO_CAPS)
); );
#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");
GST_BOILERPLATE_FULL (GstGLFilter, gst_gl_filter, GstBaseTransform, GST_BOILERPLATE_FULL (GstGLFilter, gst_gl_filter, GstBaseTransform,
GST_TYPE_BASE_TRANSFORM, DEBUG_INIT); GST_TYPE_BASE_TRANSFORM, DEBUG_INIT);
static void gst_gl_filter_set_property (GObject * object, guint prop_id, static void gst_gl_filter_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec); const GValue * value, GParamSpec * pspec);
static void gst_gl_filter_get_property (GObject * object, guint prop_id, static void gst_gl_filter_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
static GstCaps* gst_gl_filter_transform_caps (GstBaseTransform* bt, static GstCaps *gst_gl_filter_transform_caps (GstBaseTransform * bt,
GstPadDirection direction, GstCaps* caps); GstPadDirection direction, GstCaps * caps);
static void gst_gl_filter_reset (GstGLFilter * filter); static void gst_gl_filter_reset (GstGLFilter * filter);
static gboolean gst_gl_filter_start (GstBaseTransform * bt); static gboolean gst_gl_filter_start (GstBaseTransform * bt);
static gboolean gst_gl_filter_stop (GstBaseTransform * bt); static gboolean gst_gl_filter_stop (GstBaseTransform * bt);
static gboolean gst_gl_filter_get_unit_size (GstBaseTransform * trans, static gboolean gst_gl_filter_get_unit_size (GstBaseTransform * trans,
GstCaps * caps, guint * size); GstCaps * caps, guint * size);
static GstFlowReturn gst_gl_filter_transform (GstBaseTransform * bt, static GstFlowReturn gst_gl_filter_transform (GstBaseTransform * bt,
GstBuffer * inbuf, GstBuffer * outbuf); GstBuffer * inbuf, GstBuffer * outbuf);
static GstFlowReturn gst_gl_filter_prepare_output_buffer (GstBaseTransform * static GstFlowReturn gst_gl_filter_prepare_output_buffer (GstBaseTransform *
trans, GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf); trans, GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf);
static gboolean gst_gl_filter_set_caps (GstBaseTransform * bt, GstCaps * incaps, static gboolean gst_gl_filter_set_caps (GstBaseTransform * bt, GstCaps * incaps,
GstCaps * outcaps); GstCaps * outcaps);
static gboolean gst_gl_filter_do_transform (GstGLFilter * filter, static gboolean gst_gl_filter_do_transform (GstGLFilter * filter,
GstGLBuffer * inbuf, GstGLBuffer * outbuf); GstGLBuffer * inbuf, GstGLBuffer * outbuf);
/* GstGLDisplayThreadFunc */ /* GstGLDisplayThreadFunc */
static void gst_gl_filter_start_gl (GstGLDisplay *display, gpointer data); static void gst_gl_filter_start_gl (GstGLDisplay * display, gpointer data);
static void gst_gl_filter_stop_gl (GstGLDisplay *display, gpointer data); static void gst_gl_filter_stop_gl (GstGLDisplay * display, gpointer data);
static void static void
@ -81,9 +81,9 @@ gst_gl_filter_base_init (gpointer klass)
GstElementClass *element_class = GST_ELEMENT_CLASS (klass); GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
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,
gst_static_pad_template_get (&gst_gl_filter_sink_pad_template)); gst_static_pad_template_get (&gst_gl_filter_sink_pad_template));
} }
static void static void
@ -96,14 +96,14 @@ gst_gl_filter_class_init (GstGLFilterClass * klass)
gobject_class->get_property = gst_gl_filter_get_property; gobject_class->get_property = gst_gl_filter_get_property;
GST_BASE_TRANSFORM_CLASS (klass)->transform_caps = GST_BASE_TRANSFORM_CLASS (klass)->transform_caps =
gst_gl_filter_transform_caps; gst_gl_filter_transform_caps;
GST_BASE_TRANSFORM_CLASS (klass)->transform = gst_gl_filter_transform; GST_BASE_TRANSFORM_CLASS (klass)->transform = gst_gl_filter_transform;
GST_BASE_TRANSFORM_CLASS (klass)->start = gst_gl_filter_start; GST_BASE_TRANSFORM_CLASS (klass)->start = gst_gl_filter_start;
GST_BASE_TRANSFORM_CLASS (klass)->stop = gst_gl_filter_stop; GST_BASE_TRANSFORM_CLASS (klass)->stop = gst_gl_filter_stop;
GST_BASE_TRANSFORM_CLASS (klass)->set_caps = gst_gl_filter_set_caps; GST_BASE_TRANSFORM_CLASS (klass)->set_caps = gst_gl_filter_set_caps;
GST_BASE_TRANSFORM_CLASS (klass)->get_unit_size = gst_gl_filter_get_unit_size; GST_BASE_TRANSFORM_CLASS (klass)->get_unit_size = gst_gl_filter_get_unit_size;
GST_BASE_TRANSFORM_CLASS (klass)->prepare_output_buffer = GST_BASE_TRANSFORM_CLASS (klass)->prepare_output_buffer =
gst_gl_filter_prepare_output_buffer; gst_gl_filter_prepare_output_buffer;
klass->set_caps = NULL; klass->set_caps = NULL;
klass->filter = NULL; klass->filter = NULL;
@ -128,48 +128,45 @@ gst_gl_filter_init (GstGLFilter * filter, GstGLFilterClass * klass)
static void static void
gst_gl_filter_set_property (GObject * object, guint prop_id, gst_gl_filter_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec) const GValue * value, GParamSpec * pspec)
{ {
//GstGLFilter *filter = GST_GL_FILTER (object); //GstGLFilter *filter = GST_GL_FILTER (object);
switch (prop_id) switch (prop_id) {
{ default:
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break;
break;
} }
} }
static void static void
gst_gl_filter_get_property (GObject * object, guint prop_id, gst_gl_filter_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec) GValue * value, GParamSpec * pspec)
{ {
//GstGLFilter *filter = GST_GL_FILTER (object); //GstGLFilter *filter = GST_GL_FILTER (object);
switch (prop_id) switch (prop_id) {
{ default:
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break;
break;
} }
} }
static void static void
gst_gl_filter_reset (GstGLFilter* filter) gst_gl_filter_reset (GstGLFilter * filter)
{ {
GstGLFilterClass* filter_class = GST_GL_FILTER_GET_CLASS (filter); GstGLFilterClass *filter_class = GST_GL_FILTER_GET_CLASS (filter);
if (filter->display) if (filter->display) {
{
if (filter_class->onReset) if (filter_class->onReset)
filter_class->onReset (filter); filter_class->onReset (filter);
if (filter_class->display_reset_cb != NULL) { if (filter_class->display_reset_cb != NULL) {
gst_gl_display_thread_add (filter->display, gst_gl_filter_stop_gl, filter); gst_gl_display_thread_add (filter->display, gst_gl_filter_stop_gl,
filter);
} }
//blocking call, delete the FBO //blocking call, delete the FBO
gst_gl_display_del_fbo (filter->display, filter->fbo, gst_gl_display_del_fbo (filter->display, filter->fbo, filter->depthbuffer);
filter->depthbuffer);
g_object_unref (filter->display); g_object_unref (filter->display);
filter->display = NULL; filter->display = NULL;
} }
@ -180,19 +177,19 @@ gst_gl_filter_reset (GstGLFilter* filter)
} }
static gboolean static gboolean
gst_gl_filter_start (GstBaseTransform* bt) gst_gl_filter_start (GstBaseTransform * bt)
{ {
GstGLFilter *filter = GST_GL_FILTER (bt); GstGLFilter *filter = GST_GL_FILTER (bt);
GstGLFilterClass *filter_class = GST_GL_FILTER_GET_CLASS (filter); GstGLFilterClass *filter_class = GST_GL_FILTER_GET_CLASS (filter);
if (filter_class->onStart) if (filter_class->onStart)
filter_class->onStart (filter); filter_class->onStart (filter);
return TRUE; return TRUE;
} }
static gboolean static gboolean
gst_gl_filter_stop (GstBaseTransform* bt) gst_gl_filter_stop (GstBaseTransform * bt)
{ {
GstGLFilter *filter = GST_GL_FILTER (bt); GstGLFilter *filter = GST_GL_FILTER (bt);
GstGLFilterClass *filter_class = GST_GL_FILTER_GET_CLASS (filter); GstGLFilterClass *filter_class = GST_GL_FILTER_GET_CLASS (filter);
@ -206,7 +203,7 @@ gst_gl_filter_stop (GstBaseTransform* bt)
} }
static void static void
gst_gl_filter_start_gl (GstGLDisplay *display, gpointer data) gst_gl_filter_start_gl (GstGLDisplay * display, gpointer data)
{ {
GstGLFilter *filter = GST_GL_FILTER (data); GstGLFilter *filter = GST_GL_FILTER (data);
GstGLFilterClass *filter_class = GST_GL_FILTER_GET_CLASS (filter); GstGLFilterClass *filter_class = GST_GL_FILTER_GET_CLASS (filter);
@ -215,7 +212,7 @@ gst_gl_filter_start_gl (GstGLDisplay *display, gpointer data)
} }
static void static void
gst_gl_filter_stop_gl (GstGLDisplay *display, gpointer data) gst_gl_filter_stop_gl (GstGLDisplay * display, gpointer data)
{ {
GstGLFilter *filter = GST_GL_FILTER (data); GstGLFilter *filter = GST_GL_FILTER (data);
GstGLFilterClass *filter_class = GST_GL_FILTER_GET_CLASS (filter); GstGLFilterClass *filter_class = GST_GL_FILTER_GET_CLASS (filter);
@ -223,30 +220,28 @@ gst_gl_filter_stop_gl (GstGLDisplay *display, gpointer data)
filter_class->display_reset_cb (filter); filter_class->display_reset_cb (filter);
} }
static GstCaps* static GstCaps *
gst_gl_filter_transform_caps (GstBaseTransform* bt, gst_gl_filter_transform_caps (GstBaseTransform * bt,
GstPadDirection direction, GstCaps* caps) GstPadDirection direction, GstCaps * caps)
{ {
//GstGLFilter* filter = GST_GL_FILTER (bt); //GstGLFilter* filter = GST_GL_FILTER (bt);
GstStructure* structure = gst_caps_get_structure (caps, 0); GstStructure *structure = gst_caps_get_structure (caps, 0);
GstCaps* ret = gst_caps_copy (caps); GstCaps *ret = gst_caps_copy (caps);
const GValue* par = NULL; const GValue *par = NULL;
structure = gst_structure_copy (gst_caps_get_structure (ret, 0)); structure = gst_structure_copy (gst_caps_get_structure (ret, 0));
gst_structure_set (structure, gst_structure_set (structure,
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT, "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"height", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
gst_caps_merge_structure (ret, gst_structure_copy (structure)); gst_caps_merge_structure (ret, gst_structure_copy (structure));
if ((par = gst_structure_get_value (structure, "pixel-aspect-ratio"))) if ((par = gst_structure_get_value (structure, "pixel-aspect-ratio"))) {
{
gst_structure_set (structure, gst_structure_set (structure,
"pixel-aspect-ratio", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); "pixel-aspect-ratio", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
gst_caps_merge_structure (ret, structure); gst_caps_merge_structure (ret, structure);
} } else
else
gst_structure_free (structure); gst_structure_free (structure);
GST_DEBUG_OBJECT (bt, "returning caps: %" GST_PTR_FORMAT, ret); GST_DEBUG_OBJECT (bt, "returning caps: %" GST_PTR_FORMAT, ret);
@ -256,8 +251,8 @@ gst_gl_filter_transform_caps (GstBaseTransform* bt,
static gboolean 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 = FALSE; gboolean ret = FALSE;
gint width = 0; gint width = 0;
@ -271,27 +266,27 @@ gst_gl_filter_get_unit_size (GstBaseTransform* trans, GstCaps* caps,
} }
static GstFlowReturn static GstFlowReturn
gst_gl_filter_prepare_output_buffer (GstBaseTransform* trans, gst_gl_filter_prepare_output_buffer (GstBaseTransform * trans,
GstBuffer* inbuf, gint size, GstCaps* caps, GstBuffer** buf) GstBuffer * inbuf, gint size, GstCaps * caps, GstBuffer ** buf)
{ {
GstGLFilter* filter = NULL; GstGLFilter *filter = NULL;
GstGLBuffer* gl_inbuf = GST_GL_BUFFER (inbuf); GstGLBuffer *gl_inbuf = GST_GL_BUFFER (inbuf);
GstGLBuffer* gl_outbuf = NULL; GstGLBuffer *gl_outbuf = NULL;
filter = GST_GL_FILTER (trans); filter = GST_GL_FILTER (trans);
if (filter->display == NULL) if (filter->display == NULL) {
{ GstGLFilterClass *filter_class = GST_GL_FILTER_GET_CLASS (filter);
GstGLFilterClass* filter_class = GST_GL_FILTER_GET_CLASS (filter);
filter->display = g_object_ref (gl_inbuf->display); filter->display = g_object_ref (gl_inbuf->display);
//blocking call, generate a FBO //blocking call, generate a FBO
gst_gl_display_gen_fbo (filter->display, filter->width, filter->height, gst_gl_display_gen_fbo (filter->display, filter->width, filter->height,
&filter->fbo, &filter->depthbuffer); &filter->fbo, &filter->depthbuffer);
if (filter_class->display_init_cb != NULL) { if (filter_class->display_init_cb != NULL) {
gst_gl_display_thread_add (filter->display, gst_gl_filter_start_gl, filter); gst_gl_display_thread_add (filter->display, gst_gl_filter_start_gl,
filter);
} }
if (filter_class->onInitFBO) if (filter_class->onInitFBO)
@ -299,7 +294,7 @@ gst_gl_filter_prepare_output_buffer (GstBaseTransform* trans,
} }
gl_outbuf = gst_gl_buffer_new (filter->display, gl_outbuf = gst_gl_buffer_new (filter->display,
filter->width, filter->height); filter->width, filter->height);
*buf = GST_BUFFER (gl_outbuf); *buf = GST_BUFFER (gl_outbuf);
gst_buffer_set_caps (*buf, caps); gst_buffer_set_caps (*buf, caps);
@ -311,20 +306,19 @@ gst_gl_filter_prepare_output_buffer (GstBaseTransform* trans,
} }
static gboolean static gboolean
gst_gl_filter_set_caps (GstBaseTransform* bt, GstCaps* incaps, gst_gl_filter_set_caps (GstBaseTransform * bt, GstCaps * incaps,
GstCaps* outcaps) GstCaps * outcaps)
{ {
GstGLFilter* filter = GST_GL_FILTER (bt); GstGLFilter *filter = GST_GL_FILTER (bt);
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_parse_caps (outcaps, &filter->width, &filter->height); ret = gst_gl_buffer_parse_caps (outcaps, &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);
if (!ret) if (!ret) {
{
GST_DEBUG ("bad caps"); GST_DEBUG ("bad caps");
return FALSE; return FALSE;
} }
@ -335,12 +329,12 @@ gst_gl_filter_set_caps (GstBaseTransform* bt, GstCaps* incaps,
} }
static GstFlowReturn static GstFlowReturn
gst_gl_filter_transform (GstBaseTransform* bt, GstBuffer* inbuf, gst_gl_filter_transform (GstBaseTransform * bt, GstBuffer * inbuf,
GstBuffer* outbuf) GstBuffer * outbuf)
{ {
GstGLFilter* filter; GstGLFilter *filter;
GstGLBuffer* gl_inbuf = GST_GL_BUFFER (inbuf); GstGLBuffer *gl_inbuf = GST_GL_BUFFER (inbuf);
GstGLBuffer* gl_outbuf = GST_GL_BUFFER (outbuf); GstGLBuffer *gl_outbuf = GST_GL_BUFFER (outbuf);
filter = GST_GL_FILTER (bt); filter = GST_GL_FILTER (bt);
@ -350,10 +344,10 @@ gst_gl_filter_transform (GstBaseTransform* bt, GstBuffer* inbuf,
} }
static gboolean static gboolean
gst_gl_filter_do_transform (GstGLFilter* filter, gst_gl_filter_do_transform (GstGLFilter * filter,
GstGLBuffer* inbuf, GstGLBuffer* outbuf) GstGLBuffer * inbuf, GstGLBuffer * outbuf)
{ {
GstGLFilterClass* filter_class = GST_GL_FILTER_GET_CLASS (filter); GstGLFilterClass *filter_class = GST_GL_FILTER_GET_CLASS (filter);
filter_class->filter (filter, inbuf, outbuf); filter_class->filter (filter, inbuf, outbuf);
@ -363,15 +357,13 @@ gst_gl_filter_do_transform (GstGLFilter* filter,
/* convenience functions to simplify filter development */ /* convenience functions to simplify filter development */
void void
gst_gl_filter_render_to_target (GstGLFilter *filter, gst_gl_filter_render_to_target (GstGLFilter * filter,
GLuint input, GLuint target, GLuint input, GLuint target, GLCB func, gpointer data)
GLCB func, gpointer data)
{ {
gst_gl_display_use_fbo (filter->display, filter->width, filter->height, gst_gl_display_use_fbo (filter->display, filter->width, filter->height,
filter->fbo, filter->depthbuffer, target, filter->fbo, filter->depthbuffer, target,
func, func,
filter->width, filter->height, input, filter->width, filter->height, input,
0, filter->width, 0, filter->height, 0, filter->width, 0, filter->height,
GST_GL_DISPLAY_PROJECTION_ORTHO2D, GST_GL_DISPLAY_PROJECTION_ORTHO2D, data);
data);
} }

View file

@ -132,8 +132,8 @@ gst_gl_shader_get_property (GObject * object,
} }
static void static void
gst_gl_shader_log_handler (const gchar *domain, GLogLevelFlags flags, gst_gl_shader_log_handler (const gchar * domain, GLogLevelFlags flags,
const gchar *message, gpointer user_data) const gchar * message, gpointer user_data)
{ {
if (_gst_gl_shader_debug) { if (_gst_gl_shader_debug) {
g_log_default_handler (domain, flags, message, user_data); g_log_default_handler (domain, flags, message, user_data);
@ -249,7 +249,7 @@ gst_gl_shader_init (GstGLShader * self)
_gst_gl_shader_debug = TRUE; _gst_gl_shader_debug = TRUE;
g_log_set_handler ("GstGLShader", G_LOG_LEVEL_DEBUG, g_log_set_handler ("GstGLShader", G_LOG_LEVEL_DEBUG,
gst_gl_shader_log_handler, NULL); gst_gl_shader_log_handler, NULL);
} }
GstGLShader * GstGLShader *
@ -511,7 +511,7 @@ gst_gl_shader_set_uniform_1i (GstGLShader * shader, const gchar * name,
} }
GLint GLint
gst_gl_shader_get_attribute_location (GstGLShader * shader, const gchar *name) gst_gl_shader_get_attribute_location (GstGLShader * shader, const gchar * name)
{ {
GstGLShaderPrivate *priv; GstGLShaderPrivate *priv;

View file

@ -32,9 +32,11 @@
#define WM_GST_GL_WINDOW_CUSTOM (WM_APP+1) #define WM_GST_GL_WINDOW_CUSTOM (WM_APP+1)
#define WM_GST_GL_WINDOW_QUIT (WM_APP+2) #define WM_GST_GL_WINDOW_QUIT (WM_APP+2)
void gst_gl_window_set_pixel_format (GstGLWindow *window); void gst_gl_window_set_pixel_format (GstGLWindow * window);
LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam,
LRESULT FAR PASCAL sub_class_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); LPARAM lParam);
LRESULT FAR PASCAL sub_class_proc (HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam);
#define GST_GL_WINDOW_GET_PRIVATE(o) \ #define GST_GL_WINDOW_GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_WINDOW, GstGLWindowPrivate)) (G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_WINDOW, GstGLWindowPrivate))
@ -79,8 +81,8 @@ gst_gl_window_finalize (GObject * object)
} }
static void static void
gst_gl_window_log_handler (const gchar *domain, GLogLevelFlags flags, gst_gl_window_log_handler (const gchar * domain, GLogLevelFlags flags,
const gchar *message, gpointer user_data) const gchar * message, gpointer user_data)
{ {
if (_gst_gl_window_debug) { if (_gst_gl_window_debug) {
g_log_default_handler (domain, flags, message, user_data); g_log_default_handler (domain, flags, message, user_data);
@ -106,9 +108,8 @@ gst_gl_window_class_init (GstGLWindowClass * klass)
atom = GetClassInfo (hinstance, "GSTGL", &wc); atom = GetClassInfo (hinstance, "GSTGL", &wc);
if (atom == 0) if (atom == 0) {
{ ZeroMemory (&wc, sizeof (WNDCLASS));
ZeroMemory (&wc, sizeof(WNDCLASS));
wc.lpfnWndProc = window_proc; wc.lpfnWndProc = window_proc;
wc.cbClsExtra = 0; wc.cbClsExtra = 0;
@ -124,12 +125,12 @@ gst_gl_window_class_init (GstGLWindowClass * klass)
atom = RegisterClass (&wc); atom = RegisterClass (&wc);
if (atom == 0) if (atom == 0)
g_error ("Failed to register window class %x\r\n", GetLastError()); g_error ("Failed to register window class %x\r\n", GetLastError ());
} }
} }
static void static void
gst_gl_window_init (GstGLWindow *window) gst_gl_window_init (GstGLWindow * window)
{ {
window->priv = GST_GL_WINDOW_GET_PRIVATE (window); window->priv = GST_GL_WINDOW_GET_PRIVATE (window);
@ -137,7 +138,7 @@ gst_gl_window_init (GstGLWindow *window)
_gst_gl_window_debug = TRUE; _gst_gl_window_debug = TRUE;
g_log_set_handler ("GstGLWindow", G_LOG_LEVEL_DEBUG, g_log_set_handler ("GstGLWindow", G_LOG_LEVEL_DEBUG,
gst_gl_window_log_handler, NULL); gst_gl_window_log_handler, NULL);
} }
/* Must be called in the gl thread */ /* Must be called in the gl thread */
@ -146,7 +147,7 @@ gst_gl_window_new (gint width, gint height)
{ {
GstGLWindow *window = g_object_new (GST_GL_TYPE_WINDOW, NULL); GstGLWindow *window = g_object_new (GST_GL_TYPE_WINDOW, NULL);
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
GstGLWindowClass* klass = GST_GL_WINDOW_GET_CLASS (window); GstGLWindowClass *klass = GST_GL_WINDOW_GET_CLASS (window);
HINSTANCE hinstance = GetModuleHandle (NULL); HINSTANCE hinstance = GetModuleHandle (NULL);
@ -169,22 +170,16 @@ gst_gl_window_new (gint width, gint height)
priv->visible = FALSE; priv->visible = FALSE;
width += 2 * GetSystemMetrics (SM_CXSIZEFRAME); width += 2 * GetSystemMetrics (SM_CXSIZEFRAME);
height += 2 * GetSystemMetrics (SM_CYSIZEFRAME) + GetSystemMetrics (SM_CYCAPTION); height +=
2 * GetSystemMetrics (SM_CYSIZEFRAME) + GetSystemMetrics (SM_CYCAPTION);
priv->internal_win_id = CreateWindowEx ( priv->internal_win_id = CreateWindowEx (0,
0, "GSTGL",
"GSTGL", "OpenGL renderer",
"OpenGL renderer", WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW,
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW, x, y, width, height, (HWND) NULL, (HMENU) NULL, hinstance, window);
x, y, width, height,
(HWND) NULL,
(HMENU) NULL,
hinstance,
window
);
if (!priv->internal_win_id) if (!priv->internal_win_id) {
{
g_debug ("failed to create gl window: %d\n", priv->internal_win_id); g_debug ("failed to create gl window: %d\n", priv->internal_win_id);
return NULL; return NULL;
} }
@ -206,36 +201,41 @@ gst_gl_window_error_quark (void)
} }
void void
gst_gl_window_set_external_window_id (GstGLWindow *window, guint64 id) gst_gl_window_set_external_window_id (GstGLWindow * window, guint64 id)
{ {
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
WNDPROC window_parent_proc = (WNDPROC) (guint64) GetWindowLongPtr((HWND)id, GWL_WNDPROC); WNDPROC window_parent_proc =
(WNDPROC) (guint64) GetWindowLongPtr ((HWND) id, GWL_WNDPROC);
RECT rect; RECT rect;
SetProp (priv->internal_win_id, "gl_window_parent_id", (HWND)id); SetProp (priv->internal_win_id, "gl_window_parent_id", (HWND) id);
SetProp ((HWND)id, "gl_window_id", priv->internal_win_id); SetProp ((HWND) id, "gl_window_id", priv->internal_win_id);
SetProp ((HWND)id, "gl_window_parent_proc", (WNDPROC) window_parent_proc); SetProp ((HWND) id, "gl_window_parent_proc", (WNDPROC) window_parent_proc);
SetWindowLongPtr ((HWND)id, GWL_WNDPROC, (DWORD) (guint64) sub_class_proc); SetWindowLongPtr ((HWND) id, GWL_WNDPROC, (DWORD) (guint64) sub_class_proc);
SetWindowLongPtr (priv->internal_win_id, GWL_STYLE, WS_CHILD | WS_MAXIMIZE); SetWindowLongPtr (priv->internal_win_id, GWL_STYLE, WS_CHILD | WS_MAXIMIZE);
SetParent (priv->internal_win_id, (HWND)id); SetParent (priv->internal_win_id, (HWND) id);
//take changes into account: SWP_FRAMECHANGED //take changes into account: SWP_FRAMECHANGED
GetClientRect ((HWND)id, &rect); GetClientRect ((HWND) id, &rect);
SetWindowPos (priv->internal_win_id, HWND_TOP, rect.left, rect.top, rect.right, rect.bottom, SetWindowPos (priv->internal_win_id, HWND_TOP, rect.left, rect.top,
SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE); rect.right, rect.bottom,
MoveWindow (priv->internal_win_id, rect.left, rect.top, rect.right, rect.bottom, FALSE); SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
SWP_FRAMECHANGED | SWP_NOACTIVATE);
MoveWindow (priv->internal_win_id, rect.left, rect.top, rect.right,
rect.bottom, FALSE);
} }
void void
gst_gl_window_set_external_gl_context (GstGLWindow *window, guint64 context) gst_gl_window_set_external_gl_context (GstGLWindow * window, guint64 context)
{ {
g_warning ("gst_gl_window_set_external_gl_context: not implemented\n"); g_warning ("gst_gl_window_set_external_gl_context: not implemented\n");
} }
/* Must be called in the gl thread */ /* Must be called in the gl thread */
void void
gst_gl_window_set_draw_callback (GstGLWindow *window, GstGLWindowCB callback, gpointer data) gst_gl_window_set_draw_callback (GstGLWindow * window, GstGLWindowCB callback,
gpointer data)
{ {
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
@ -245,7 +245,8 @@ gst_gl_window_set_draw_callback (GstGLWindow *window, GstGLWindowCB callback, gp
/* Must be called in the gl thread */ /* Must be called in the gl thread */
void void
gst_gl_window_set_resize_callback (GstGLWindow *window, GstGLWindowCB2 callback , gpointer data) gst_gl_window_set_resize_callback (GstGLWindow * window,
GstGLWindowCB2 callback, gpointer data)
{ {
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
@ -255,7 +256,8 @@ gst_gl_window_set_resize_callback (GstGLWindow *window, GstGLWindowCB2 callback
/* Must be called in the gl thread */ /* Must be called in the gl thread */
void void
gst_gl_window_set_close_callback (GstGLWindow *window, GstGLWindowCB callback, gpointer data) gst_gl_window_set_close_callback (GstGLWindow * window, GstGLWindowCB callback,
gpointer data)
{ {
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
@ -264,29 +266,28 @@ gst_gl_window_set_close_callback (GstGLWindow *window, GstGLWindowCB callback, g
} }
void void
gst_gl_window_draw_unlocked (GstGLWindow *window) gst_gl_window_draw_unlocked (GstGLWindow * window)
{ {
gst_gl_window_draw (window); gst_gl_window_draw (window);
} }
/* Thread safe */ /* Thread safe */
void void
gst_gl_window_draw (GstGLWindow *window) gst_gl_window_draw (GstGLWindow * window)
{ {
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
if (!priv->visible) if (!priv->visible) {
{
ShowWindowAsync (priv->internal_win_id, SW_SHOW); ShowWindowAsync (priv->internal_win_id, SW_SHOW);
priv->visible = TRUE; priv->visible = TRUE;
} }
RedrawWindow (priv->internal_win_id, NULL, NULL, RedrawWindow (priv->internal_win_id, NULL, NULL,
RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE); RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE);
} }
void void
gst_gl_window_run_loop (GstGLWindow *window) gst_gl_window_run_loop (GstGLWindow * window)
{ {
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
gboolean running = TRUE; gboolean running = TRUE;
@ -295,18 +296,14 @@ gst_gl_window_run_loop (GstGLWindow *window)
g_debug ("begin loop\n"); g_debug ("begin loop\n");
while (running && (bRet = GetMessage (&msg, NULL, 0, 0)) != 0) while (running && (bRet = GetMessage (&msg, NULL, 0, 0)) != 0) {
{ if (bRet == -1) {
if (bRet == -1) g_error ("Failed to get message %x\r\n", GetLastError ());
{ running = FALSE;
g_error ("Failed to get message %x\r\n", GetLastError()); } else {
running = FALSE; TranslateMessage (&msg);
} DispatchMessage (&msg);
else }
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
} }
g_debug ("end loop\n"); g_debug ("end loop\n");
@ -314,12 +311,13 @@ gst_gl_window_run_loop (GstGLWindow *window)
/* Thread safe */ /* Thread safe */
void void
gst_gl_window_quit_loop (GstGLWindow *window, GstGLWindowCB callback, gpointer data) gst_gl_window_quit_loop (GstGLWindow * window, GstGLWindowCB callback,
gpointer data)
{ {
if (window) if (window) {
{
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
LRESULT res = PostMessage(priv->internal_win_id, WM_GST_GL_WINDOW_QUIT, (WPARAM) data, (LPARAM) callback); LRESULT res = PostMessage (priv->internal_win_id, WM_GST_GL_WINDOW_QUIT,
(WPARAM) data, (LPARAM) callback);
g_assert (SUCCEEDED (res)); g_assert (SUCCEEDED (res));
g_debug ("end loop requested\n"); g_debug ("end loop requested\n");
} }
@ -327,12 +325,13 @@ gst_gl_window_quit_loop (GstGLWindow *window, GstGLWindowCB callback, gpointer d
/* Thread safe */ /* Thread safe */
void void
gst_gl_window_send_message (GstGLWindow *window, GstGLWindowCB callback, gpointer data) gst_gl_window_send_message (GstGLWindow * window, GstGLWindowCB callback,
gpointer data)
{ {
if (window) if (window) {
{
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
LRESULT res = SendMessage (priv->internal_win_id, WM_GST_GL_WINDOW_CUSTOM, (WPARAM) data, (LPARAM) callback); LRESULT res = SendMessage (priv->internal_win_id, WM_GST_GL_WINDOW_CUSTOM,
(WPARAM) data, (LPARAM) callback);
g_assert (SUCCEEDED (res)); g_assert (SUCCEEDED (res));
} }
} }
@ -340,56 +339,58 @@ gst_gl_window_send_message (GstGLWindow *window, GstGLWindowCB callback, gpointe
/* PRIVATE */ /* PRIVATE */
void void
gst_gl_window_set_pixel_format (GstGLWindow *window) gst_gl_window_set_pixel_format (GstGLWindow * window)
{ {
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
PIXELFORMATDESCRIPTOR pfd; PIXELFORMATDESCRIPTOR pfd;
gint pixelformat = 0; gint pixelformat = 0;
gboolean res = FALSE; gboolean res = FALSE;
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); pfd.nSize = sizeof (PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1; pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA; pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24; pfd.cColorBits = 24;
pfd.cRedBits = 0; pfd.cRedBits = 0;
pfd.cRedShift = 0; pfd.cRedShift = 0;
pfd.cGreenBits = 0; pfd.cGreenBits = 0;
pfd.cGreenShift = 0; pfd.cGreenShift = 0;
pfd.cBlueBits = 0; pfd.cBlueBits = 0;
pfd.cBlueShift = 0; pfd.cBlueShift = 0;
pfd.cAlphaBits = 0; pfd.cAlphaBits = 0;
pfd.cAlphaShift = 0; pfd.cAlphaShift = 0;
pfd.cAccumBits = 0; pfd.cAccumBits = 0;
pfd.cAccumRedBits = 0; pfd.cAccumRedBits = 0;
pfd.cAccumGreenBits = 0; pfd.cAccumGreenBits = 0;
pfd.cAccumBlueBits = 0; pfd.cAccumBlueBits = 0;
pfd.cAccumAlphaBits = 0; pfd.cAccumAlphaBits = 0;
pfd.cDepthBits = 32; pfd.cDepthBits = 32;
pfd.cStencilBits = 8; pfd.cStencilBits = 8;
pfd.cAuxBuffers = 0; pfd.cAuxBuffers = 0;
pfd.iLayerType = PFD_MAIN_PLANE; pfd.iLayerType = PFD_MAIN_PLANE;
pfd.bReserved = 0; pfd.bReserved = 0;
pfd.dwLayerMask = 0; pfd.dwLayerMask = 0;
pfd.dwVisibleMask = 0; pfd.dwVisibleMask = 0;
pfd.dwDamageMask = 0; pfd.dwDamageMask = 0;
pfd.cColorBits = (BYTE) GetDeviceCaps (priv->device, BITSPIXEL); pfd.cColorBits = (BYTE) GetDeviceCaps (priv->device, BITSPIXEL);
pixelformat = ChoosePixelFormat (priv->device, &pfd ); pixelformat = ChoosePixelFormat (priv->device, &pfd);
g_assert (pixelformat); g_assert (pixelformat);
res = SetPixelFormat (priv->device, pixelformat, &pfd); res = SetPixelFormat (priv->device, pixelformat, &pfd);
g_assert (res); g_assert (res);
} }
LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK
window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ {
if (uMsg == WM_CREATE) { if (uMsg == WM_CREATE) {
GstGLWindow *window = (GstGLWindow *) (((LPCREATESTRUCT) lParam)->lpCreateParams); GstGLWindow *window =
(GstGLWindow *) (((LPCREATESTRUCT) lParam)->lpCreateParams);
g_debug ("WM_CREATE\n"); g_debug ("WM_CREATE\n");
@ -403,20 +404,21 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
if (priv->gl_context) if (priv->gl_context)
g_debug ("gl context created: %d\n", priv->gl_context); g_debug ("gl context created: %d\n", priv->gl_context);
else else
g_debug ("failed to create glcontext %d, %x\r\n", hWnd, GetLastError()); g_debug ("failed to create glcontext %d, %x\r\n", hWnd,
GetLastError ());
g_assert (priv->gl_context); g_assert (priv->gl_context);
ReleaseDC (hWnd, priv->device); ReleaseDC (hWnd, priv->device);
if (!wglMakeCurrent (priv->device, priv->gl_context)) if (!wglMakeCurrent (priv->device, priv->gl_context))
g_debug ("failed to make opengl context current %d, %x\r\n", hWnd, GetLastError()); g_debug ("failed to make opengl context current %d, %x\r\n", hWnd,
GetLastError ());
} }
SetProp (hWnd, "gl_window", window); SetProp (hWnd, "gl_window", window);
return 0; return 0;
} } else if (GetProp (hWnd, "gl_window")) {
else if (GetProp(hWnd, "gl_window")) {
GstGLWindow *window = GetProp(hWnd, "gl_window"); GstGLWindow *window = GetProp (hWnd, "gl_window");
GstGLWindowPrivate *priv = NULL; GstGLWindowPrivate *priv = NULL;
g_assert (window); g_assert (window);
@ -427,21 +429,20 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
g_assert (priv->internal_win_id == hWnd); g_assert (priv->internal_win_id == hWnd);
g_assert (priv->gl_context == wglGetCurrentContext()); g_assert (priv->gl_context == wglGetCurrentContext ());
switch ( uMsg ) { switch (uMsg) {
case WM_SIZE: case WM_SIZE:
{ {
if (priv->resize_cb) if (priv->resize_cb)
priv->resize_cb (priv->resize_data, LOWORD(lParam), HIWORD(lParam)); priv->resize_cb (priv->resize_data, LOWORD (lParam), HIWORD (lParam));
break; break;
} }
case WM_PAINT: case WM_PAINT:
{ {
if (priv->draw_cb) if (priv->draw_cb) {
{
PAINTSTRUCT ps; PAINTSTRUCT ps;
BeginPaint (hWnd, &ps); BeginPaint (hWnd, &ps);
priv->draw_cb (priv->draw_data); priv->draw_cb (priv->draw_data);
@ -456,14 +457,14 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
ShowWindowAsync (priv->internal_win_id, SW_HIDE); ShowWindowAsync (priv->internal_win_id, SW_HIDE);
if (priv->close_cb) if (priv->close_cb)
priv->close_cb (priv->close_data); priv->close_cb (priv->close_data);
priv->draw_cb = NULL; priv->draw_cb = NULL;
priv->draw_data = NULL; priv->draw_data = NULL;
priv->resize_cb = NULL; priv->resize_cb = NULL;
priv->resize_data = NULL; priv->resize_data = NULL;
priv->close_cb = NULL; priv->close_cb = NULL;
priv->close_data = NULL; priv->close_data = NULL;
break; break;
} }
@ -477,13 +478,13 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
destroy_cb ((gpointer) wParam); destroy_cb ((gpointer) wParam);
parent_id = GetProp (hWnd, "gl_window_parent_id"); parent_id = GetProp (hWnd, "gl_window_parent_id");
if (parent_id) if (parent_id) {
{
WNDPROC parent_proc = GetProp (parent_id, "gl_window_parent_proc"); WNDPROC parent_proc = GetProp (parent_id, "gl_window_parent_proc");
g_assert (parent_proc); g_assert (parent_proc);
SetWindowLongPtr (parent_id, GWL_WNDPROC, (LONG) (guint64) parent_proc); SetWindowLongPtr (parent_id, GWL_WNDPROC,
(LONG) (guint64) parent_proc);
SetParent (hWnd, NULL); SetParent (hWnd, NULL);
RemoveProp (parent_id, "gl_window_parent_proc"); RemoveProp (parent_id, "gl_window_parent_proc");
@ -494,19 +495,19 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
RemoveProp (hWnd, "gl_window"); RemoveProp (hWnd, "gl_window");
if (!wglMakeCurrent (NULL, NULL)) if (!wglMakeCurrent (NULL, NULL))
g_debug ("failed to make current %d, %x\r\n", hWnd, GetLastError()); g_debug ("failed to make current %d, %x\r\n", hWnd, GetLastError ());
if (priv->gl_context) if (priv->gl_context) {
{
if (!wglDeleteContext (priv->gl_context)) if (!wglDeleteContext (priv->gl_context))
g_debug ("failed to destroy context %d, %x\r\n", priv->gl_context, GetLastError()); g_debug ("failed to destroy context %d, %x\r\n", priv->gl_context,
GetLastError ());
} }
if (priv->internal_win_id) if (priv->internal_win_id) {
{
g_debug ("BEFORE\n"); g_debug ("BEFORE\n");
if (!DestroyWindow(priv->internal_win_id)) if (!DestroyWindow (priv->internal_win_id))
g_debug ("failed to destroy window %d, %x\r\n", hWnd, GetLastError()); g_debug ("failed to destroy window %d, %x\r\n", hWnd,
GetLastError ());
g_debug ("AFTER\n"); g_debug ("AFTER\n");
} }
@ -524,8 +525,7 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
case WM_GST_GL_WINDOW_CUSTOM: case WM_GST_GL_WINDOW_CUSTOM:
{ {
if (!priv->is_closed) if (!priv->is_closed) {
{
GstGLWindowCB custom_cb = (GstGLWindowCB) lParam; GstGLWindowCB custom_cb = (GstGLWindowCB) lParam;
custom_cb ((gpointer) wParam); custom_cb ((gpointer) wParam);
} }
@ -536,25 +536,23 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
return TRUE; return TRUE;
default: default:
return DefWindowProc( hWnd, uMsg, wParam, lParam ); return DefWindowProc (hWnd, uMsg, wParam, lParam);
} }
return 0; return 0;
} } else
else return DefWindowProc (hWnd, uMsg, wParam, lParam);
return DefWindowProc( hWnd, uMsg, wParam, lParam );
} }
LRESULT FAR PASCAL sub_class_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) LRESULT FAR PASCAL
sub_class_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ {
WNDPROC window_parent_proc = GetProp (hWnd, "gl_window_parent_proc"); WNDPROC window_parent_proc = GetProp (hWnd, "gl_window_parent_proc");
if (uMsg == WM_SIZE) if (uMsg == WM_SIZE) {
{
HWND gl_window_id = GetProp (hWnd, "gl_window_id"); HWND gl_window_id = GetProp (hWnd, "gl_window_id");
MoveWindow (gl_window_id, 0, 0, LOWORD(lParam), HIWORD(lParam), FALSE); MoveWindow (gl_window_id, 0, 0, LOWORD (lParam), HIWORD (lParam), FALSE);
} }
return CallWindowProc (window_parent_proc, hWnd, uMsg, wParam, lParam); return CallWindowProc (window_parent_proc, hWnd, uMsg, wParam, lParam);
} }

View file

@ -119,14 +119,14 @@ gst_gl_window_finalize (GObject * object)
XSync (priv->device, FALSE); XSync (priv->device, FALSE);
while(XPending (priv->device)) while (XPending (priv->device))
XNextEvent (priv->device, &event); XNextEvent (priv->device, &event);
XSetCloseDownMode (priv->device, DestroyAll); XSetCloseDownMode (priv->device, DestroyAll);
/*XAddToSaveSet (display, w) /*XAddToSaveSet (display, w)
Display *display; Display *display;
Window w;*/ Window w; */
//FIXME: it seems it causes destroy all created windows, even by other display connection: //FIXME: it seems it causes destroy all created windows, even by other display connection:
//This is case in: gst-launch-0.10 videotestsrc ! tee name=t t. ! queue ! glimagesink t. ! queue ! glimagesink //This is case in: gst-launch-0.10 videotestsrc ! tee name=t t. ! queue ! glimagesink t. ! queue ! glimagesink
@ -142,16 +142,14 @@ gst_gl_window_finalize (GObject * object)
g_debug ("display sender closed\n"); g_debug ("display sender closed\n");
if (priv->cond_send_message) if (priv->cond_send_message) {
{
g_cond_free (priv->cond_send_message); g_cond_free (priv->cond_send_message);
priv->cond_send_message = NULL; priv->cond_send_message = NULL;
} }
g_mutex_unlock (priv->x_lock); g_mutex_unlock (priv->x_lock);
if (priv->x_lock) if (priv->x_lock) {
{
g_mutex_free (priv->x_lock); g_mutex_free (priv->x_lock);
priv->x_lock = NULL; priv->x_lock = NULL;
} }
@ -206,8 +204,8 @@ gst_gl_window_get_property (GObject * object, guint prop_id,
} }
static void static void
gst_gl_window_log_handler (const gchar *domain, GLogLevelFlags flags, gst_gl_window_log_handler (const gchar * domain, GLogLevelFlags flags,
const gchar *message, gpointer user_data) const gchar * message, gpointer user_data)
{ {
if (_gst_gl_window_debug) { if (_gst_gl_window_debug) {
g_log_default_handler (domain, flags, message, user_data); g_log_default_handler (domain, flags, message, user_data);
@ -231,7 +229,7 @@ gst_gl_window_class_init (GstGLWindowClass * klass)
} }
static void static void
gst_gl_window_init (GstGLWindow *window) gst_gl_window_init (GstGLWindow * window)
{ {
window->priv = GST_GL_WINDOW_GET_PRIVATE (window); window->priv = GST_GL_WINDOW_GET_PRIVATE (window);
@ -239,7 +237,7 @@ gst_gl_window_init (GstGLWindow *window)
_gst_gl_window_debug = TRUE; _gst_gl_window_debug = TRUE;
g_log_set_handler ("GstGLWindow", G_LOG_LEVEL_DEBUG, g_log_set_handler ("GstGLWindow", G_LOG_LEVEL_DEBUG,
gst_gl_window_log_handler, NULL); gst_gl_window_log_handler, NULL);
} }
/* Must be called in the gl thread */ /* Must be called in the gl thread */
@ -270,7 +268,7 @@ gst_gl_window_new (gint width, gint height)
static gint x = 0; static gint x = 0;
static gint y = 0; static gint y = 0;
setlocale(LC_NUMERIC, "C"); setlocale (LC_NUMERIC, "C");
priv->x_lock = g_mutex_new (); priv->x_lock = g_mutex_new ();
priv->cond_send_message = g_cond_new (); priv->cond_send_message = g_cond_new ();
@ -314,8 +312,7 @@ gst_gl_window_new (gint width, gint height)
priv->visual_info = glXChooseVisual (priv->device, priv->screen_num, attrib); priv->visual_info = glXChooseVisual (priv->device, priv->screen_num, attrib);
if (!priv->visual_info) if (!priv->visual_info) {
{
g_warning ("glx visual is null (bad attributes)\n"); g_warning ("glx visual is null (bad attributes)\n");
return NULL; return NULL;
} }
@ -326,7 +323,8 @@ gst_gl_window_new (gint width, gint height)
if (priv->visual_info->class == TrueColor) if (priv->visual_info->class == TrueColor)
g_debug ("visual is using TrueColor\n"); g_debug ("visual is using TrueColor\n");
g_debug ("visual ID: %d\n", (gint)XVisualIDFromVisual(priv->visual_info->visual)); g_debug ("visual ID: %d\n",
(gint) XVisualIDFromVisual (priv->visual_info->visual));
g_debug ("visual info screen: %d\n", priv->visual_info->screen); g_debug ("visual info screen: %d\n", priv->visual_info->screen);
g_debug ("visual info visualid: %d\n", (gint) priv->visual_info->visualid); g_debug ("visual info visualid: %d\n", (gint) priv->visual_info->visualid);
g_debug ("visual info depth: %d\n", priv->visual_info->depth); g_debug ("visual info depth: %d\n", priv->visual_info->depth);
@ -336,20 +334,23 @@ gst_gl_window_new (gint width, gint height)
g_debug ("visual info blue_mask: %ld\n", priv->visual_info->blue_mask); g_debug ("visual info blue_mask: %ld\n", priv->visual_info->blue_mask);
g_debug ("visual info bits_per_rgb: %d\n", priv->visual_info->bits_per_rgb); g_debug ("visual info bits_per_rgb: %d\n", priv->visual_info->bits_per_rgb);
win_attr.event_mask = StructureNotifyMask | ExposureMask | VisibilityChangeMask; win_attr.event_mask =
StructureNotifyMask | ExposureMask | VisibilityChangeMask;
win_attr.do_not_propagate_mask = NoEventMask; win_attr.do_not_propagate_mask = NoEventMask;
win_attr.background_pixmap = None; win_attr.background_pixmap = None;
win_attr.background_pixel = 0; win_attr.background_pixel = 0;
win_attr.border_pixel = 0; win_attr.border_pixel = 0;
win_attr.colormap = XCreateColormap(priv->device, priv->root, priv->visual_info->visual, AllocNone); win_attr.colormap =
XCreateColormap (priv->device, priv->root, priv->visual_info->visual,
AllocNone);
mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask; mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
priv->internal_win_id = XCreateWindow (priv->device, priv->root, x, y, priv->internal_win_id = XCreateWindow (priv->device, priv->root, x, y,
width, height, 0, priv->visual_info->depth, InputOutput, width, height, 0, priv->visual_info->depth, InputOutput,
priv->visual_info->visual, mask, &win_attr); priv->visual_info->visual, mask, &win_attr);
x += 20; x += 20;
y += 20; y += 20;
@ -358,7 +359,8 @@ gst_gl_window_new (gint width, gint height)
XSetWindowBackgroundPixmap (priv->device, priv->internal_win_id, None); XSetWindowBackgroundPixmap (priv->device, priv->internal_win_id, None);
g_debug ("gl window id: %" G_GUINT64_FORMAT "\n", (guint64) priv->internal_win_id); g_debug ("gl window id: %" G_GUINT64_FORMAT "\n",
(guint64) priv->internal_win_id);
g_debug ("gl window props: x:%d y:%d w:%d h:%d\n", x, y, width, height); g_debug ("gl window props: x:%d y:%d w:%d h:%d\n", x, y, width, height);
@ -376,21 +378,22 @@ gst_gl_window_new (gint width, gint height)
XSetWMProtocols (priv->device, priv->internal_win_id, wm_atoms, 2); XSetWMProtocols (priv->device, priv->internal_win_id, wm_atoms, 2);
priv->gl_context = glXCreateContext (priv->device, priv->visual_info, NULL, TRUE); priv->gl_context =
glXCreateContext (priv->device, priv->visual_info, NULL, TRUE);
g_debug ("gl context id: %ld\n", (gulong) priv->gl_context); g_debug ("gl context id: %ld\n", (gulong) priv->gl_context);
if (!glXIsDirect(priv->device, priv->gl_context)) if (!glXIsDirect (priv->device, priv->gl_context))
g_debug ("direct rendering failed\n"); g_debug ("direct rendering failed\n");
wm_hints.flags = StateHint; wm_hints.flags = StateHint;
wm_hints.initial_state = NormalState; wm_hints.initial_state = NormalState;
wm_hints.input = False; wm_hints.input = False;
XStringListToTextProperty ((char**)&title, 1, &text_property); XStringListToTextProperty ((char **) &title, 1, &text_property);
XSetWMProperties (priv->device, priv->internal_win_id, &text_property, &text_property, 0, 0, XSetWMProperties (priv->device, priv->internal_win_id, &text_property,
NULL, &wm_hints, NULL); &text_property, 0, 0, NULL, &wm_hints, NULL);
XFree (text_property.value); XFree (text_property.value);
@ -417,10 +420,9 @@ gst_gl_window_error_quark (void)
/* Not called by the gl thread */ /* Not called by the gl thread */
void void
gst_gl_window_set_external_window_id (GstGLWindow *window, guint64 id) gst_gl_window_set_external_window_id (GstGLWindow * window, guint64 id)
{ {
if (window) if (window) {
{
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
XWindowAttributes attr; XWindowAttributes attr;
@ -432,9 +434,11 @@ gst_gl_window_set_external_window_id (GstGLWindow *window, guint64 id)
XGetWindowAttributes (priv->disp_send, priv->parent, &attr); XGetWindowAttributes (priv->disp_send, priv->parent, &attr);
XResizeWindow (priv->disp_send, priv->internal_win_id, attr.width, attr.height); XResizeWindow (priv->disp_send, priv->internal_win_id, attr.width,
attr.height);
XReparentWindow (priv->disp_send, priv->internal_win_id, priv->parent, attr.x, attr.y); XReparentWindow (priv->disp_send, priv->internal_win_id, priv->parent,
attr.x, attr.y);
XSync (priv->disp_send, FALSE); XSync (priv->disp_send, FALSE);
@ -443,13 +447,14 @@ gst_gl_window_set_external_window_id (GstGLWindow *window, guint64 id)
} }
void void
gst_gl_window_set_external_gl_context (GstGLWindow *window, guint64 context) gst_gl_window_set_external_gl_context (GstGLWindow * window, guint64 context)
{ {
g_warning ("gst_gl_window_set_external_gl_context: not implemented\n"); g_warning ("gst_gl_window_set_external_gl_context: not implemented\n");
} }
void void
gst_gl_window_set_draw_callback (GstGLWindow *window, GstGLWindowCB callback, gpointer data) gst_gl_window_set_draw_callback (GstGLWindow * window, GstGLWindowCB callback,
gpointer data)
{ {
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
@ -462,7 +467,8 @@ gst_gl_window_set_draw_callback (GstGLWindow *window, GstGLWindowCB callback, gp
} }
void void
gst_gl_window_set_resize_callback (GstGLWindow *window, GstGLWindowCB2 callback , gpointer data) gst_gl_window_set_resize_callback (GstGLWindow * window,
GstGLWindowCB2 callback, gpointer data)
{ {
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
@ -475,7 +481,8 @@ gst_gl_window_set_resize_callback (GstGLWindow *window, GstGLWindowCB2 callback
} }
void void
gst_gl_window_set_close_callback (GstGLWindow *window, GstGLWindowCB callback, gpointer data) gst_gl_window_set_close_callback (GstGLWindow * window, GstGLWindowCB callback,
gpointer data)
{ {
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
@ -489,12 +496,11 @@ gst_gl_window_set_close_callback (GstGLWindow *window, GstGLWindowCB callback, g
/* Called in the gl thread */ /* Called in the gl thread */
void void
gst_gl_window_draw_unlocked (GstGLWindow *window) gst_gl_window_draw_unlocked (GstGLWindow * window)
{ {
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
if (priv->running && priv->allow_extra_expose_events) if (priv->running && priv->allow_extra_expose_events) {
{
XEvent event; XEvent event;
XWindowAttributes attr; XWindowAttributes attr;
@ -510,44 +516,42 @@ gst_gl_window_draw_unlocked (GstGLWindow *window)
event.xexpose.height = attr.height; event.xexpose.height = attr.height;
event.xexpose.count = 0; event.xexpose.count = 0;
XSendEvent (priv->device, priv->internal_win_id, FALSE, ExposureMask, &event); XSendEvent (priv->device, priv->internal_win_id, FALSE, ExposureMask,
&event);
XSync (priv->disp_send, FALSE); XSync (priv->disp_send, FALSE);
} }
} }
/* Not called by the gl thread */ /* Not called by the gl thread */
void void
gst_gl_window_draw (GstGLWindow *window) gst_gl_window_draw (GstGLWindow * window)
{ {
if (window) if (window) {
{
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
g_mutex_lock (priv->x_lock); g_mutex_lock (priv->x_lock);
if (priv->running) if (priv->running) {
{
XEvent event; XEvent event;
XWindowAttributes attr; XWindowAttributes attr;
if (!priv->visible) if (!priv->visible) {
{
XMapWindow (priv->disp_send, priv->internal_win_id); XMapWindow (priv->disp_send, priv->internal_win_id);
priv->visible = TRUE; priv->visible = TRUE;
} }
XGetWindowAttributes (priv->disp_send, priv->internal_win_id, &attr); XGetWindowAttributes (priv->disp_send, priv->internal_win_id, &attr);
if (priv->parent) if (priv->parent) {
{
XWindowAttributes attr_parent; XWindowAttributes attr_parent;
XGetWindowAttributes (priv->disp_send, priv->parent, &attr_parent); XGetWindowAttributes (priv->disp_send, priv->parent, &attr_parent);
if (attr.x != attr_parent.x || attr.y != attr_parent.y || if (attr.x != attr_parent.x || attr.y != attr_parent.y ||
attr.width != attr_parent.width || attr.height != attr_parent.height) attr.width != attr_parent.width
{ || attr.height != attr_parent.height) {
XMoveResizeWindow (priv->disp_send, priv->internal_win_id, attr_parent.x, attr_parent.y, XMoveResizeWindow (priv->disp_send, priv->internal_win_id,
attr_parent.width, attr_parent.height); attr_parent.x, attr_parent.y, attr_parent.width,
attr_parent.height);
XSync (priv->disp_send, FALSE); XSync (priv->disp_send, FALSE);
attr.x = attr_parent.x; attr.x = attr_parent.x;
@ -556,8 +560,8 @@ gst_gl_window_draw (GstGLWindow *window)
attr.width = attr_parent.width; attr.width = attr_parent.width;
attr.height = attr_parent.height; attr.height = attr_parent.height;
g_debug ("parent resize: %d, %d, %d, %d\n", attr_parent.x, attr_parent.y, g_debug ("parent resize: %d, %d, %d, %d\n", attr_parent.x,
attr_parent.width, attr_parent.height); attr_parent.y, attr_parent.width, attr_parent.height);
} }
} }
@ -571,7 +575,8 @@ gst_gl_window_draw (GstGLWindow *window)
event.xexpose.height = attr.height; event.xexpose.height = attr.height;
event.xexpose.count = 0; event.xexpose.count = 0;
XSendEvent (priv->disp_send, priv->internal_win_id, FALSE, ExposureMask, &event); XSendEvent (priv->disp_send, priv->internal_win_id, FALSE, ExposureMask,
&event);
XSync (priv->disp_send, FALSE); XSync (priv->disp_send, FALSE);
} }
@ -581,7 +586,7 @@ gst_gl_window_draw (GstGLWindow *window)
/* Called in the gl thread */ /* Called in the gl thread */
void void
gst_gl_window_run_loop (GstGLWindow *window) gst_gl_window_run_loop (GstGLWindow * window)
{ {
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
@ -589,23 +594,21 @@ gst_gl_window_run_loop (GstGLWindow *window)
g_mutex_lock (priv->x_lock); g_mutex_lock (priv->x_lock);
while (priv->running) while (priv->running) {
{
XEvent event; XEvent event;
XEvent pending_event; XEvent pending_event;
g_mutex_unlock (priv->x_lock); g_mutex_unlock (priv->x_lock);
/* XSendEvent (which are called in other threads) are done from another display structure */ /* XSendEvent (which are called in other threads) are done from another display structure */
XNextEvent(priv->device, &event); XNextEvent (priv->device, &event);
g_mutex_lock (priv->x_lock); g_mutex_lock (priv->x_lock);
// use in generic/cube and other related uses // use in generic/cube and other related uses
priv->allow_extra_expose_events = XPending (priv->device) <= 2; priv->allow_extra_expose_events = XPending (priv->device) <= 2;
switch (event.type) switch (event.type) {
{
case ClientMessage: case ClientMessage:
{ {
@ -647,9 +650,10 @@ gst_gl_window_run_loop (GstGLWindow *window)
} }
/* User clicked on the cross */ /* User clicked on the cross */
else if (wm_delete != None && (Atom) event.xclient.data.l[0] == wm_delete) else if (wm_delete != None
{ && (Atom) event.xclient.data.l[0] == wm_delete) {
g_debug ("Close %" G_GUINT64_FORMAT "\n", (guint64) priv->internal_win_id); g_debug ("Close %" G_GUINT64_FORMAT "\n",
(guint64) priv->internal_win_id);
if (priv->close_cb) if (priv->close_cb)
priv->close_cb (priv->close_data); priv->close_cb (priv->close_data);
@ -679,7 +683,8 @@ gst_gl_window_run_loop (GstGLWindow *window)
gpointer destroy_data = (gpointer) event.xclient.data.l[1]; gpointer destroy_data = (gpointer) event.xclient.data.l[1];
#endif #endif
g_debug ("Quit loop message %" G_GUINT64_FORMAT "\n", (guint64) priv->internal_win_id); g_debug ("Quit loop message %" G_GUINT64_FORMAT "\n",
(guint64) priv->internal_win_id);
/* exit loop */ /* exit loop */
priv->running = FALSE; priv->running = FALSE;
@ -716,9 +721,8 @@ gst_gl_window_run_loop (GstGLWindow *window)
destroy_cb (destroy_data); destroy_cb (destroy_data);
} } else
else g_debug ("client message not reconized \n");
g_debug("client message not reconized \n");
break; break;
} }
@ -726,7 +730,8 @@ gst_gl_window_run_loop (GstGLWindow *window)
case ConfigureNotify: case ConfigureNotify:
{ {
if (priv->resize_cb) if (priv->resize_cb)
priv->resize_cb (priv->resize_data, event.xconfigure.width, event.xconfigure.height); priv->resize_cb (priv->resize_data, event.xconfigure.width,
event.xconfigure.height);
break; break;
} }
@ -735,18 +740,16 @@ gst_gl_window_run_loop (GstGLWindow *window)
break; break;
case Expose: case Expose:
if (priv->draw_cb) if (priv->draw_cb) {
{
priv->draw_cb (priv->draw_data); priv->draw_cb (priv->draw_data);
glFlush(); glFlush ();
glXSwapBuffers (priv->device, priv->internal_win_id); glXSwapBuffers (priv->device, priv->internal_win_id);
} }
break; break;
case VisibilityNotify: case VisibilityNotify:
{ {
switch (event.xvisibility.state) switch (event.xvisibility.state) {
{
case VisibilityUnobscured: case VisibilityUnobscured:
if (priv->draw_cb) if (priv->draw_cb)
priv->draw_cb (priv->draw_data); priv->draw_cb (priv->draw_data);
@ -761,7 +764,8 @@ gst_gl_window_run_loop (GstGLWindow *window)
break; break;
default: default:
g_debug("unknown xvisibility event: %d\n", event.xvisibility.state); g_debug ("unknown xvisibility event: %d\n",
event.xvisibility.state);
break; break;
} }
break; break;
@ -771,9 +775,9 @@ gst_gl_window_run_loop (GstGLWindow *window)
g_debug ("unknow\n"); g_debug ("unknow\n");
break; break;
}// switch } // switch
}// while running } // while running
g_mutex_unlock (priv->x_lock); g_mutex_unlock (priv->x_lock);
@ -782,23 +786,23 @@ gst_gl_window_run_loop (GstGLWindow *window)
/* Not called by the gl thread */ /* Not called by the gl thread */
void void
gst_gl_window_quit_loop (GstGLWindow *window, GstGLWindowCB callback, gpointer data) gst_gl_window_quit_loop (GstGLWindow * window, GstGLWindowCB callback,
gpointer data)
{ {
if (window) if (window) {
{
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
g_mutex_lock (priv->x_lock); g_mutex_lock (priv->x_lock);
if (priv->running) if (priv->running) {
{
XEvent event; XEvent event;
event.xclient.type = ClientMessage; event.xclient.type = ClientMessage;
event.xclient.send_event = TRUE; event.xclient.send_event = TRUE;
event.xclient.display = priv->disp_send; event.xclient.display = priv->disp_send;
event.xclient.window = priv->internal_win_id; event.xclient.window = priv->internal_win_id;
event.xclient.message_type = XInternAtom (priv->disp_send, "WM_QUIT_LOOP", True);; event.xclient.message_type =
XInternAtom (priv->disp_send, "WM_QUIT_LOOP", True);;
event.xclient.format = 32; event.xclient.format = 32;
#if SIZEOF_VOID_P == 8 #if SIZEOF_VOID_P == 8
event.xclient.data.l[0] = (((long) callback) >> 32) & 0xffffffff; event.xclient.data.l[0] = (((long) callback) >> 32) & 0xffffffff;
@ -810,7 +814,8 @@ gst_gl_window_quit_loop (GstGLWindow *window, GstGLWindowCB callback, gpointer d
event.xclient.data.l[1] = (long) data; event.xclient.data.l[1] = (long) data;
#endif #endif
XSendEvent (priv->disp_send, priv->internal_win_id, FALSE, NoEventMask, &event); XSendEvent (priv->disp_send, priv->internal_win_id, FALSE, NoEventMask,
&event);
XSync (priv->disp_send, FALSE); XSync (priv->disp_send, FALSE);
} }
@ -820,23 +825,23 @@ gst_gl_window_quit_loop (GstGLWindow *window, GstGLWindowCB callback, gpointer d
/* Not called by the gl thread */ /* Not called by the gl thread */
void void
gst_gl_window_send_message (GstGLWindow *window, GstGLWindowCB callback, gpointer data) gst_gl_window_send_message (GstGLWindow * window, GstGLWindowCB callback,
gpointer data)
{ {
if (window) if (window) {
{
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
g_mutex_lock (priv->x_lock); g_mutex_lock (priv->x_lock);
if (priv->running) if (priv->running) {
{
XEvent event; XEvent event;
event.xclient.type = ClientMessage; event.xclient.type = ClientMessage;
event.xclient.send_event = TRUE; event.xclient.send_event = TRUE;
event.xclient.display = priv->disp_send; event.xclient.display = priv->disp_send;
event.xclient.window = priv->internal_win_id; event.xclient.window = priv->internal_win_id;
event.xclient.message_type = XInternAtom (priv->disp_send, "WM_GL_WINDOW", True); event.xclient.message_type =
XInternAtom (priv->disp_send, "WM_GL_WINDOW", True);
event.xclient.format = 32; event.xclient.format = 32;
#if SIZEOF_VOID_P == 8 #if SIZEOF_VOID_P == 8
event.xclient.data.l[0] = (((long) callback) >> 32) & 0xffffffff; event.xclient.data.l[0] = (((long) callback) >> 32) & 0xffffffff;
@ -848,7 +853,8 @@ gst_gl_window_send_message (GstGLWindow *window, GstGLWindowCB callback, gpointe
event.xclient.data.l[1] = (long) data; event.xclient.data.l[1] = (long) data;
#endif #endif
XSendEvent (priv->disp_send, priv->internal_win_id, FALSE, NoEventMask, &event); XSendEvent (priv->disp_send, priv->internal_win_id, FALSE, NoEventMask,
&event);
XSync (priv->disp_send, FALSE); XSync (priv->disp_send, FALSE);
/* block until opengl calls have been executed in the gl thread */ /* block until opengl calls have been executed in the gl thread */

View file

@ -21,44 +21,45 @@
#include <gstgleffects.h> #include <gstgleffects.h>
static void static void
gst_gl_effects_bulge_callback (gint width, gint height, guint texture, gpointer data) gst_gl_effects_bulge_callback (gint width, gint height, guint texture,
gpointer data)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (data); GstGLEffects *effects = GST_GL_EFFECTS (data);
GstGLShader *shader; GstGLShader *shader;
shader = g_hash_table_lookup (effects->shaderstable, "bulge0"); shader = g_hash_table_lookup (effects->shaderstable, "bulge0");
if (!shader) { if (!shader) {
shader = gst_gl_shader_new (); shader = gst_gl_shader_new ();
g_hash_table_insert (effects->shaderstable, "bulge0", shader); g_hash_table_insert (effects->shaderstable, "bulge0", shader);
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (shader,
gst_gl_shader_compile_and_check (shader, bulge_fragment_source, bulge_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
gst_gl_shader_use (shader); gst_gl_shader_use (shader);
glActiveTexture (GL_TEXTURE0); glActiveTexture (GL_TEXTURE0);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
gst_gl_shader_set_uniform_1i (shader, "tex", 0); gst_gl_shader_set_uniform_1i (shader, "tex", 0);
gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f); gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f);
gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f); gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f);
gst_gl_effects_draw_texture (effects, texture); gst_gl_effects_draw_texture (effects, texture);
} }
void void
gst_gl_effects_bulge (GstGLEffects *effects) { gst_gl_effects_bulge (GstGLEffects * effects)
{
GstGLFilter *filter = GST_GL_FILTER (effects); GstGLFilter *filter = GST_GL_FILTER (effects);
gst_gl_filter_render_to_target (filter, effects->intexture, effects->outtexture, gst_gl_filter_render_to_target (filter, effects->intexture,
gst_gl_effects_bulge_callback, effects); effects->outtexture, gst_gl_effects_bulge_callback, effects);
} }

View file

@ -21,44 +21,45 @@
#include <gstgleffects.h> #include <gstgleffects.h>
static void static void
gst_gl_effects_fisheye_callback (gint width, gint height, guint texture, gpointer data) gst_gl_effects_fisheye_callback (gint width, gint height, guint texture,
gpointer data)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (data); GstGLEffects *effects = GST_GL_EFFECTS (data);
GstGLShader *shader; GstGLShader *shader;
shader = g_hash_table_lookup (effects->shaderstable, "fisheye0"); shader = g_hash_table_lookup (effects->shaderstable, "fisheye0");
if (!shader) { if (!shader) {
shader = gst_gl_shader_new (); shader = gst_gl_shader_new ();
g_hash_table_insert (effects->shaderstable, "fisheye0", shader); g_hash_table_insert (effects->shaderstable, "fisheye0", shader);
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (shader,
gst_gl_shader_compile_and_check (shader, fisheye_fragment_source, fisheye_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
gst_gl_shader_use (shader); gst_gl_shader_use (shader);
glActiveTexture (GL_TEXTURE0); glActiveTexture (GL_TEXTURE0);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
gst_gl_shader_set_uniform_1i (shader, "tex", 0); gst_gl_shader_set_uniform_1i (shader, "tex", 0);
gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f); gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f);
gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f); gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f);
gst_gl_effects_draw_texture (effects, texture); gst_gl_effects_draw_texture (effects, texture);
} }
void void
gst_gl_effects_fisheye (GstGLEffects *effects) { gst_gl_effects_fisheye (GstGLEffects * effects)
{
GstGLFilter *filter = GST_GL_FILTER (effects); GstGLFilter *filter = GST_GL_FILTER (effects);
gst_gl_filter_render_to_target (filter, effects->intexture, effects->outtexture, gst_gl_filter_render_to_target (filter, effects->intexture,
gst_gl_effects_fisheye_callback, effects); effects->outtexture, gst_gl_effects_fisheye_callback, effects);
} }

View file

@ -20,61 +20,62 @@
#include <gstgleffects.h> #include <gstgleffects.h>
static gfloat gauss_kernel[9] = { 0.060493f, 0.075284f, 0.088016f, static gfloat gauss_kernel[9] = { 0.060493f, 0.075284f, 0.088016f,
0.096667f, 0.099736f, 0.096667f, 0.096667f, 0.099736f, 0.096667f,
0.088016f, 0.075284f, 0.060493f }; 0.088016f, 0.075284f, 0.060493f
};
static void static void
gst_gl_effects_glow_step_one (gint width, gint height, guint texture, gpointer data) gst_gl_effects_glow_step_one (gint width, gint height, guint texture,
gpointer data)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (data); GstGLEffects *effects = GST_GL_EFFECTS (data);
GstGLShader *shader; GstGLShader *shader;
shader = g_hash_table_lookup (effects->shaderstable, "glow0"); shader = g_hash_table_lookup (effects->shaderstable, "glow0");
if (!shader) { if (!shader) {
shader = gst_gl_shader_new (); shader = gst_gl_shader_new ();
g_hash_table_insert (effects->shaderstable, "glow0", shader); g_hash_table_insert (effects->shaderstable, "glow0", shader);
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (shader,
gst_gl_shader_compile_and_check (shader, luma_threshold_fragment_source, luma_threshold_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
gst_gl_shader_use (shader); gst_gl_shader_use (shader);
glActiveTexture (GL_TEXTURE0); glActiveTexture (GL_TEXTURE0);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
gst_gl_shader_set_uniform_1i (shader, "tex", 0); gst_gl_shader_set_uniform_1i (shader, "tex", 0);
gst_gl_effects_draw_texture (effects, texture); gst_gl_effects_draw_texture (effects, texture);
} }
static void static void
gst_gl_effects_glow_step_two (gint width, gint height, guint texture, gpointer stuff) gst_gl_effects_glow_step_two (gint width, gint height, guint texture,
gpointer stuff)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (stuff); GstGLEffects *effects = GST_GL_EFFECTS (stuff);
GstGLShader *shader; GstGLShader *shader;
/* hard coded kernel, it could be easily generated at runtime with a /* hard coded kernel, it could be easily generated at runtime with a
* property to change standard deviation */ * property to change standard deviation */
shader = g_hash_table_lookup (effects->shaderstable, "glow1"); shader = g_hash_table_lookup (effects->shaderstable, "glow1");
if (!shader) { if (!shader) {
shader = gst_gl_shader_new (); shader = gst_gl_shader_new ();
g_hash_table_insert (effects->shaderstable, "glow1", shader); g_hash_table_insert (effects->shaderstable, "glow1", shader);
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (shader,
gst_gl_shader_compile_and_check (shader, hconv9_fragment_source, hconv9_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
@ -96,21 +97,21 @@ gst_gl_effects_glow_step_two (gint width, gint height, guint texture, gpointer s
} }
void void
gst_gl_effects_glow_step_three (gint width, gint height, guint texture, gpointer stuff) gst_gl_effects_glow_step_three (gint width, gint height, guint texture,
gpointer stuff)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (stuff); GstGLEffects *effects = GST_GL_EFFECTS (stuff);
GstGLShader *shader; GstGLShader *shader;
shader = g_hash_table_lookup (effects->shaderstable, "glow2"); shader = g_hash_table_lookup (effects->shaderstable, "glow2");
if (!shader) { if (!shader) {
shader = gst_gl_shader_new (); shader = gst_gl_shader_new ();
g_hash_table_insert (effects->shaderstable, "glow2", shader); g_hash_table_insert (effects->shaderstable, "glow2", shader);
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (shader,
gst_gl_shader_compile_and_check (shader, vconv9_fragment_source, vconv9_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
@ -132,21 +133,21 @@ gst_gl_effects_glow_step_three (gint width, gint height, guint texture, gpointer
} }
void void
gst_gl_effects_glow_step_four (gint width, gint height, guint texture, gpointer stuff) gst_gl_effects_glow_step_four (gint width, gint height, guint texture,
gpointer stuff)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (stuff); GstGLEffects *effects = GST_GL_EFFECTS (stuff);
GstGLShader *shader; GstGLShader *shader;
shader = g_hash_table_lookup (effects->shaderstable, "glow3"); shader = g_hash_table_lookup (effects->shaderstable, "glow3");
if (!shader) { if (!shader) {
shader = gst_gl_shader_new (); shader = gst_gl_shader_new ();
g_hash_table_insert (effects->shaderstable, "glow3", shader); g_hash_table_insert (effects->shaderstable, "glow3", shader);
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (shader,
gst_gl_shader_compile_and_check (shader, sum_fragment_source, sum_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
@ -156,35 +157,36 @@ gst_gl_effects_glow_step_four (gint width, gint height, guint texture, gpointer
glActiveTexture (GL_TEXTURE2); glActiveTexture (GL_TEXTURE2);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, effects->intexture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, effects->intexture);
glDisable(GL_TEXTURE_RECTANGLE_ARB); glDisable (GL_TEXTURE_RECTANGLE_ARB);
gst_gl_shader_set_uniform_1f (shader, "alpha", 1.0); gst_gl_shader_set_uniform_1f (shader, "alpha", 1.0);
gst_gl_shader_set_uniform_1i (shader, "base", 2); gst_gl_shader_set_uniform_1i (shader, "base", 2);
glActiveTexture (GL_TEXTURE1); glActiveTexture (GL_TEXTURE1);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
glDisable(GL_TEXTURE_RECTANGLE_ARB); glDisable (GL_TEXTURE_RECTANGLE_ARB);
gst_gl_shader_set_uniform_1f (shader, "beta", (gfloat) 1/3.5f); gst_gl_shader_set_uniform_1f (shader, "beta", (gfloat) 1 / 3.5f);
gst_gl_shader_set_uniform_1i (shader, "blend", 1); gst_gl_shader_set_uniform_1i (shader, "blend", 1);
gst_gl_effects_draw_texture (effects, texture); gst_gl_effects_draw_texture (effects, texture);
} }
void void
gst_gl_effects_glow (GstGLEffects *effects) { gst_gl_effects_glow (GstGLEffects * effects)
{
GstGLFilter *filter = GST_GL_FILTER (effects); GstGLFilter *filter = GST_GL_FILTER (effects);
/* threshold */ /* threshold */
gst_gl_filter_render_to_target (filter, effects->intexture, effects->midtexture[0], gst_gl_filter_render_to_target (filter, effects->intexture,
gst_gl_effects_glow_step_one, effects); effects->midtexture[0], gst_gl_effects_glow_step_one, effects);
/* blur */ /* blur */
gst_gl_filter_render_to_target (filter, effects->midtexture[0], effects->midtexture[1], gst_gl_filter_render_to_target (filter, effects->midtexture[0],
gst_gl_effects_glow_step_two, effects); effects->midtexture[1], gst_gl_effects_glow_step_two, effects);
gst_gl_filter_render_to_target (filter, effects->midtexture[1], effects->midtexture[2], gst_gl_filter_render_to_target (filter, effects->midtexture[1],
gst_gl_effects_glow_step_three, effects); effects->midtexture[2], gst_gl_effects_glow_step_three, effects);
/* add blurred luma to intexture */ /* add blurred luma to intexture */
gst_gl_filter_render_to_target (filter, effects->midtexture[2], effects->outtexture, gst_gl_filter_render_to_target (filter, effects->midtexture[2],
gst_gl_effects_glow_step_four, effects); effects->outtexture, gst_gl_effects_glow_step_four, effects);
} }

View file

@ -21,9 +21,10 @@
#include <gstgleffects.h> #include <gstgleffects.h>
static void static void
gst_gl_effects_identity_callback (gint width, gint height, guint texture, gpointer data) gst_gl_effects_identity_callback (gint width, gint height, guint texture,
gpointer data)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (data); GstGLEffects *effects = GST_GL_EFFECTS (data);
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
@ -32,9 +33,10 @@ gst_gl_effects_identity_callback (gint width, gint height, guint texture, gpoint
} }
void void
gst_gl_effects_identity (GstGLEffects *effects) { gst_gl_effects_identity (GstGLEffects * effects)
{
GstGLFilter *filter = GST_GL_FILTER (effects); GstGLFilter *filter = GST_GL_FILTER (effects);
gst_gl_filter_render_to_target (filter, effects->intexture, effects->outtexture, gst_gl_filter_render_to_target (filter, effects->intexture,
gst_gl_effects_identity_callback, effects); effects->outtexture, gst_gl_effects_identity_callback, effects);
} }

View file

@ -21,24 +21,22 @@
#include <gstgleffects.h> #include <gstgleffects.h>
#include <gstgleffectlumatocurve.h> #include <gstgleffectlumatocurve.h>
void gst_gl_effects_luma_to_curve (GstGLEffects *effects, void
GstGLEffectsCurve curve, gst_gl_effects_luma_to_curve (GstGLEffects * effects,
gint curve_index, GstGLEffectsCurve curve,
gint width, gint height, gint curve_index, gint width, gint height, GLuint texture)
GLuint texture)
{ {
GstGLShader *shader; GstGLShader *shader;
shader = g_hash_table_lookup (effects->shaderstable, "lumamap0"); shader = g_hash_table_lookup (effects->shaderstable, "lumamap0");
if (!shader) { if (!shader) {
shader = gst_gl_shader_new (); shader = gst_gl_shader_new ();
g_hash_table_insert (effects->shaderstable, "lumamap0", shader); g_hash_table_insert (effects->shaderstable, "lumamap0", shader);
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (shader,
gst_gl_shader_compile_and_check (shader, luma_to_curve_fragment_source, luma_to_curve_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
@ -47,20 +45,18 @@ void gst_gl_effects_luma_to_curve (GstGLEffects *effects,
if (effects->curve[curve_index] == 0) { if (effects->curve[curve_index] == 0) {
/* this parameters are needed to have a right, predictable, mapping */ /* this parameters are needed to have a right, predictable, mapping */
glGenTextures(1, &effects->curve[curve_index]); glGenTextures (1, &effects->curve[curve_index]);
glEnable(GL_TEXTURE_1D); glEnable (GL_TEXTURE_1D);
glBindTexture (GL_TEXTURE_1D, effects->curve[curve_index]); glBindTexture (GL_TEXTURE_1D, effects->curve[curve_index]);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage1D(GL_TEXTURE_1D, 0, curve.bytes_per_pixel, glTexImage1D (GL_TEXTURE_1D, 0, curve.bytes_per_pixel,
curve.width, 0, curve.width, 0, GL_RGB, GL_UNSIGNED_BYTE, curve.pixel_data);
GL_RGB, GL_UNSIGNED_BYTE,
curve.pixel_data); glDisable (GL_TEXTURE_1D);
glDisable(GL_TEXTURE_1D);
} }
glActiveTexture (GL_TEXTURE2); glActiveTexture (GL_TEXTURE2);
@ -78,55 +74,63 @@ void gst_gl_effects_luma_to_curve (GstGLEffects *effects,
gst_gl_shader_set_uniform_1i (shader, "curve", 1); gst_gl_shader_set_uniform_1i (shader, "curve", 1);
glDisable (GL_TEXTURE_1D); glDisable (GL_TEXTURE_1D);
gst_gl_effects_draw_texture (effects, texture); gst_gl_effects_draw_texture (effects, texture);
} }
static void gst_gl_effects_heat_callback (gint width, gint height, guint texture, gpointer data) static void
gst_gl_effects_heat_callback (gint width, gint height, guint texture,
gpointer data)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (data); GstGLEffects *effects = GST_GL_EFFECTS (data);
gst_gl_effects_luma_to_curve (effects, heat_curve, GST_GL_EFFECTS_CURVE_HEAT, gst_gl_effects_luma_to_curve (effects, heat_curve, GST_GL_EFFECTS_CURVE_HEAT,
width, height, texture); width, height, texture);
} }
void void
gst_gl_effects_heat (GstGLEffects *effects) { gst_gl_effects_heat (GstGLEffects * effects)
{
GstGLFilter *filter = GST_GL_FILTER (effects); GstGLFilter *filter = GST_GL_FILTER (effects);
gst_gl_filter_render_to_target (filter, effects->intexture, effects->outtexture, gst_gl_filter_render_to_target (filter, effects->intexture,
gst_gl_effects_heat_callback, effects); effects->outtexture, gst_gl_effects_heat_callback, effects);
} }
static void gst_gl_effects_sepia_callback (gint width, gint height, guint texture, gpointer data) static void
gst_gl_effects_sepia_callback (gint width, gint height, guint texture,
gpointer data)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (data); GstGLEffects *effects = GST_GL_EFFECTS (data);
gst_gl_effects_luma_to_curve (effects, sepia_curve, GST_GL_EFFECTS_CURVE_SEPIA, gst_gl_effects_luma_to_curve (effects, sepia_curve,
width, height, texture); GST_GL_EFFECTS_CURVE_SEPIA, width, height, texture);
} }
void void
gst_gl_effects_sepia (GstGLEffects *effects) { gst_gl_effects_sepia (GstGLEffects * effects)
{
GstGLFilter *filter = GST_GL_FILTER (effects); GstGLFilter *filter = GST_GL_FILTER (effects);
gst_gl_filter_render_to_target (filter, effects->intexture, effects->outtexture, gst_gl_filter_render_to_target (filter, effects->intexture,
gst_gl_effects_sepia_callback, effects); effects->outtexture, gst_gl_effects_sepia_callback, effects);
} }
static void gst_gl_effects_luma_xpro_callback (gint width, gint height, guint texture, gpointer data) static void
gst_gl_effects_luma_xpro_callback (gint width, gint height, guint texture,
gpointer data)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (data); GstGLEffects *effects = GST_GL_EFFECTS (data);
gst_gl_effects_luma_to_curve (effects, luma_xpro_curve, GST_GL_EFFECTS_CURVE_LUMA_XPRO, gst_gl_effects_luma_to_curve (effects, luma_xpro_curve,
width, height, texture); GST_GL_EFFECTS_CURVE_LUMA_XPRO, width, height, texture);
} }
void void
gst_gl_effects_luma_xpro (GstGLEffects *effects) { gst_gl_effects_luma_xpro (GstGLEffects * effects)
{
GstGLFilter *filter = GST_GL_FILTER (effects); GstGLFilter *filter = GST_GL_FILTER (effects);
gst_gl_filter_render_to_target (filter, effects->intexture, effects->outtexture, gst_gl_filter_render_to_target (filter, effects->intexture,
gst_gl_effects_luma_xpro_callback, effects); effects->outtexture, gst_gl_effects_luma_xpro_callback, effects);
} }

View file

@ -21,44 +21,45 @@
#include <gstgleffects.h> #include <gstgleffects.h>
static void static void
gst_gl_effects_mirror_callback (gint width, gint height, guint texture, gpointer data) gst_gl_effects_mirror_callback (gint width, gint height, guint texture,
gpointer data)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (data); GstGLEffects *effects = GST_GL_EFFECTS (data);
GstGLShader *shader; GstGLShader *shader;
shader = g_hash_table_lookup (effects->shaderstable, "mirror0"); shader = g_hash_table_lookup (effects->shaderstable, "mirror0");
if (!shader) { if (!shader) {
shader = gst_gl_shader_new (); shader = gst_gl_shader_new ();
g_hash_table_insert (effects->shaderstable, "mirror0", shader); g_hash_table_insert (effects->shaderstable, "mirror0", shader);
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (shader,
gst_gl_shader_compile_and_check (shader, mirror_fragment_source, mirror_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
gst_gl_shader_use (shader); gst_gl_shader_use (shader);
glActiveTexture (GL_TEXTURE0); glActiveTexture (GL_TEXTURE0);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
gst_gl_shader_set_uniform_1i (shader, "tex", 0); gst_gl_shader_set_uniform_1i (shader, "tex", 0);
gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f); gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f);
gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f); gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f);
gst_gl_effects_draw_texture (effects, texture); gst_gl_effects_draw_texture (effects, texture);
} }
void void
gst_gl_effects_mirror (GstGLEffects *effects) { gst_gl_effects_mirror (GstGLEffects * effects)
{
GstGLFilter *filter = GST_GL_FILTER (effects); GstGLFilter *filter = GST_GL_FILTER (effects);
gst_gl_filter_render_to_target (filter, effects->intexture, effects->outtexture, gst_gl_filter_render_to_target (filter, effects->intexture,
gst_gl_effects_mirror_callback, effects); effects->outtexture, gst_gl_effects_mirror_callback, effects);
} }

View file

@ -21,24 +21,22 @@
#include <gstgleffects.h> #include <gstgleffects.h>
#include <gstgleffectscurves.h> #include <gstgleffectscurves.h>
static void gst_gl_effects_rgb_to_curve (GstGLEffects *effects, static void
GstGLEffectsCurve curve, gst_gl_effects_rgb_to_curve (GstGLEffects * effects,
gint curve_index, GstGLEffectsCurve curve,
gint width, gint height, gint curve_index, gint width, gint height, GLuint texture)
GLuint texture)
{ {
GstGLShader *shader; GstGLShader *shader;
shader = g_hash_table_lookup (effects->shaderstable, "rgbmap0"); shader = g_hash_table_lookup (effects->shaderstable, "rgbmap0");
if (!shader) { if (!shader) {
shader = gst_gl_shader_new (); shader = gst_gl_shader_new ();
g_hash_table_insert (effects->shaderstable, "rgbmap0", shader); g_hash_table_insert (effects->shaderstable, "rgbmap0", shader);
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (shader,
gst_gl_shader_compile_and_check (shader, rgb_to_curve_fragment_source, rgb_to_curve_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
@ -47,20 +45,18 @@ static void gst_gl_effects_rgb_to_curve (GstGLEffects *effects,
if (effects->curve[curve_index] == 0) { if (effects->curve[curve_index] == 0) {
/* this parameters are needed to have a right, predictable, mapping */ /* this parameters are needed to have a right, predictable, mapping */
glGenTextures(1, &effects->curve[curve_index]); glGenTextures (1, &effects->curve[curve_index]);
glEnable(GL_TEXTURE_1D); glEnable (GL_TEXTURE_1D);
glBindTexture (GL_TEXTURE_1D, effects->curve[curve_index]); glBindTexture (GL_TEXTURE_1D, effects->curve[curve_index]);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage1D(GL_TEXTURE_1D, 0, curve.bytes_per_pixel,
curve.width, 0,
GL_RGB, GL_UNSIGNED_BYTE,
curve.pixel_data);
glDisable(GL_TEXTURE_1D); glTexImage1D (GL_TEXTURE_1D, 0, curve.bytes_per_pixel,
curve.width, 0, GL_RGB, GL_UNSIGNED_BYTE, curve.pixel_data);
glDisable (GL_TEXTURE_1D);
} }
glActiveTexture (GL_TEXTURE0); glActiveTexture (GL_TEXTURE0);
@ -78,22 +74,25 @@ static void gst_gl_effects_rgb_to_curve (GstGLEffects *effects,
gst_gl_shader_set_uniform_1i (shader, "curve", 1); gst_gl_shader_set_uniform_1i (shader, "curve", 1);
glDisable (GL_TEXTURE_1D); glDisable (GL_TEXTURE_1D);
gst_gl_effects_draw_texture (effects, texture); gst_gl_effects_draw_texture (effects, texture);
} }
static void gst_gl_effects_xpro_callback (gint width, gint height, guint texture, gpointer data) static void
gst_gl_effects_xpro_callback (gint width, gint height, guint texture,
gpointer data)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (data); GstGLEffects *effects = GST_GL_EFFECTS (data);
gst_gl_effects_rgb_to_curve (effects, xpro_curve, GST_GL_EFFECTS_CURVE_XPRO, gst_gl_effects_rgb_to_curve (effects, xpro_curve, GST_GL_EFFECTS_CURVE_XPRO,
width, height, texture); width, height, texture);
} }
void void
gst_gl_effects_xpro (GstGLEffects *effects) { gst_gl_effects_xpro (GstGLEffects * effects)
{
GstGLFilter *filter = GST_GL_FILTER (effects); GstGLFilter *filter = GST_GL_FILTER (effects);
gst_gl_filter_render_to_target (filter, effects->intexture, effects->outtexture, gst_gl_filter_render_to_target (filter, effects->intexture,
gst_gl_effects_xpro_callback, effects); effects->outtexture, gst_gl_effects_xpro_callback, effects);
} }

View file

@ -21,41 +21,42 @@
#include <gstgleffects.h> #include <gstgleffects.h>
static void static void
gst_gl_effects_sin_callback (gint width, gint height, guint texture, gpointer data) gst_gl_effects_sin_callback (gint width, gint height, guint texture,
gpointer data)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (data); GstGLEffects *effects = GST_GL_EFFECTS (data);
GstGLShader *shader; GstGLShader *shader;
shader = g_hash_table_lookup (effects->shaderstable, "sin0"); shader = g_hash_table_lookup (effects->shaderstable, "sin0");
if (!shader) { if (!shader) {
shader = gst_gl_shader_new (); shader = gst_gl_shader_new ();
g_hash_table_insert (effects->shaderstable, "sin0", shader); g_hash_table_insert (effects->shaderstable, "sin0", shader);
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (shader,
gst_gl_shader_compile_and_check (shader, sin_fragment_source, sin_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
gst_gl_shader_use (shader); gst_gl_shader_use (shader);
glActiveTexture (GL_TEXTURE0); glActiveTexture (GL_TEXTURE0);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
gst_gl_shader_set_uniform_1i (shader, "tex", 0); gst_gl_shader_set_uniform_1i (shader, "tex", 0);
gst_gl_effects_draw_texture (effects, texture); gst_gl_effects_draw_texture (effects, texture);
} }
void void
gst_gl_effects_sin (GstGLEffects *effects) { gst_gl_effects_sin (GstGLEffects * effects)
{
GstGLFilter *filter = GST_GL_FILTER (effects); GstGLFilter *filter = GST_GL_FILTER (effects);
gst_gl_filter_render_to_target (filter, effects->intexture, effects->outtexture, gst_gl_filter_render_to_target (filter, effects->intexture,
gst_gl_effects_sin_callback, effects); effects->outtexture, gst_gl_effects_sin_callback, effects);
} }

View file

@ -21,44 +21,45 @@
#include <gstgleffects.h> #include <gstgleffects.h>
static void static void
gst_gl_effects_square_callback (gint width, gint height, guint texture, gpointer data) gst_gl_effects_square_callback (gint width, gint height, guint texture,
gpointer data)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (data); GstGLEffects *effects = GST_GL_EFFECTS (data);
GstGLShader *shader; GstGLShader *shader;
shader = g_hash_table_lookup (effects->shaderstable, "square0"); shader = g_hash_table_lookup (effects->shaderstable, "square0");
if (!shader) { if (!shader) {
shader = gst_gl_shader_new (); shader = gst_gl_shader_new ();
g_hash_table_insert (effects->shaderstable, "square0", shader); g_hash_table_insert (effects->shaderstable, "square0", shader);
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (shader,
gst_gl_shader_compile_and_check (shader, square_fragment_source, square_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
gst_gl_shader_use (shader); gst_gl_shader_use (shader);
glActiveTexture (GL_TEXTURE0); glActiveTexture (GL_TEXTURE0);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
gst_gl_shader_set_uniform_1i (shader, "tex", 0); gst_gl_shader_set_uniform_1i (shader, "tex", 0);
gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f); gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f);
gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f); gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f);
gst_gl_effects_draw_texture (effects, texture); gst_gl_effects_draw_texture (effects, texture);
} }
void void
gst_gl_effects_square (GstGLEffects *effects) { gst_gl_effects_square (GstGLEffects * effects)
{
GstGLFilter *filter = GST_GL_FILTER (effects); GstGLFilter *filter = GST_GL_FILTER (effects);
gst_gl_filter_render_to_target (filter, effects->intexture, effects->outtexture, gst_gl_filter_render_to_target (filter, effects->intexture,
gst_gl_effects_square_callback, effects); effects->outtexture, gst_gl_effects_square_callback, effects);
} }

View file

@ -21,44 +21,45 @@
#include <gstgleffects.h> #include <gstgleffects.h>
static void static void
gst_gl_effects_squeeze_callback (gint width, gint height, guint texture, gpointer data) gst_gl_effects_squeeze_callback (gint width, gint height, guint texture,
gpointer data)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (data); GstGLEffects *effects = GST_GL_EFFECTS (data);
GstGLShader *shader; GstGLShader *shader;
shader = g_hash_table_lookup (effects->shaderstable, "squeeze0"); shader = g_hash_table_lookup (effects->shaderstable, "squeeze0");
if (!shader) { if (!shader) {
shader = gst_gl_shader_new (); shader = gst_gl_shader_new ();
g_hash_table_insert (effects->shaderstable, "squeeze0", shader); g_hash_table_insert (effects->shaderstable, "squeeze0", shader);
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (shader,
gst_gl_shader_compile_and_check (shader, squeeze_fragment_source, squeeze_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
gst_gl_shader_use (shader); gst_gl_shader_use (shader);
glActiveTexture (GL_TEXTURE0); glActiveTexture (GL_TEXTURE0);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
gst_gl_shader_set_uniform_1i (shader, "tex", 0); gst_gl_shader_set_uniform_1i (shader, "tex", 0);
gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f); gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f);
gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f); gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f);
gst_gl_effects_draw_texture (effects, texture); gst_gl_effects_draw_texture (effects, texture);
} }
void void
gst_gl_effects_squeeze (GstGLEffects *effects) { gst_gl_effects_squeeze (GstGLEffects * effects)
{
GstGLFilter *filter = GST_GL_FILTER (effects); GstGLFilter *filter = GST_GL_FILTER (effects);
gst_gl_filter_render_to_target (filter, effects->intexture, effects->outtexture, gst_gl_filter_render_to_target (filter, effects->intexture,
gst_gl_effects_squeeze_callback, effects); effects->outtexture, gst_gl_effects_squeeze_callback, effects);
} }

View file

@ -27,391 +27,350 @@
/* Mirror effect */ /* Mirror effect */
const gchar *mirror_fragment_source = const gchar *mirror_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect tex;" "uniform sampler2DRect tex;"
"uniform float width, height;" "uniform float width, height;"
"void main () {" "void main () {"
" vec2 tex_size = vec2 (width, height);" " vec2 tex_size = vec2 (width, height);"
" vec2 texturecoord = gl_TexCoord[0].xy;" " vec2 texturecoord = gl_TexCoord[0].xy;"
" vec2 normcoord;" " vec2 normcoord;"
" normcoord = texturecoord / tex_size - 1.0;" " normcoord = texturecoord / tex_size - 1.0;"
" normcoord.x *= sign (normcoord.x);" " normcoord.x *= sign (normcoord.x);"
" texturecoord = (normcoord + 1.0) * tex_size;" " texturecoord = (normcoord + 1.0) * tex_size;"
" vec4 color = texture2DRect (tex, texturecoord); " " vec4 color = texture2DRect (tex, texturecoord); "
" gl_FragColor = color * gl_Color;" " gl_FragColor = color * gl_Color;" "}";
"}";
/* Squeeze effect */ /* Squeeze effect */
const gchar *squeeze_fragment_source = const gchar *squeeze_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect tex;" "uniform sampler2DRect tex;"
"uniform float width, height;" "uniform float width, height;"
"void main () {" "void main () {"
" vec2 tex_size = vec2 (width, height);" " vec2 tex_size = vec2 (width, height);"
" vec2 texturecoord = gl_TexCoord[0].xy;" " vec2 texturecoord = gl_TexCoord[0].xy;"
" vec2 normcoord;" " vec2 normcoord;"
" normcoord = texturecoord / tex_size - 1.0; " " normcoord = texturecoord / tex_size - 1.0; "
" float r = length (normcoord);" " float r = length (normcoord);"
" r = pow(r, 0.40)*1.3;" " r = pow(r, 0.40)*1.3;"
" normcoord = normcoord / r;" " normcoord = normcoord / r;"
" texturecoord = (normcoord + 1.0) * tex_size;" " texturecoord = (normcoord + 1.0) * tex_size;"
" vec4 color = texture2DRect (tex, texturecoord); " " vec4 color = texture2DRect (tex, texturecoord); "
" gl_FragColor = color * gl_Color;" " gl_FragColor = color * gl_Color;" "}";
"}";
/* Stretch Effect */ /* Stretch Effect */
const gchar *stretch_fragment_source = const gchar *stretch_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect tex;" "uniform sampler2DRect tex;"
"uniform float width, height;" "uniform float width, height;"
"void main () {" "void main () {"
" vec2 tex_size = vec2 (width, height);" " vec2 tex_size = vec2 (width, height);"
" vec2 texturecoord = gl_TexCoord[0].xy;" " vec2 texturecoord = gl_TexCoord[0].xy;"
" vec2 normcoord;" " vec2 normcoord;"
" normcoord = texturecoord / tex_size - 1.0;" " normcoord = texturecoord / tex_size - 1.0;"
" float r = length (normcoord);" " float r = length (normcoord);"
" normcoord *= 2.0 - smoothstep(0.0, 0.7, r);" " normcoord *= 2.0 - smoothstep(0.0, 0.7, r);"
" texturecoord = (normcoord + 1.0) * tex_size;" " texturecoord = (normcoord + 1.0) * tex_size;"
" vec4 color = texture2DRect (tex, texturecoord);" " vec4 color = texture2DRect (tex, texturecoord);"
" gl_FragColor = color * gl_Color;" " gl_FragColor = color * gl_Color;" "}";
"}";
/* Light Tunnel effect */ /* Light Tunnel effect */
const gchar *tunnel_fragment_source = const gchar *tunnel_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect tex;" "uniform sampler2DRect tex;"
"uniform float width, height;" "uniform float width, height;"
"void main () {" "void main () {"
" vec2 tex_size = vec2 (width, height);" " vec2 tex_size = vec2 (width, height);"
" vec2 texturecoord = gl_TexCoord[0].xy;" " vec2 texturecoord = gl_TexCoord[0].xy;" " vec2 normcoord;"
" vec2 normcoord;" /* little trick with normalized coords to obtain a circle */
/* little trick with normalized coords to obtain a circle */ " normcoord = texturecoord / tex_size.x - tex_size / tex_size.x;" " float r = length(normcoord);" " float phi = atan(normcoord.y, normcoord.x);" " r = clamp (r, 0.0, 0.5);" /* is there a way to do this without polars? */
" normcoord = texturecoord / tex_size.x - tex_size / tex_size.x;" " normcoord.x = r * cos(phi);"
" float r = length(normcoord);" " normcoord.y = r * sin(phi); "
" float phi = atan(normcoord.y, normcoord.x);" " texturecoord = (normcoord + tex_size/tex_size.x) * tex_size.x;"
" r = clamp (r, 0.0, 0.5);" /* is there a way to do this without polars? */ " vec4 color = texture2DRect (tex, texturecoord); "
" normcoord.x = r * cos(phi);" " gl_FragColor = color;" "}";
" normcoord.y = r * sin(phi); "
" texturecoord = (normcoord + tex_size/tex_size.x) * tex_size.x;"
" vec4 color = texture2DRect (tex, texturecoord); "
" gl_FragColor = color;"
"}";
/* FishEye effect */ /* FishEye effect */
const gchar *fisheye_fragment_source = const gchar *fisheye_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect tex;" "uniform sampler2DRect tex;"
"uniform float width, height;" "uniform float width, height;"
"void main () {" "void main () {"
" vec2 tex_size = vec2 (width, height);" " vec2 tex_size = vec2 (width, height);"
" vec2 texturecoord = gl_TexCoord[0].xy;" " vec2 texturecoord = gl_TexCoord[0].xy;"
" vec2 normcoord;" " vec2 normcoord;"
" normcoord = texturecoord / tex_size - 1.0;" " normcoord = texturecoord / tex_size - 1.0;"
" float r = length (normcoord);" " float r = length (normcoord);"
" normcoord *= r/sqrt(2.0);" " normcoord *= r/sqrt(2.0);"
" texturecoord = (normcoord + 1.0) * tex_size;" " texturecoord = (normcoord + 1.0) * tex_size;"
" vec4 color = texture2DRect (tex, texturecoord);" " vec4 color = texture2DRect (tex, texturecoord);"
" gl_FragColor = color;" " gl_FragColor = color;" "}";
"}";
/* Twirl effect */ /* Twirl effect */
const gchar *twirl_fragment_source = const gchar *twirl_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect tex;" "uniform sampler2DRect tex;"
"uniform float width, height;" "uniform float width, height;"
"void main () {" "void main () {"
" vec2 tex_size = vec2 (width, height);" " vec2 tex_size = vec2 (width, height);"
" vec2 texturecoord = gl_TexCoord[0].xy;" " vec2 texturecoord = gl_TexCoord[0].xy;"
" vec2 normcoord;" " vec2 normcoord;"
" normcoord = texturecoord / tex_size - 1.0;" " normcoord = texturecoord / tex_size - 1.0;"
" float r = length (normcoord);" " float r = length (normcoord);"
" float phi = atan (normcoord.y, normcoord.x);" " float phi = atan (normcoord.y, normcoord.x);"
" phi += (1.0 - smoothstep (-0.6, 0.6, r)) * 4.8;" " phi += (1.0 - smoothstep (-0.6, 0.6, r)) * 4.8;"
" normcoord.x = r * cos(phi);" " normcoord.x = r * cos(phi);"
" normcoord.y = r * sin(phi);" " normcoord.y = r * sin(phi);"
" texturecoord = (normcoord + 1.0) * tex_size;" " texturecoord = (normcoord + 1.0) * tex_size;"
" vec4 color = texture2DRect (tex, texturecoord); " " vec4 color = texture2DRect (tex, texturecoord); "
" gl_FragColor = color;" " gl_FragColor = color;" "}";
"}";
/* Bulge effect */ /* Bulge effect */
const gchar *bulge_fragment_source = const gchar *bulge_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect tex;" "uniform sampler2DRect tex;"
"uniform float width, height;" "uniform float width, height;"
"void main () {" "void main () {"
" vec2 tex_size = vec2 (width, height);" " vec2 tex_size = vec2 (width, height);"
" vec2 texturecoord = gl_TexCoord[0].xy;" " vec2 texturecoord = gl_TexCoord[0].xy;"
" vec2 normcoord;" " vec2 normcoord;"
" normcoord = texturecoord / tex_size - 1.0;" " normcoord = texturecoord / tex_size - 1.0;"
" float r = length (normcoord);" " float r = length (normcoord);"
" normcoord *= smoothstep (-0.1, 0.5, r);" " normcoord *= smoothstep (-0.1, 0.5, r);"
" texturecoord = (normcoord + 1.0) * tex_size;" " texturecoord = (normcoord + 1.0) * tex_size;"
" vec4 color = texture2DRect (tex, texturecoord);" " vec4 color = texture2DRect (tex, texturecoord);"
" gl_FragColor = color;" " gl_FragColor = color;" "}";
"}";
/* Square Effect */ /* Square Effect */
const gchar *square_fragment_source = const gchar *square_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect tex;" "uniform sampler2DRect tex;"
"uniform float width;" "uniform float width;"
"uniform float height;" "uniform float height;"
"void main () {" "void main () {"
" vec2 tex_size = vec2 (width, height);" " vec2 tex_size = vec2 (width, height);"
" vec2 texturecoord = gl_TexCoord[0].xy;" " vec2 texturecoord = gl_TexCoord[0].xy;"
" vec2 normcoord;" " vec2 normcoord;"
" normcoord = texturecoord / tex_size - 1.0;" " normcoord = texturecoord / tex_size - 1.0;"
" float r = length (normcoord);" " float r = length (normcoord);"
" normcoord *= 1.0 + smoothstep(0.25, 0.5, abs(normcoord));" " normcoord *= 1.0 + smoothstep(0.25, 0.5, abs(normcoord));"
" normcoord /= 2.0; /* zoom amount */" " normcoord /= 2.0; /* zoom amount */"
" texturecoord = (normcoord + 1.0) * tex_size;" " texturecoord = (normcoord + 1.0) * tex_size;"
" vec4 color = texture2DRect (tex, texturecoord);" " vec4 color = texture2DRect (tex, texturecoord);"
" gl_FragColor = color * gl_Color;" " gl_FragColor = color * gl_Color;" "}";
"}";
const gchar *luma_threshold_fragment_source = const gchar *luma_threshold_fragment_source = "#extension GL_ARB_texture_rectangle : enable\n" "uniform sampler2DRect tex;" "void main () {" " vec2 texturecoord = gl_TexCoord[0].st;" " int i;" " vec4 color = texture2DRect(tex, texturecoord);" " float luma = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));" /* BT.709 (from orange book) */
"#extension GL_ARB_texture_rectangle : enable\n" " gl_FragColor = vec4 (vec3 (smoothstep (0.30, 0.50, luma)), color.a);"
"uniform sampler2DRect tex;" "}";
"void main () {"
" vec2 texturecoord = gl_TexCoord[0].st;"
" int i;"
" vec4 color = texture2DRect(tex, texturecoord);"
" float luma = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));" /* BT.709 (from orange book) */
" gl_FragColor = vec4 (vec3 (smoothstep (0.30, 0.50, luma)), color.a);"
"}";
const gchar *sobel_fragment_source = const gchar *sobel_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect tex;" "uniform sampler2DRect tex;"
"uniform float hkern[9];" "uniform float hkern[9];"
"uniform float vkern[9];" "uniform float vkern[9];"
"uniform bool invert;" "uniform bool invert;"
"void main () {" "void main () {"
" vec2 offset[9] = vec2[9] ( vec2(-1.0,-1.0), vec2( 0.0,-1.0), vec2( 1.0,-1.0)," " vec2 offset[9] = vec2[9] ( vec2(-1.0,-1.0), vec2( 0.0,-1.0), vec2( 1.0,-1.0),"
" vec2(-1.0, 0.0), vec2( 0.0, 0.0), vec2( 1.0, 0.0)," " vec2(-1.0, 0.0), vec2( 0.0, 0.0), vec2( 1.0, 0.0),"
" vec2(-1.0, 1.0), vec2( 0.0, 1.0), vec2( 1.0, 1.0) );" " vec2(-1.0, 1.0), vec2( 0.0, 1.0), vec2( 1.0, 1.0) );"
" vec2 texturecoord = gl_TexCoord[0].st;" " vec2 texturecoord = gl_TexCoord[0].st;"
" int i;" " int i;"
" float luma;" " float luma;"
" float gx = 0.0;" " float gx = 0.0;"
" float gy = 0.0 ;" " float gy = 0.0 ;"
" for (i = 0; i < 9; i++) { " " for (i = 0; i < 9; i++) { "
" if(hkern[i] != 0.0 || vkern[i] != 0.0) {" " if(hkern[i] != 0.0 || vkern[i] != 0.0) {"
" vec4 neighbor = texture2DRect(tex, texturecoord + vec2(offset[i])); " " vec4 neighbor = texture2DRect(tex, texturecoord + vec2(offset[i])); "
" luma = dot(neighbor, vec4(0.2125, 0.7154, 0.0721, neighbor.a));" " luma = dot(neighbor, vec4(0.2125, 0.7154, 0.0721, neighbor.a));"
" gx += luma * hkern[i]; " " gx += luma * hkern[i]; "
" gy += luma * vkern[i]; " " gy += luma * vkern[i]; "
" }" " }"
" }" " }"
" float g = sqrt(gx*gx + gy*gy);" " float g = sqrt(gx*gx + gy*gy);"
" if (invert) g = 1.0 - g;" " if (invert) g = 1.0 - g;" " gl_FragColor = vec4(vec3(g), 1.0);" "}";
" gl_FragColor = vec4(vec3(g), 1.0);"
"}";
/* horizontal convolution */ /* horizontal convolution */
const gchar *hconv9_fragment_source = const gchar *hconv9_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect tex;" "uniform sampler2DRect tex;"
"uniform float norm_const;" "uniform float norm_const;"
"uniform float norm_offset;" "uniform float norm_offset;" "uniform float kernel[9];" "void main () {"
"uniform float kernel[9];"
"void main () {"
/* "float offset[9] = float[9] (-4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0);" */ /* "float offset[9] = float[9] (-4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0);" */
/* don't use array constructor so we don't have to depend on #version 120 */ /* don't use array constructor so we don't have to depend on #version 120 */
" float offset[9];" " float offset[9];"
" offset[0] = -4.0;" " offset[0] = -4.0;"
" offset[1] = -3.0;" " offset[1] = -3.0;"
" offset[2] = -2.0;" " offset[2] = -2.0;"
" offset[3] = -1.0;" " offset[3] = -1.0;"
" offset[4] = 0.0;" " offset[4] = 0.0;"
" offset[5] = 1.0;" " offset[5] = 1.0;"
" offset[6] = 2.0;" " offset[6] = 2.0;"
" offset[7] = 3.0;" " offset[7] = 3.0;"
" offset[8] = 4.0;" " offset[8] = 4.0;"
" vec2 texturecoord = gl_TexCoord[0].st;" " vec2 texturecoord = gl_TexCoord[0].st;"
" int i;" " int i;"
" vec4 sum = vec4 (0.0);" " vec4 sum = vec4 (0.0);"
" for (i = 0; i < 9; i++) { " " for (i = 0; i < 9; i++) { "
" if (kernel[i] != 0.0) {" " if (kernel[i] != 0.0) {"
" vec4 neighbor = texture2DRect(tex, vec2(texturecoord.s+offset[i], texturecoord.t)); " " vec4 neighbor = texture2DRect(tex, vec2(texturecoord.s+offset[i], texturecoord.t)); "
" sum += neighbor * kernel[i]/norm_const; " " sum += neighbor * kernel[i]/norm_const; "
" }" " }" " }" " gl_FragColor = sum + norm_offset;" "}";
" }"
" gl_FragColor = sum + norm_offset;"
"}";
/* vertical convolution */ /* vertical convolution */
const gchar *vconv9_fragment_source = const gchar *vconv9_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect tex;" "uniform sampler2DRect tex;"
"uniform float norm_const;" "uniform float norm_const;"
"uniform float norm_offset;" "uniform float norm_offset;" "uniform float kernel[9];" "void main () {"
"uniform float kernel[9];"
"void main () {"
/* "float offset[9] = float[9] (-4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0);" */ /* "float offset[9] = float[9] (-4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0);" */
/* don't use array constructor so we don't have to depend on #version 120 */ /* don't use array constructor so we don't have to depend on #version 120 */
" float offset[9];" " float offset[9];"
" offset[0] = -4.0;" " offset[0] = -4.0;"
" offset[1] = -3.0;" " offset[1] = -3.0;"
" offset[2] = -2.0;" " offset[2] = -2.0;"
" offset[3] = -1.0;" " offset[3] = -1.0;"
" offset[4] = 0.0;" " offset[4] = 0.0;"
" offset[5] = 1.0;" " offset[5] = 1.0;"
" offset[6] = 2.0;" " offset[6] = 2.0;"
" offset[7] = 3.0;" " offset[7] = 3.0;"
" offset[8] = 4.0;" " offset[8] = 4.0;"
" vec2 texturecoord = gl_TexCoord[0].st;" " vec2 texturecoord = gl_TexCoord[0].st;"
" int i;" " int i;"
" vec4 sum = vec4 (0.0);" " vec4 sum = vec4 (0.0);"
" for (i = 0; i < 9; i++) { " " for (i = 0; i < 9; i++) { "
" if (kernel[i] != 0.0) {" " if (kernel[i] != 0.0) {"
" vec4 neighbor = texture2DRect(tex, vec2(texturecoord.s, texturecoord.t+offset[i])); " " vec4 neighbor = texture2DRect(tex, vec2(texturecoord.s, texturecoord.t+offset[i])); "
" sum += neighbor * kernel[i]/norm_const; " " sum += neighbor * kernel[i]/norm_const; "
" }" " }" " }" " gl_FragColor = sum + norm_offset;" "}";
" }"
" gl_FragColor = sum + norm_offset;"
"}";
/* TODO: support several blend modes */ /* TODO: support several blend modes */
const gchar *sum_fragment_source = const gchar *sum_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect base;" "uniform sampler2DRect base;"
"uniform sampler2DRect blend;" "uniform sampler2DRect blend;"
"uniform float alpha;" "uniform float alpha;"
"uniform float beta;" "uniform float beta;"
"void main () {" "void main () {"
" vec4 basecolor = texture2DRect (base, gl_TexCoord[0].st);" " vec4 basecolor = texture2DRect (base, gl_TexCoord[0].st);"
" vec4 blendcolor = texture2DRect (blend, gl_TexCoord[0].st);" " vec4 blendcolor = texture2DRect (blend, gl_TexCoord[0].st);"
" gl_FragColor = alpha * basecolor + beta * blendcolor;" " gl_FragColor = alpha * basecolor + beta * blendcolor;" "}";
"}";
const gchar *multiply_fragment_source = const gchar *multiply_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect base;" "uniform sampler2DRect base;"
"uniform sampler2DRect blend;" "uniform sampler2DRect blend;"
"uniform float alpha;" "uniform float alpha;"
"void main () {" "void main () {"
" vec4 basecolor = texture2DRect (base, gl_TexCoord[0].st);" " vec4 basecolor = texture2DRect (base, gl_TexCoord[0].st);"
" vec4 blendcolor = texture2DRect (blend, gl_TexCoord[0].st);" " vec4 blendcolor = texture2DRect (blend, gl_TexCoord[0].st);"
" gl_FragColor = (1 - alpha) * basecolor + alpha * basecolor * blendcolor;" " gl_FragColor = (1 - alpha) * basecolor + alpha * basecolor * blendcolor;"
"}"; "}";
/* lut operations, map luma to tex1d, see orange book (chapter 19) */ /* lut operations, map luma to tex1d, see orange book (chapter 19) */
const gchar *luma_to_curve_fragment_source = const gchar *luma_to_curve_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect tex;" "uniform sampler2DRect tex;"
"uniform sampler1D curve;" "uniform sampler1D curve;"
"void main () {" "void main () {"
" vec2 texturecoord = gl_TexCoord[0].st;" " vec2 texturecoord = gl_TexCoord[0].st;"
" vec4 color = texture2DRect (tex, texturecoord);" " vec4 color = texture2DRect (tex, texturecoord);"
" float luma = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));" " float luma = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));"
" color = texture1D(curve, luma);" " color = texture1D(curve, luma);" " gl_FragColor = color;" "}";
" gl_FragColor = color;"
"}";
/* lut operations, map rgb to tex1d, see orange book (chapter 19) */ /* lut operations, map rgb to tex1d, see orange book (chapter 19) */
const gchar *rgb_to_curve_fragment_source = const gchar *rgb_to_curve_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect tex;" "uniform sampler2DRect tex;"
"uniform sampler1D curve;" "uniform sampler1D curve;"
"void main () {" "void main () {"
" vec2 texturecoord = gl_TexCoord[0].st;" " vec2 texturecoord = gl_TexCoord[0].st;"
" vec4 color = texture2DRect (tex, texturecoord);" " vec4 color = texture2DRect (tex, texturecoord);"
" vec4 outcolor;" " vec4 outcolor;"
" outcolor.r = texture1D(curve, color.r).r;" " outcolor.r = texture1D(curve, color.r).r;"
" outcolor.g = texture1D(curve, color.g).g;" " outcolor.g = texture1D(curve, color.g).g;"
" outcolor.b = texture1D(curve, color.b).b;" " outcolor.b = texture1D(curve, color.b).b;"
" outcolor.a = color.a;" " outcolor.a = color.a;" " gl_FragColor = outcolor;" "}";
" gl_FragColor = outcolor;"
"}";
const gchar *sin_fragment_source = const gchar *sin_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect tex;" "uniform sampler2DRect tex;" "vec3 rgb2hsl (vec3 v) " "{"
"vec3 rgb2hsl (vec3 v) "
"{"
/* TODO: check this algorythm */ /* TODO: check this algorythm */
" float MIN, MAX;" " float MIN, MAX;"
" float r, g, b;" " float r, g, b;"
" float h, l, s;" " float h, l, s;"
" float delta;" " float delta;"
" h = 0.0; l = 0.0; s = 0.0;" " h = 0.0; l = 0.0; s = 0.0;"
" r = v.r; g = v.g; b = v.b;" " r = v.r; g = v.g; b = v.b;"
" MIN = min (r, min (g, b));" " MIN = min (r, min (g, b));"
" MAX = max (r, max (g, b));" " MAX = max (r, max (g, b));"
" delta = MAX - MIN;" " delta = MAX - MIN;"
" l = (MAX + MIN) / 2.0;" " l = (MAX + MIN) / 2.0;"
" if ((MAX - MIN) < 0.0001) { h = 0.0; s = 0.0; }" " if ((MAX - MIN) < 0.0001) { h = 0.0; s = 0.0; }"
" else {" " else {"
" if (l <= 0.5) s = (MAX - MIN) / (MAX + MIN);" " if (l <= 0.5) s = (MAX - MIN) / (MAX + MIN);"
" else s = (MAX - MIN) / (2.0 - MAX - MIN);" " else s = (MAX - MIN) / (2.0 - MAX - MIN);"
" if (r == MAX) h = (g - b) / delta;" " if (r == MAX) h = (g - b) / delta;"
" else if (g == MAX) h = 2.0 + (b - r) / delta;" " else if (g == MAX) h = 2.0 + (b - r) / delta;"
" else h = 4.0 + (r - g) / delta;" " else h = 4.0 + (r - g) / delta;"
" h *= 60.0;" " h *= 60.0;"
" if (h < 0.0) h += 360.0;" " if (h < 0.0) h += 360.0;"
" }" " }"
" return vec3 (h, l, s);" " return vec3 (h, l, s);"
"}" "}"
"void main () {" "void main () {"
" vec3 HSL, RGB;" " vec3 HSL, RGB;"
" vec4 color = texture2DRect (tex, vec2(gl_TexCoord[0].st));" " vec4 color = texture2DRect (tex, vec2(gl_TexCoord[0].st));"
" float luma = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));" " float luma = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));"
" HSL = rgb2hsl (color.rgb);" " HSL = rgb2hsl (color.rgb);"
/* move hls discontinuity away from the desired red zone so we can use /* move hls discontinuity away from the desired red zone so we can use
* smoothstep.. to try: convert degrees in radiants, divide by 2 and * smoothstep.. to try: convert degrees in radiants, divide by 2 and
* smoothstep cosine */ * smoothstep cosine */
" HSL.x += 180.0;" " HSL.x += 180.0;" " if ((HSL.x) > 360.0) HSL.x -= 360.0;"
" if ((HSL.x) > 360.0) HSL.x -= 360.0;"
/* damn, it is extremely hard to get rid of human face reds! */ /* damn, it is extremely hard to get rid of human face reds! */
/* picked hue is slightly shifted towards violet to prevent this but /* picked hue is slightly shifted towards violet to prevent this but
* still fails.. maybe hsl is not well suited for this */ * still fails.. maybe hsl is not well suited for this */
" float a = smoothstep (110.0, 150.0, HSL.x);" " float a = smoothstep (110.0, 150.0, HSL.x);"
" float b = smoothstep (170.0, 210.0, HSL.x);" " float b = smoothstep (170.0, 210.0, HSL.x);"
" float alpha = a - b;" " float alpha = a - b;"
" gl_FragColor = color * alpha + luma * (1.0 - alpha);" " gl_FragColor = color * alpha + luma * (1.0 - alpha);" "}";
"}";
const gchar *interpolate_fragment_source = const gchar *interpolate_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect base;" "uniform sampler2DRect base;"
"uniform sampler2DRect blend;" "uniform sampler2DRect blend;"
"void main () {" "void main () {"
"vec4 basecolor = texture2DRect (base, gl_TexCoord[0].st);" "vec4 basecolor = texture2DRect (base, gl_TexCoord[0].st);"
"vec4 blendcolor = texture2DRect (blend, gl_TexCoord[0].st);" "vec4 blendcolor = texture2DRect (blend, gl_TexCoord[0].st);"
"vec4 white = vec4(1.0);" "vec4 white = vec4(1.0);"
"gl_FragColor = blendcolor + (1.0 - blendcolor.a) * basecolor;" "gl_FragColor = blendcolor + (1.0 - blendcolor.a) * basecolor;" "}";
"}";
const gchar *texture_interp_fragment_source = const gchar *texture_interp_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect base;" "uniform sampler2DRect base;"
"uniform sampler2DRect blend;" "uniform sampler2DRect blend;"
"uniform sampler2DRect alpha;" "uniform sampler2DRect alpha;"
"void main () {" "void main () {"
"vec4 basecolor = texture2DRect (base, gl_TexCoord[0].st);" "vec4 basecolor = texture2DRect (base, gl_TexCoord[0].st);"
"vec4 blendcolor = texture2DRect (blend, gl_TexCoord[0].st);" "vec4 blendcolor = texture2DRect (blend, gl_TexCoord[0].st);"
"vec4 alphacolor = texture2DRect (alpha, gl_TexCoord[0].st);" "vec4 alphacolor = texture2DRect (alpha, gl_TexCoord[0].st);"
// "gl_FragColor = alphacolor;" // "gl_FragColor = alphacolor;"
"gl_FragColor = (alphacolor * blendcolor) + (1.0 - alphacolor) * basecolor;" "gl_FragColor = (alphacolor * blendcolor) + (1.0 - alphacolor) * basecolor;"
"}"; "}";
const gchar *difference_fragment_source = const gchar *difference_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect saved;" "uniform sampler2DRect saved;"
"uniform sampler2DRect current;" "uniform sampler2DRect current;"
"void main () {" "void main () {"
"vec4 savedcolor = texture2DRect (saved, gl_TexCoord[0].st);" "vec4 savedcolor = texture2DRect (saved, gl_TexCoord[0].st);"
"vec4 currentcolor = texture2DRect (current, gl_TexCoord[0].st);" "vec4 currentcolor = texture2DRect (current, gl_TexCoord[0].st);"
"gl_FragColor = vec4 (step (0.12, length (savedcolor - currentcolor)));" "gl_FragColor = vec4 (step (0.12, length (savedcolor - currentcolor)));"
"}"; "}";

View file

@ -21,44 +21,45 @@
#include <gstgleffects.h> #include <gstgleffects.h>
static void static void
gst_gl_effects_stretch_callback (gint width, gint height, guint texture, gpointer data) gst_gl_effects_stretch_callback (gint width, gint height, guint texture,
gpointer data)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (data); GstGLEffects *effects = GST_GL_EFFECTS (data);
GstGLShader *shader; GstGLShader *shader;
shader = g_hash_table_lookup (effects->shaderstable, "stretch0"); shader = g_hash_table_lookup (effects->shaderstable, "stretch0");
if (!shader) { if (!shader) {
shader = gst_gl_shader_new (); shader = gst_gl_shader_new ();
g_hash_table_insert (effects->shaderstable, "stretch0", shader); g_hash_table_insert (effects->shaderstable, "stretch0", shader);
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (shader,
gst_gl_shader_compile_and_check (shader, stretch_fragment_source, stretch_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
gst_gl_shader_use (shader); gst_gl_shader_use (shader);
glActiveTexture (GL_TEXTURE0); glActiveTexture (GL_TEXTURE0);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
gst_gl_shader_set_uniform_1i (shader, "tex", 0); gst_gl_shader_set_uniform_1i (shader, "tex", 0);
gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f); gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f);
gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f); gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f);
gst_gl_effects_draw_texture (effects, texture); gst_gl_effects_draw_texture (effects, texture);
} }
void void
gst_gl_effects_stretch (GstGLEffects *effects) { gst_gl_effects_stretch (GstGLEffects * effects)
{
GstGLFilter *filter = GST_GL_FILTER (effects); GstGLFilter *filter = GST_GL_FILTER (effects);
gst_gl_filter_render_to_target (filter, effects->intexture, effects->outtexture, gst_gl_filter_render_to_target (filter, effects->intexture,
gst_gl_effects_stretch_callback, effects); effects->outtexture, gst_gl_effects_stretch_callback, effects);
} }

View file

@ -21,44 +21,45 @@
#include <gstgleffects.h> #include <gstgleffects.h>
static void static void
gst_gl_effects_tunnel_callback (gint width, gint height, guint texture, gpointer data) gst_gl_effects_tunnel_callback (gint width, gint height, guint texture,
gpointer data)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (data); GstGLEffects *effects = GST_GL_EFFECTS (data);
GstGLShader *shader; GstGLShader *shader;
shader = g_hash_table_lookup (effects->shaderstable, "tunnel0"); shader = g_hash_table_lookup (effects->shaderstable, "tunnel0");
if (!shader) { if (!shader) {
shader = gst_gl_shader_new (); shader = gst_gl_shader_new ();
g_hash_table_insert (effects->shaderstable, "tunnel0", shader); g_hash_table_insert (effects->shaderstable, "tunnel0", shader);
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (shader,
gst_gl_shader_compile_and_check (shader, tunnel_fragment_source, tunnel_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
gst_gl_shader_use (shader); gst_gl_shader_use (shader);
glActiveTexture (GL_TEXTURE0); glActiveTexture (GL_TEXTURE0);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
gst_gl_shader_set_uniform_1i (shader, "tex", 0); gst_gl_shader_set_uniform_1i (shader, "tex", 0);
gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f); gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f);
gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f); gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f);
gst_gl_effects_draw_texture (effects, texture); gst_gl_effects_draw_texture (effects, texture);
} }
void void
gst_gl_effects_tunnel (GstGLEffects *effects) { gst_gl_effects_tunnel (GstGLEffects * effects)
{
GstGLFilter *filter = GST_GL_FILTER (effects); GstGLFilter *filter = GST_GL_FILTER (effects);
gst_gl_filter_render_to_target (filter, effects->intexture, effects->outtexture, gst_gl_filter_render_to_target (filter, effects->intexture,
gst_gl_effects_tunnel_callback, effects); effects->outtexture, gst_gl_effects_tunnel_callback, effects);
} }

View file

@ -21,44 +21,45 @@
#include <gstgleffects.h> #include <gstgleffects.h>
static void static void
gst_gl_effects_twirl_callback (gint width, gint height, guint texture, gpointer data) gst_gl_effects_twirl_callback (gint width, gint height, guint texture,
gpointer data)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (data); GstGLEffects *effects = GST_GL_EFFECTS (data);
GstGLShader *shader; GstGLShader *shader;
shader = g_hash_table_lookup (effects->shaderstable, "twirl0"); shader = g_hash_table_lookup (effects->shaderstable, "twirl0");
if (!shader) { if (!shader) {
shader = gst_gl_shader_new (); shader = gst_gl_shader_new ();
g_hash_table_insert (effects->shaderstable, "twirl0", shader); g_hash_table_insert (effects->shaderstable, "twirl0", shader);
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (shader,
gst_gl_shader_compile_and_check (shader, twirl_fragment_source, twirl_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
gst_gl_shader_use (shader); gst_gl_shader_use (shader);
glActiveTexture (GL_TEXTURE0); glActiveTexture (GL_TEXTURE0);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
gst_gl_shader_set_uniform_1i (shader, "tex", 0); gst_gl_shader_set_uniform_1i (shader, "tex", 0);
gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f); gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f);
gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f); gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f);
gst_gl_effects_draw_texture (effects, texture); gst_gl_effects_draw_texture (effects, texture);
} }
void void
gst_gl_effects_twirl (GstGLEffects *effects) { gst_gl_effects_twirl (GstGLEffects * effects)
{
GstGLFilter *filter = GST_GL_FILTER (effects); GstGLFilter *filter = GST_GL_FILTER (effects);
gst_gl_filter_render_to_target (filter, effects->intexture, effects->outtexture, gst_gl_filter_render_to_target (filter, effects->intexture,
gst_gl_effects_twirl_callback, effects); effects->outtexture, gst_gl_effects_twirl_callback, effects);
} }

View file

@ -24,34 +24,38 @@
/* Gaussian Kernel: std = 1.200000, size = 9x1 */ /* Gaussian Kernel: std = 1.200000, size = 9x1 */
static gfloat gauss_kernel[9] = { 0.001285f, 0.014607f, 0.082898f, static gfloat gauss_kernel[9] = { 0.001285f, 0.014607f, 0.082898f,
0.234927f, 0.332452f, 0.234927f, 0.234927f, 0.332452f, 0.234927f,
0.082898f, 0.014607f, 0.001285f }; 0.082898f, 0.014607f, 0.001285f
};
/* Normalization Constant = 0.999885 */ /* Normalization Constant = 0.999885 */
static void gst_gl_effects_xray_step_one (gint width, gint height, guint texture, gpointer data) static void
gst_gl_effects_xray_step_one (gint width, gint height, guint texture,
gpointer data)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (data); GstGLEffects *effects = GST_GL_EFFECTS (data);
gst_gl_effects_luma_to_curve (effects, xray_curve, GST_GL_EFFECTS_CURVE_XRAY, gst_gl_effects_luma_to_curve (effects, xray_curve, GST_GL_EFFECTS_CURVE_XRAY,
width, height, texture); width, height, texture);
} }
static void static void
gst_gl_effects_xray_step_two (gint width, gint height, guint texture, gpointer data) gst_gl_effects_xray_step_two (gint width, gint height, guint texture,
gpointer data)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (data); GstGLEffects *effects = GST_GL_EFFECTS (data);
GstGLShader *shader; GstGLShader *shader;
shader = g_hash_table_lookup (effects->shaderstable, "xray1"); shader = g_hash_table_lookup (effects->shaderstable, "xray1");
if (!shader) { if (!shader) {
shader = gst_gl_shader_new (); shader = gst_gl_shader_new ();
g_hash_table_insert (effects->shaderstable, "xray1", shader); g_hash_table_insert (effects->shaderstable, "xray1", shader);
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (shader,
gst_gl_shader_compile_and_check (shader, hconv9_fragment_source, hconv9_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
@ -73,21 +77,21 @@ gst_gl_effects_xray_step_two (gint width, gint height, guint texture, gpointer d
} }
static void static void
gst_gl_effects_xray_step_three (gint width, gint height, guint texture, gpointer data) gst_gl_effects_xray_step_three (gint width, gint height, guint texture,
gpointer data)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (data); GstGLEffects *effects = GST_GL_EFFECTS (data);
GstGLShader *shader; GstGLShader *shader;
shader = g_hash_table_lookup (effects->shaderstable, "xray2"); shader = g_hash_table_lookup (effects->shaderstable, "xray2");
if (!shader) { if (!shader) {
shader = gst_gl_shader_new (); shader = gst_gl_shader_new ();
g_hash_table_insert (effects->shaderstable, "xray2", shader); g_hash_table_insert (effects->shaderstable, "xray2", shader);
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (shader,
gst_gl_shader_compile_and_check (shader, vconv9_fragment_source, vconv9_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
@ -109,33 +113,33 @@ gst_gl_effects_xray_step_three (gint width, gint height, guint texture, gpointer
} }
static void static void
gst_gl_effects_xray_step_four (gint width, gint height, guint texture, gpointer data) gst_gl_effects_xray_step_four (gint width, gint height, guint texture,
gpointer data)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (data); GstGLEffects *effects = GST_GL_EFFECTS (data);
GstGLShader *shader; GstGLShader *shader;
gfloat hkern[9] = { gfloat hkern[9] = {
1.0, 0.0, -1.0, 1.0, 0.0, -1.0,
2.0, 0.0, -2.0, 2.0, 0.0, -2.0,
1.0, 0.0, -1.0 1.0, 0.0, -1.0
}; };
gfloat vkern[9] = { gfloat vkern[9] = {
1.0, 2.0, 1.0, 1.0, 2.0, 1.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
-1.0, -2.0, -1.0 -1.0, -2.0, -1.0
}; };
shader = g_hash_table_lookup (effects->shaderstable, "xray3"); shader = g_hash_table_lookup (effects->shaderstable, "xray3");
if (!shader) { if (!shader) {
shader = gst_gl_shader_new (); shader = gst_gl_shader_new ();
g_hash_table_insert (effects->shaderstable, "xray3", shader); g_hash_table_insert (effects->shaderstable, "xray3", shader);
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (shader,
gst_gl_shader_compile_and_check (shader, sobel_fragment_source, sobel_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
@ -158,21 +162,21 @@ gst_gl_effects_xray_step_four (gint width, gint height, guint texture, gpointer
} }
void void
gst_gl_effects_xray_step_five (gint width, gint height, guint texture, gpointer stuff) gst_gl_effects_xray_step_five (gint width, gint height, guint texture,
gpointer stuff)
{ {
GstGLEffects* effects = GST_GL_EFFECTS (stuff); GstGLEffects *effects = GST_GL_EFFECTS (stuff);
GstGLShader *shader; GstGLShader *shader;
shader = g_hash_table_lookup (effects->shaderstable, "xray4"); shader = g_hash_table_lookup (effects->shaderstable, "xray4");
if (!shader) { if (!shader) {
shader = gst_gl_shader_new (); shader = gst_gl_shader_new ();
g_hash_table_insert (effects->shaderstable, "xray4", shader); g_hash_table_insert (effects->shaderstable, "xray4", shader);
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (shader,
gst_gl_shader_compile_and_check (shader, multiply_fragment_source, multiply_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
@ -182,37 +186,39 @@ gst_gl_effects_xray_step_five (gint width, gint height, guint texture, gpointer
glActiveTexture (GL_TEXTURE2); glActiveTexture (GL_TEXTURE2);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, effects->midtexture[2]); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, effects->midtexture[2]);
glDisable(GL_TEXTURE_RECTANGLE_ARB); glDisable (GL_TEXTURE_RECTANGLE_ARB);
gst_gl_shader_set_uniform_1i (shader, "base", 2); gst_gl_shader_set_uniform_1i (shader, "base", 2);
glActiveTexture (GL_TEXTURE1); glActiveTexture (GL_TEXTURE1);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
glDisable(GL_TEXTURE_RECTANGLE_ARB); glDisable (GL_TEXTURE_RECTANGLE_ARB);
gst_gl_shader_set_uniform_1f (shader, "alpha", (gfloat) 0.28f); gst_gl_shader_set_uniform_1f (shader, "alpha", (gfloat) 0.28f);
gst_gl_shader_set_uniform_1i (shader, "blend", 1); gst_gl_shader_set_uniform_1i (shader, "blend", 1);
gst_gl_effects_draw_texture (effects, texture); gst_gl_effects_draw_texture (effects, texture);
} }
void gst_gl_effects_xray (GstGLEffects *effects) { void
gst_gl_effects_xray (GstGLEffects * effects)
{
GstGLFilter *filter = GST_GL_FILTER (effects); GstGLFilter *filter = GST_GL_FILTER (effects);
/* map luma to xray curve */ /* map luma to xray curve */
gst_gl_filter_render_to_target (filter, effects->intexture, effects->midtexture[0], gst_gl_filter_render_to_target (filter, effects->intexture,
gst_gl_effects_xray_step_one, effects); effects->midtexture[0], gst_gl_effects_xray_step_one, effects);
/* horizontal blur */ /* horizontal blur */
gst_gl_filter_render_to_target (filter, effects->midtexture[0], effects->midtexture[1], gst_gl_filter_render_to_target (filter, effects->midtexture[0],
gst_gl_effects_xray_step_two, effects); effects->midtexture[1], gst_gl_effects_xray_step_two, effects);
/* vertical blur */ /* vertical blur */
gst_gl_filter_render_to_target (filter, effects->midtexture[1], effects->midtexture[2], gst_gl_filter_render_to_target (filter, effects->midtexture[1],
gst_gl_effects_xray_step_three, effects); effects->midtexture[2], gst_gl_effects_xray_step_three, effects);
/* detect edges with Sobel */ /* detect edges with Sobel */
gst_gl_filter_render_to_target (filter, effects->midtexture[2], effects->midtexture[3], gst_gl_filter_render_to_target (filter, effects->midtexture[2],
gst_gl_effects_xray_step_four, effects); effects->midtexture[3], gst_gl_effects_xray_step_four, effects);
/* multiply edges with the blurred image */ /* multiply edges with the blurred image */
gst_gl_filter_render_to_target (filter, effects->midtexture[3], effects->outtexture, gst_gl_filter_render_to_target (filter, effects->midtexture[3],
gst_gl_effects_xray_step_five, effects); effects->outtexture, gst_gl_effects_xray_step_five, effects);
} }

View file

@ -101,7 +101,8 @@ gst_gl_test_src_smpte (GstGLTestSrc * v, GstGLBuffer * buffer, int w, int h)
vts_colors[i].B * (1 / 255.0f), 1.0f); vts_colors[i].B * (1 / 255.0f), 1.0f);
glBegin (GL_QUADS); glBegin (GL_QUADS);
glVertex3f (-1.0f + i * (2.0f / 7.0f), -1.0f + 2.0 * (2.0f / 3.0f), 0); glVertex3f (-1.0f + i * (2.0f / 7.0f), -1.0f + 2.0 * (2.0f / 3.0f), 0);
glVertex3f (-1.0f + (i + 1.0f) * (2.0f / 7.0f), -1.0f + 2.0f * (2.0f / 3.0f), 0); glVertex3f (-1.0f + (i + 1.0f) * (2.0f / 7.0f),
-1.0f + 2.0f * (2.0f / 3.0f), 0);
glVertex3f (-1.0f + (i + 1.0f) * (2.0f / 7.0f), -1.0f, 0); glVertex3f (-1.0f + (i + 1.0f) * (2.0f / 7.0f), -1.0f, 0);
glVertex3f (-1.0f + i * (2.0f / 7.0f), -1.0f, 0); glVertex3f (-1.0f + i * (2.0f / 7.0f), -1.0f, 0);
glEnd (); glEnd ();
@ -120,8 +121,10 @@ gst_gl_test_src_smpte (GstGLTestSrc * v, GstGLBuffer * buffer, int w, int h)
vts_colors[k].B * (1 / 255.0f), 1.0f); vts_colors[k].B * (1 / 255.0f), 1.0f);
glBegin (GL_QUADS); glBegin (GL_QUADS);
glVertex3f (-1.0f + i * (2.0f / 7.0f), -1.0f + 2.0f * (3.0f / 4.0f), 0); glVertex3f (-1.0f + i * (2.0f / 7.0f), -1.0f + 2.0f * (3.0f / 4.0f), 0);
glVertex3f (-1.0f + (i + 1) * (2.0f / 7.0f), -1.0f + 2.0f * (3.0f / 4.0f), 0); glVertex3f (-1.0f + (i + 1) * (2.0f / 7.0f), -1.0f + 2.0f * (3.0f / 4.0f),
glVertex3f (-1.0f + (i + 1) * (2.0f / 7.0f), -1.0f + 2.0f * (2.0f / 3.0f), 0); 0);
glVertex3f (-1.0f + (i + 1) * (2.0f / 7.0f), -1.0f + 2.0f * (2.0f / 3.0f),
0);
glVertex3f (-1.0f + i * (2.0f / 7.0f), -1.0f + 2.0f * (2.0f / 3.0f), 0); glVertex3f (-1.0f + i * (2.0f / 7.0f), -1.0f + 2.0f * (2.0f / 3.0f), 0);
glEnd (); glEnd ();
} }
@ -142,7 +145,8 @@ gst_gl_test_src_smpte (GstGLTestSrc * v, GstGLBuffer * buffer, int w, int h)
glBegin (GL_QUADS); glBegin (GL_QUADS);
glVertex3f (-1.0f + i * (2.0f / 6.0f), -1.0f + 2.0f * 1, 0); glVertex3f (-1.0f + i * (2.0f / 6.0f), -1.0f + 2.0f * 1, 0);
glVertex3f (-1.0f + (i + 1) * (2.0f / 6.0f), -1.0f + 2.0f * 1, 0); glVertex3f (-1.0f + (i + 1) * (2.0f / 6.0f), -1.0f + 2.0f * 1, 0);
glVertex3f (-1.0f + (i + 1) * (2.0f / 6.0f), -1.0f + 2.0f * (3.0f / 4.0f), 0); glVertex3f (-1.0f + (i + 1) * (2.0f / 6.0f), -1.0f + 2.0f * (3.0f / 4.0f),
0);
glVertex3f (-1.0f + i * (2.0f / 6.0f), -1.0f + 2.0f * (3.0f / 4.0f), 0); glVertex3f (-1.0f + i * (2.0f / 6.0f), -1.0f + 2.0f * (3.0f / 4.0f), 0);
glEnd (); glEnd ();
} }
@ -162,11 +166,12 @@ gst_gl_test_src_smpte (GstGLTestSrc * v, GstGLBuffer * buffer, int w, int h)
vts_colors[k].B * (1 / 255.0f), 1.0f); vts_colors[k].B * (1 / 255.0f), 1.0f);
glBegin (GL_QUADS); glBegin (GL_QUADS);
glVertex3f (-1.0f + 2.0f * (0.5f + i * (1.0f / 12.0f)), -1.0 + 2.0f * 1, 0); glVertex3f (-1.0f + 2.0f * (0.5f + i * (1.0f / 12.0f)), -1.0 + 2.0f * 1, 0);
glVertex3f (-1.0f + 2.0f * (0.5f + (i + 1) * (1.0f / 12.0f)), -1.0f + 2.0f * 1, 0); glVertex3f (-1.0f + 2.0f * (0.5f + (i + 1) * (1.0f / 12.0f)),
-1.0f + 2.0f * 1, 0);
glVertex3f (-1.0f + 2.0f * (0.5f + (i + 1) * (1.0f / 12.0f)), glVertex3f (-1.0f + 2.0f * (0.5f + (i + 1) * (1.0f / 12.0f)),
-1.0f + 2.0f * (3.0f / 4.0f), 0); -1.0f + 2.0f * (3.0f / 4.0f), 0);
glVertex3f (-1.0f + 2.0f * (0.5f + i * (1.0f / 12.0f)), -1.0f + 2.0f * (3.0f / 4.0f), glVertex3f (-1.0f + 2.0f * (0.5f + i * (1.0f / 12.0f)),
0); -1.0f + 2.0f * (3.0f / 4.0f), 0);
glEnd (); glEnd ();
} }

View file

@ -44,7 +44,7 @@
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
static const GstElementDetails element_details = static const GstElementDetails element_details =
GST_ELEMENT_DETAILS ("OpenGL bumper filter", GST_ELEMENT_DETAILS ("OpenGL bumper filter",
"Filter/Effect", "Filter/Effect",
"Bump mapping filter", "Bump mapping filter",
"Cyril Comparon <cyril.comparon@gmail.com>, Julien Isorce <julien.isorce@gmail.com>"); "Cyril Comparon <cyril.comparon@gmail.com>, Julien Isorce <julien.isorce@gmail.com>");
@ -59,98 +59,98 @@ enum
GST_DEBUG_CATEGORY_INIT (gst_gl_bumper_debug, "glbumper", 0, "glbumper element"); GST_DEBUG_CATEGORY_INIT (gst_gl_bumper_debug, "glbumper", 0, "glbumper element");
GST_BOILERPLATE_FULL (GstGLBumper, gst_gl_bumper, GstGLFilter, GST_BOILERPLATE_FULL (GstGLBumper, gst_gl_bumper, GstGLFilter,
GST_TYPE_GL_FILTER, DEBUG_INIT); GST_TYPE_GL_FILTER, DEBUG_INIT);
static void gst_gl_bumper_set_property (GObject * object, guint prop_id, static void gst_gl_bumper_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec); const GValue * value, GParamSpec * pspec);
static void gst_gl_bumper_get_property (GObject * object, guint prop_id, static void gst_gl_bumper_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
static void gst_gl_bumper_reset (GstGLFilter* filter); static void gst_gl_bumper_reset (GstGLFilter * filter);
static void gst_gl_bumper_init_shader (GstGLFilter* filter); static void gst_gl_bumper_init_shader (GstGLFilter * filter);
static gboolean gst_gl_bumper_filter (GstGLFilter * filter, static gboolean gst_gl_bumper_filter (GstGLFilter * filter,
GstGLBuffer * inbuf, GstGLBuffer * outbuf); GstGLBuffer * inbuf, GstGLBuffer * outbuf);
static void gst_gl_bumper_callback (gint width, gint height, guint texture, gpointer stuff); static void gst_gl_bumper_callback (gint width, gint height, guint texture,
gpointer stuff);
//vertex source //vertex source
static const gchar *bumper_v_src = static const gchar *bumper_v_src =
"attribute vec3 aTangent;\n" "attribute vec3 aTangent;\n"
"\n" "\n"
"varying vec3 vNormal;\n" "varying vec3 vNormal;\n"
"varying vec3 vTangent;\n" "varying vec3 vTangent;\n"
"varying vec3 vVertexToLight0;\n" "varying vec3 vVertexToLight0;\n"
"varying vec3 vVertexToLight1;\n" "varying vec3 vVertexToLight1;\n"
"\n" "\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" // transform the vertex\n" " // transform the vertex\n"
" gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" " gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n"
"\n" "\n"
" // transform the normal and the tangent to scene coords\n" " // transform the normal and the tangent to scene coords\n"
" vNormal = normalize(gl_NormalMatrix * gl_Normal);\n" " vNormal = normalize(gl_NormalMatrix * gl_Normal);\n"
" vTangent = normalize(gl_NormalMatrix * aTangent);\n" " vTangent = normalize(gl_NormalMatrix * aTangent);\n"
"\n" "\n"
" // transforming the vertex position to modelview-space\n" " // transforming the vertex position to modelview-space\n"
" //const vec4 vertexInSceneCoords = gl_ModelViewMatrix * gl_Vertex;\n" " //const vec4 vertexInSceneCoords = gl_ModelViewMatrix * gl_Vertex;\n"
"\n" "\n"
" // calculate the vector from the vertex position to the light position\n" " // calculate the vector from the vertex position to the light position\n"
" vVertexToLight0 = normalize(gl_LightSource[0].position).xyz;\n" " vVertexToLight0 = normalize(gl_LightSource[0].position).xyz;\n"
" vVertexToLight1 = normalize(gl_LightSource[1].position).xyz;\n" " vVertexToLight1 = normalize(gl_LightSource[1].position).xyz;\n"
"\n" "\n"
" // transit vertex color\n" " // transit vertex color\n"
" gl_FrontColor = gl_BackColor = gl_Color;\n" " gl_FrontColor = gl_BackColor = gl_Color;\n"
"\n" "\n"
" // use the two first sets of texture coordinates in the fragment shader\n" " // use the two first sets of texture coordinates in the fragment shader\n"
" gl_TexCoord[0] = gl_MultiTexCoord0;\n" " gl_TexCoord[0] = gl_MultiTexCoord0;\n"
" gl_TexCoord[1] = gl_MultiTexCoord1;\n" " gl_TexCoord[1] = gl_MultiTexCoord1;\n" "}\n";
"}\n";
//fragment source //fragment source
static const gchar *bumper_f_src = static const gchar *bumper_f_src =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect texture0;\n" "uniform sampler2DRect texture0;\n"
"uniform sampler2DRect texture1;\n" "uniform sampler2DRect texture1;\n"
"\n" "\n"
"varying vec3 vNormal;\n" "varying vec3 vNormal;\n"
"varying vec3 vTangent;\n" "varying vec3 vTangent;\n"
"varying vec3 vVertexToLight0;\n" "varying vec3 vVertexToLight0;\n"
"varying vec3 vVertexToLight1;\n" "varying vec3 vVertexToLight1;\n"
"\n" "\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" // get the color of the textures\n" " // get the color of the textures\n"
" vec4 textureColor = texture2DRect(texture0, gl_TexCoord[0].st);\n" " vec4 textureColor = texture2DRect(texture0, gl_TexCoord[0].st);\n"
" vec3 normalmapItem = texture2DRect(texture1, gl_TexCoord[1].st).xyz * 2.0 - 1.0;\n" " vec3 normalmapItem = texture2DRect(texture1, gl_TexCoord[1].st).xyz * 2.0 - 1.0;\n"
"\n" "\n"
" // calculate matrix that transform from tangent space to normalmap space (contrary of intuition)\n" " // calculate matrix that transform from tangent space to normalmap space (contrary of intuition)\n"
" vec3 binormal = cross(vNormal, vTangent);\n" " vec3 binormal = cross(vNormal, vTangent);\n"
" mat3 tangentSpace2normalmapSpaceMat = mat3(vTangent, binormal, vNormal);\n" " mat3 tangentSpace2normalmapSpaceMat = mat3(vTangent, binormal, vNormal);\n"
"\n" "\n"
" // disturb the normal\n" " // disturb the normal\n"
" vec3 disturbedNormal = tangentSpace2normalmapSpaceMat * normalmapItem;\n" " vec3 disturbedNormal = tangentSpace2normalmapSpaceMat * normalmapItem;\n"
"\n" "\n"
" // calculate the diffuse term and clamping it to [0;1]\n" " // calculate the diffuse term and clamping it to [0;1]\n"
" float diffuseTerm0 = clamp(dot(disturbedNormal, vVertexToLight0), 0.0, 1.0);\n" " float diffuseTerm0 = clamp(dot(disturbedNormal, vVertexToLight0), 0.0, 1.0);\n"
" float diffuseTerm1 = clamp(dot(disturbedNormal, vVertexToLight1), 0.0, 1.0);\n" " float diffuseTerm1 = clamp(dot(disturbedNormal, vVertexToLight1), 0.0, 1.0);\n"
"\n" "\n"
" vec3 irradiance = (diffuseTerm0 * gl_LightSource[0].diffuse.rgb + diffuseTerm1 * gl_LightSource[1].diffuse.rgb);\n" " vec3 irradiance = (diffuseTerm0 * gl_LightSource[0].diffuse.rgb + diffuseTerm1 * gl_LightSource[1].diffuse.rgb);\n"
"\n" "\n"
" // calculate the final color\n" " // calculate the final color\n"
" gl_FragColor = vec4(irradiance * textureColor.rgb, textureColor.w);\n" " gl_FragColor = vec4(irradiance * textureColor.rgb, textureColor.w);\n"
"}\n"; "}\n";
#define LOAD_ERROR(msg) { GST_WARNING ("unable to load %s: %s", bumper->location, msg); display->isAlive = FALSE; return; } #define LOAD_ERROR(msg) { GST_WARNING ("unable to load %s: %s", bumper->location, msg); display->isAlive = FALSE; return; }
//png reading error handler //png reading error handler
static void static void
user_warning_fn(png_structp png_ptr, png_const_charp warning_msg) user_warning_fn (png_structp png_ptr, png_const_charp warning_msg)
{ {
g_warning("%s\n", warning_msg); g_warning ("%s\n", warning_msg);
} }
//Called in the gl thread //Called in the gl thread
static void static void
gst_gl_bumper_init_resources (GstGLFilter *filter) gst_gl_bumper_init_resources (GstGLFilter * filter)
{ {
GstGLBumper *bumper = GST_GL_BUMPER (filter); GstGLBumper *bumper = GST_GL_BUMPER (filter);
GstGLDisplay *display = filter->display; GstGLDisplay *display = filter->display;
@ -173,80 +173,76 @@ gst_gl_bumper_init_resources (GstGLFilter *filter)
/* BEGIN load png image file */ /* BEGIN load png image file */
if ((fp = fopen(bumper->location, "rb")) == NULL) if ((fp = fopen (bumper->location, "rb")) == NULL)
LOAD_ERROR ("file not found"); LOAD_ERROR ("file not found");
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) if (png_ptr == NULL) {
{ fclose (fp);
fclose(fp);
LOAD_ERROR ("failed to initialize the png_struct"); LOAD_ERROR ("failed to initialize the png_struct");
} }
png_set_error_fn (png_ptr, NULL, NULL, user_warning_fn); png_set_error_fn (png_ptr, NULL, NULL, user_warning_fn);
info_ptr = png_create_info_struct(png_ptr); info_ptr = png_create_info_struct (png_ptr);
if (info_ptr == NULL) if (info_ptr == NULL) {
{ fclose (fp);
fclose(fp); png_destroy_read_struct (&png_ptr, png_infopp_NULL, png_infopp_NULL);
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
LOAD_ERROR ("failed to initialize the memory for image information"); LOAD_ERROR ("failed to initialize the memory for image information");
} }
png_init_io(png_ptr, fp); png_init_io (png_ptr, fp);
png_set_sig_bytes(png_ptr, sig_read); png_set_sig_bytes (png_ptr, sig_read);
png_read_info(png_ptr, info_ptr); png_read_info (png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
&interlace_type, int_p_NULL, int_p_NULL); &interlace_type, int_p_NULL, int_p_NULL);
if (color_type != PNG_COLOR_TYPE_RGB) if (color_type != PNG_COLOR_TYPE_RGB) {
{ fclose (fp);
fclose(fp); png_destroy_read_struct (&png_ptr, png_infopp_NULL, png_infopp_NULL);
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
LOAD_ERROR ("color type is not rgb"); LOAD_ERROR ("color type is not rgb");
} }
raw_data = (guchar*) malloc ( sizeof(guchar) * width * height * 3 ); raw_data = (guchar *) malloc (sizeof (guchar) * width * height * 3);
rows = (guchar**)malloc(sizeof(guchar*) * height); rows = (guchar **) malloc (sizeof (guchar *) * height);
for (y = 0; y < height; ++y) for (y = 0; y < height; ++y)
rows[y] = (guchar*) (raw_data + y * width * 3); rows[y] = (guchar *) (raw_data + y * width * 3);
png_read_image(png_ptr, rows); png_read_image (png_ptr, rows);
free(rows); free (rows);
png_read_end(png_ptr, info_ptr); png_read_end (png_ptr, info_ptr);
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); png_destroy_read_struct (&png_ptr, &info_ptr, png_infopp_NULL);
fclose(fp); fclose (fp);
/* END load png image file */ /* END load png image file */
bumper->bumpmap_width = width; bumper->bumpmap_width = width;
bumper->bumpmap_height = height; bumper->bumpmap_height = height;
glGenTextures (1, &bumper->bumpmap); glGenTextures (1, &bumper->bumpmap);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, bumper->bumpmap); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, bumper->bumpmap);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
bumper->bumpmap_width, bumper->bumpmap_height, 0, bumper->bumpmap_width, bumper->bumpmap_height, 0,
GL_RGB, GL_UNSIGNED_BYTE, raw_data); GL_RGB, GL_UNSIGNED_BYTE, raw_data);
free (raw_data); free (raw_data);
} }
//Called in the gl thread //Called in the gl thread
static void static void
gst_gl_bumper_reset_resources (GstGLFilter *filter) gst_gl_bumper_reset_resources (GstGLFilter * filter)
{ {
GstGLBumper *bumper = GST_GL_BUMPER (filter); GstGLBumper *bumper = GST_GL_BUMPER (filter);
if (bumper->bumpmap) if (bumper->bumpmap) {
{
glDeleteTextures (1, &bumper->bumpmap); glDeleteTextures (1, &bumper->bumpmap);
bumper->bumpmap = 0; bumper->bumpmap = 0;
} }
@ -261,9 +257,9 @@ gst_gl_bumper_base_init (gpointer klass)
} }
static void static void
gst_gl_bumper_class_init (GstGLBumperClass* klass) gst_gl_bumper_class_init (GstGLBumperClass * klass)
{ {
GObjectClass* gobject_class; GObjectClass *gobject_class;
gobject_class = (GObjectClass *) klass; gobject_class = (GObjectClass *) klass;
gobject_class->set_property = gst_gl_bumper_set_property; gobject_class->set_property = gst_gl_bumper_set_property;
@ -276,90 +272,87 @@ gst_gl_bumper_class_init (GstGLBumperClass* klass)
GST_GL_FILTER_CLASS (klass)->onReset = gst_gl_bumper_reset; GST_GL_FILTER_CLASS (klass)->onReset = gst_gl_bumper_reset;
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_LOCATION, g_param_spec_string ("location", PROP_LOCATION, g_param_spec_string ("location",
"Normal map location", "Normal map location",
"Normal map location", "Normal map location", NULL, G_PARAM_READWRITE));
NULL, G_PARAM_READWRITE));
} }
static void static void
gst_gl_bumper_init (GstGLBumper* bumper, gst_gl_bumper_init (GstGLBumper * bumper, GstGLBumperClass * klass)
GstGLBumperClass* klass)
{ {
bumper->shader = NULL; bumper->shader = NULL;
bumper->bumpmap = 0; bumper->bumpmap = 0;
bumper->bumpmap_width = 0; bumper->bumpmap_width = 0;
bumper->bumpmap_height = 0; bumper->bumpmap_height = 0;
bumper->location = NULL; bumper->location = NULL;
} }
static void static void
gst_gl_bumper_reset (GstGLFilter* filter) gst_gl_bumper_reset (GstGLFilter * filter)
{ {
GstGLBumper* bumper_filter = GST_GL_BUMPER(filter); GstGLBumper *bumper_filter = GST_GL_BUMPER (filter);
//blocking call, wait the opengl thread has destroyed the shader //blocking call, wait the opengl thread has destroyed the shader
gst_gl_display_del_shader (filter->display, bumper_filter->shader); gst_gl_display_del_shader (filter->display, bumper_filter->shader);
} }
static void static void
gst_gl_bumper_set_property (GObject* object, guint prop_id, gst_gl_bumper_set_property (GObject * object, guint prop_id,
const GValue* value, GParamSpec* pspec) const GValue * value, GParamSpec * pspec)
{ {
GstGLBumper *bumper = GST_GL_BUMPER (object); GstGLBumper *bumper = GST_GL_BUMPER (object);
switch (prop_id) switch (prop_id) {
{ case PROP_LOCATION:
case PROP_LOCATION: if (bumper->location != NULL)
if (bumper->location != NULL) g_free (bumper->location);
g_free (bumper->location); bumper->location = g_value_dup_string (value);
bumper->location = g_value_dup_string (value); break;
break; default:
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break;
break;
} }
} }
static void static void
gst_gl_bumper_get_property (GObject* object, guint prop_id, gst_gl_bumper_get_property (GObject * object, guint prop_id,
GValue* value, GParamSpec* pspec) GValue * value, GParamSpec * pspec)
{ {
GstGLBumper *bumper = GST_GL_BUMPER (object); GstGLBumper *bumper = GST_GL_BUMPER (object);
switch (prop_id) switch (prop_id) {
{ case PROP_LOCATION:
case PROP_LOCATION: g_value_set_string (value, bumper->location);
g_value_set_string (value, bumper->location); break;
break; default:
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break;
break;
} }
} }
static void static void
gst_gl_bumper_init_shader (GstGLFilter* filter) gst_gl_bumper_init_shader (GstGLFilter * filter)
{ {
GstGLBumper *bumper = GST_GL_BUMPER (filter); GstGLBumper *bumper = GST_GL_BUMPER (filter);
//blocking call, wait the opengl thread has compiled the shader //blocking call, wait the opengl thread has compiled the shader
gst_gl_display_gen_shader (filter->display, bumper_v_src, bumper_f_src, &bumper->shader); gst_gl_display_gen_shader (filter->display, bumper_v_src, bumper_f_src,
&bumper->shader);
} }
static gboolean static gboolean
gst_gl_bumper_filter (GstGLFilter* filter, GstGLBuffer* inbuf, gst_gl_bumper_filter (GstGLFilter * filter, GstGLBuffer * inbuf,
GstGLBuffer* outbuf) GstGLBuffer * outbuf)
{ {
gpointer bumper_filter = GST_GL_BUMPER (filter); gpointer bumper_filter = GST_GL_BUMPER (filter);
//blocking call, use a FBO //blocking call, use a FBO
gst_gl_display_use_fbo (filter->display, filter->width, filter->height, gst_gl_display_use_fbo (filter->display, filter->width, filter->height,
filter->fbo, filter->depthbuffer, outbuf->texture, gst_gl_bumper_callback, filter->fbo, filter->depthbuffer, outbuf->texture, gst_gl_bumper_callback,
inbuf->width, inbuf->height, inbuf->texture, inbuf->width, inbuf->height, inbuf->texture,
//bumper_filter->fovy, bumper_filter->aspect, bumper_filter->znear, bumper_filter->zfar, //bumper_filter->fovy, bumper_filter->aspect, bumper_filter->znear, bumper_filter->zfar,
45, (gdouble)filter->width/(gdouble)filter->height, 0.1, 50, 45, (gdouble) filter->width / (gdouble) filter->height, 0.1, 50,
GST_GL_DISPLAY_PROJECTION_PERSPECIVE, bumper_filter); GST_GL_DISPLAY_PROJECTION_PERSPECIVE, bumper_filter);
return TRUE; return TRUE;
} }
@ -368,48 +361,47 @@ gst_gl_bumper_filter (GstGLFilter* filter, GstGLBuffer* inbuf,
static void static void
gst_gl_bumper_callback (gint width, gint height, guint texture, gpointer stuff) gst_gl_bumper_callback (gint width, gint height, guint texture, gpointer stuff)
{ {
static GLfloat xrot = 0; static GLfloat xrot = 0;
static GLfloat yrot = 0; static GLfloat yrot = 0;
static GLfloat zrot = 0; static GLfloat zrot = 0;
GstGLBumper* bumper = GST_GL_BUMPER (stuff); GstGLBumper *bumper = GST_GL_BUMPER (stuff);
GLint locTangent = 0; GLint locTangent = 0;
//choose the lights //choose the lights
GLfloat light_direction0[] = { 1.0, 0.0, -1.0, 0.0 }; // light goes along -x GLfloat light_direction0[] = { 1.0, 0.0, -1.0, 0.0 }; // light goes along -x
GLfloat light_direction1[] = { -1.0, 0.0, -1.0, 0.0 }; // light goes along x GLfloat light_direction1[] = { -1.0, 0.0, -1.0, 0.0 }; // light goes along x
GLfloat light_diffuse0[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat light_diffuse0[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_diffuse1[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat light_diffuse1[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat mat_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
//eye point //eye point
glMatrixMode(GL_PROJECTION); glMatrixMode (GL_PROJECTION);
gluLookAt(0.0, 0.0, -6.0, gluLookAt (0.0, 0.0, -6.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
0.0, 0.0, 0.0, glMatrixMode (GL_MODELVIEW);
0.0, 1.0, 0.0);
glMatrixMode(GL_MODELVIEW);
//scene conf //scene conf
glEnable(GL_DEPTH_TEST); glEnable (GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL); glDepthFunc (GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glShadeModel(GL_SMOOTH); glShadeModel (GL_SMOOTH);
//set the lights //set the lights
glLightfv(GL_LIGHT0, GL_POSITION, light_direction0); glLightfv (GL_LIGHT0, GL_POSITION, light_direction0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse0); glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse0);
glLightfv(GL_LIGHT1, GL_POSITION, light_direction1); glLightfv (GL_LIGHT1, GL_POSITION, light_direction1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse1); glLightfv (GL_LIGHT1, GL_DIFFUSE, light_diffuse1);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv (GL_FRONT, GL_DIFFUSE, mat_diffuse);
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); glColorMaterial (GL_FRONT_AND_BACK, GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL); glEnable (GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING); glEnable (GL_LIGHTING);
glEnable(GL_LIGHT0); glEnable (GL_LIGHT0);
glEnable(GL_LIGHT1); glEnable (GL_LIGHT1);
//configure shader //configure shader
gst_gl_shader_use (bumper->shader); gst_gl_shader_use (bumper->shader);
locTangent = gst_gl_shader_get_attribute_location (bumper->shader, "aTangent"); locTangent =
gst_gl_shader_get_attribute_location (bumper->shader, "aTangent");
//set the normal map //set the normal map
glActiveTextureARB (GL_TEXTURE1_ARB); glActiveTextureARB (GL_TEXTURE1_ARB);
@ -423,117 +415,123 @@ gst_gl_bumper_callback (gint width, gint height, guint texture, gpointer stuff)
//glTranslatef(2.0f, 2.0f, 5.0f); //glTranslatef(2.0f, 2.0f, 5.0f);
glRotatef(xrot,1.0f,0.0f,0.0f); glRotatef (xrot, 1.0f, 0.0f, 0.0f);
glRotatef(yrot,0.0f,1.0f,0.0f); glRotatef (yrot, 0.0f, 1.0f, 0.0f);
glRotatef(zrot,0.0f,0.0f,1.0f); glRotatef (zrot, 0.0f, 0.0f, 1.0f);
//Cube //Cube
glBegin(GL_QUADS); glBegin (GL_QUADS);
// front face // front face
glNormal3d(0.0, 0.0, -1.0); glNormal3d (0.0, 0.0, -1.0);
glVertexAttrib3dARB(locTangent, 0.0, 1.0, 0.0); glVertexAttrib3dARB (locTangent, 0.0, 1.0, 0.0);
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, 0.0, 0.0); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, 0.0, 0.0);
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, 0.0, 0.0); glMultiTexCoord2dARB (GL_TEXTURE1_ARB, 0.0, 0.0);
glVertex3d( 1.0, 1.0, -1.0); // B glVertex3d (1.0, 1.0, -1.0); // B
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, 0.0, height); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, 0.0, height);
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, 0.0, bumper->bumpmap_height); glMultiTexCoord2dARB (GL_TEXTURE1_ARB, 0.0, bumper->bumpmap_height);
glVertex3d( 1.0, -1.0, -1.0); // A glVertex3d (1.0, -1.0, -1.0); // A
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, width, height); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, width, height);
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, bumper->bumpmap_width, bumper->bumpmap_height); glMultiTexCoord2dARB (GL_TEXTURE1_ARB, bumper->bumpmap_width,
glVertex3d(-1.0, -1.0, -1.0); // D bumper->bumpmap_height);
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, width, 0.0); glVertex3d (-1.0, -1.0, -1.0); // D
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, bumper->bumpmap_width, 0.0); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, width, 0.0);
glVertex3d(-1.0, 1.0, -1.0); // C glMultiTexCoord2dARB (GL_TEXTURE1_ARB, bumper->bumpmap_width, 0.0);
glVertex3d (-1.0, 1.0, -1.0); // C
// right face // right face
glNormal3d(-1.0, 0.0, 0.0); glNormal3d (-1.0, 0.0, 0.0);
glVertexAttrib3dARB(locTangent, 0.0, 1.0, 0.0); glVertexAttrib3dARB (locTangent, 0.0, 1.0, 0.0);
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, 0.0, 0.0); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, 0.0, 0.0);
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, 0.0, 0.0); glMultiTexCoord2dARB (GL_TEXTURE1_ARB, 0.0, 0.0);
glVertex3d(-1.0, 1.0, -1.0); // C glVertex3d (-1.0, 1.0, -1.0); // C
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, 0.0, height); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, 0.0, height);
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, 0.0, bumper->bumpmap_height); glMultiTexCoord2dARB (GL_TEXTURE1_ARB, 0.0, bumper->bumpmap_height);
glVertex3d(-1.0, -1.0, -1.0); // D glVertex3d (-1.0, -1.0, -1.0); // D
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, width, height); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, width, height);
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, bumper->bumpmap_width, bumper->bumpmap_height); glMultiTexCoord2dARB (GL_TEXTURE1_ARB, bumper->bumpmap_width,
glVertex3d(-1.0, -1.0, 1.0); // H bumper->bumpmap_height);
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, width, 0.0); glVertex3d (-1.0, -1.0, 1.0); // H
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, bumper->bumpmap_width, 0.0); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, width, 0.0);
glVertex3d(-1.0, 1.0, 1.0); // G glMultiTexCoord2dARB (GL_TEXTURE1_ARB, bumper->bumpmap_width, 0.0);
glVertex3d (-1.0, 1.0, 1.0); // G
// back face // back face
glNormal3d(0.0, 0.0, 1.0); glNormal3d (0.0, 0.0, 1.0);
glVertexAttrib3dARB(locTangent, 0.0, 1.0, 0.0); glVertexAttrib3dARB (locTangent, 0.0, 1.0, 0.0);
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, 0.0, 0.0); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, 0.0, 0.0);
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, 0.0, 0.0); glMultiTexCoord2dARB (GL_TEXTURE1_ARB, 0.0, 0.0);
glVertex3d(-1.0, 1.0, 1.0); // G glVertex3d (-1.0, 1.0, 1.0); // G
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, 0.0, height); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, 0.0, height);
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, 0.0, bumper->bumpmap_height); glMultiTexCoord2dARB (GL_TEXTURE1_ARB, 0.0, bumper->bumpmap_height);
glVertex3d(-1.0, -1.0, 1.0); // H glVertex3d (-1.0, -1.0, 1.0); // H
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, width, height); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, width, height);
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, bumper->bumpmap_width, bumper->bumpmap_height); glMultiTexCoord2dARB (GL_TEXTURE1_ARB, bumper->bumpmap_width,
glVertex3d( 1.0, -1.0, 1.0); // E bumper->bumpmap_height);
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, width, 0.0); glVertex3d (1.0, -1.0, 1.0); // E
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, bumper->bumpmap_width, 0.0); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, width, 0.0);
glVertex3d( 1.0, 1.0, 1.0); // F glMultiTexCoord2dARB (GL_TEXTURE1_ARB, bumper->bumpmap_width, 0.0);
glVertex3d (1.0, 1.0, 1.0); // F
// left face // left face
glNormal3d(1.0, 0.0, 0.0); glNormal3d (1.0, 0.0, 0.0);
glVertexAttrib3dARB(locTangent, 0.0, 1.0, 0.0); glVertexAttrib3dARB (locTangent, 0.0, 1.0, 0.0);
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, 0.0, 0.0); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, 0.0, 0.0);
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, 0.0, 0.0); glMultiTexCoord2dARB (GL_TEXTURE1_ARB, 0.0, 0.0);
glVertex3d( 1.0, 1.0, 1.0); // F glVertex3d (1.0, 1.0, 1.0); // F
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, 0.0, height); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, 0.0, height);
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, 0.0, bumper->bumpmap_height); glMultiTexCoord2dARB (GL_TEXTURE1_ARB, 0.0, bumper->bumpmap_height);
glVertex3d( 1.0, -1.0, 1.0); // E glVertex3d (1.0, -1.0, 1.0); // E
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, width, height); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, width, height);
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, bumper->bumpmap_width, bumper->bumpmap_height); glMultiTexCoord2dARB (GL_TEXTURE1_ARB, bumper->bumpmap_width,
glVertex3d( 1.0, -1.0, -1.0); // A bumper->bumpmap_height);
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, width, 0.0); glVertex3d (1.0, -1.0, -1.0); // A
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, bumper->bumpmap_width, 0.0); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, width, 0.0);
glVertex3d( 1.0, 1.0, -1.0); // B glMultiTexCoord2dARB (GL_TEXTURE1_ARB, bumper->bumpmap_width, 0.0);
glVertex3d (1.0, 1.0, -1.0); // B
// top face // top face
glNormal3d(0.0, 1.0, 0.0); glNormal3d (0.0, 1.0, 0.0);
glVertexAttrib3dARB(locTangent, 0.0, 0.0, 1.0); glVertexAttrib3dARB (locTangent, 0.0, 0.0, 1.0);
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, 0.0, 0.0); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, 0.0, 0.0);
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, 0.0, 0.0); glMultiTexCoord2dARB (GL_TEXTURE1_ARB, 0.0, 0.0);
glVertex3d( 1.0, 1.0, 1.0); // F glVertex3d (1.0, 1.0, 1.0); // F
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, 0.0, height); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, 0.0, height);
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, 0.0, bumper->bumpmap_height); glMultiTexCoord2dARB (GL_TEXTURE1_ARB, 0.0, bumper->bumpmap_height);
glVertex3d( 1.0, 1.0, -1.0); // B glVertex3d (1.0, 1.0, -1.0); // B
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, width, height); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, width, height);
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, bumper->bumpmap_width, bumper->bumpmap_height); glMultiTexCoord2dARB (GL_TEXTURE1_ARB, bumper->bumpmap_width,
glVertex3d(-1.0, 1.0, -1.0); // C bumper->bumpmap_height);
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, width, 0.0); glVertex3d (-1.0, 1.0, -1.0); // C
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, bumper->bumpmap_width, 0.0); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, width, 0.0);
glVertex3d(-1.0, 1.0, 1.0); // G glMultiTexCoord2dARB (GL_TEXTURE1_ARB, bumper->bumpmap_width, 0.0);
glVertex3d (-1.0, 1.0, 1.0); // G
// bottom face // bottom face
glNormal3d(0.0, -1.0, 0.0); glNormal3d (0.0, -1.0, 0.0);
glVertexAttrib3dARB(locTangent, 0.0, 0.0, -1.0); glVertexAttrib3dARB (locTangent, 0.0, 0.0, -1.0);
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, 0.0, 0.0); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, 0.0, 0.0);
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, 0.0, 0.0); glMultiTexCoord2dARB (GL_TEXTURE1_ARB, 0.0, 0.0);
glVertex3d( 1.0, -1.0, -1.0); // A glVertex3d (1.0, -1.0, -1.0); // A
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, 0.0, height); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, 0.0, height);
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, 0.0, bumper->bumpmap_height); glMultiTexCoord2dARB (GL_TEXTURE1_ARB, 0.0, bumper->bumpmap_height);
glVertex3d( 1.0, -1.0, 1.0); // E glVertex3d (1.0, -1.0, 1.0); // E
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, width, height); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, width, height);
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, bumper->bumpmap_width, bumper->bumpmap_height); glMultiTexCoord2dARB (GL_TEXTURE1_ARB, bumper->bumpmap_width,
glVertex3d(-1.0, -1.0, 1.0); // H bumper->bumpmap_height);
glMultiTexCoord2dARB(GL_TEXTURE0_ARB, width, 0.0); glVertex3d (-1.0, -1.0, 1.0); // H
glMultiTexCoord2dARB(GL_TEXTURE1_ARB, bumper->bumpmap_width, 0.0); glMultiTexCoord2dARB (GL_TEXTURE0_ARB, width, 0.0);
glVertex3d(-1.0, -1.0, -1.0); // D glMultiTexCoord2dARB (GL_TEXTURE1_ARB, bumper->bumpmap_width, 0.0);
glEnd(); glVertex3d (-1.0, -1.0, -1.0); // D
glEnd ();
glUseProgram(0); glUseProgram (0);
glDisable(GL_LIGHT0); glDisable (GL_LIGHT0);
glDisable(GL_LIGHT1); glDisable (GL_LIGHT1);
glDisable(GL_LIGHTING); glDisable (GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL); glDisable (GL_COLOR_MATERIAL);
xrot+=1.0f; xrot += 1.0f;
yrot+=0.9f; yrot += 0.9f;
zrot+=1.1f; zrot += 1.1f;
} }

View file

@ -51,17 +51,17 @@
#define GST_CAT_DEFAULT gst_gl_colorscale_debug #define GST_CAT_DEFAULT gst_gl_colorscale_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
static const GstElementDetails element_details = static const GstElementDetails element_details =
GST_ELEMENT_DETAILS ("OpenGL color scale", GST_ELEMENT_DETAILS ("OpenGL color scale",
"Filter/Effect", "Filter/Effect",
"Colorspace converter and video scaler", "Colorspace converter and video scaler",
"Julien Isorce <julien.isorce@gmail.com>"); "Julien Isorce <julien.isorce@gmail.com>");
/* Source pad definition */ /* Source pad definition */
static GstStaticPadTemplate gst_gl_colorscale_src_pad_template = static GstStaticPadTemplate gst_gl_colorscale_src_pad_template =
GST_STATIC_PAD_TEMPLATE ("src", GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC, GST_PAD_SRC,
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBx ";" GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBx ";"
@ -86,7 +86,7 @@ static GstStaticPadTemplate gst_gl_colorscale_sink_pad_template =
/* Properties */ /* Properties */
enum enum
{ {
PROP_0 PROP_0
}; };
#define DEBUG_INIT(bla) \ #define DEBUG_INIT(bla) \
@ -95,398 +95,379 @@ enum
GST_BOILERPLATE_FULL (GstGLColorscale, gst_gl_colorscale, GstBaseTransform, GST_BOILERPLATE_FULL (GstGLColorscale, gst_gl_colorscale, GstBaseTransform,
GST_TYPE_BASE_TRANSFORM, DEBUG_INIT); GST_TYPE_BASE_TRANSFORM, DEBUG_INIT);
static void gst_gl_colorscale_set_property (GObject* object, guint prop_id, static void gst_gl_colorscale_set_property (GObject * object, guint prop_id,
const GValue* value, GParamSpec* pspec); const GValue * value, GParamSpec * pspec);
static void gst_gl_colorscale_get_property (GObject* object, guint prop_id, static void gst_gl_colorscale_get_property (GObject * object, guint prop_id,
GValue* value, GParamSpec* pspec); GValue * value, GParamSpec * pspec);
static void gst_gl_colorscale_reset (GstGLColorscale* colorscale); static void gst_gl_colorscale_reset (GstGLColorscale * colorscale);
static gboolean gst_gl_colorscale_set_caps (GstBaseTransform* bt, static gboolean gst_gl_colorscale_set_caps (GstBaseTransform * bt,
GstCaps* incaps, GstCaps* outcaps); GstCaps * incaps, GstCaps * outcaps);
static GstCaps *gst_gl_colorscale_transform_caps (GstBaseTransform* bt, static GstCaps *gst_gl_colorscale_transform_caps (GstBaseTransform * bt,
GstPadDirection direction, GstCaps* caps); GstPadDirection direction, GstCaps * caps);
static void gst_gl_colorscale_fixate_caps (GstBaseTransform* base, GstPadDirection direction, static void gst_gl_colorscale_fixate_caps (GstBaseTransform * base,
GstCaps* caps, GstCaps* othercaps); GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
static gboolean gst_gl_colorscale_start (GstBaseTransform* bt); static gboolean gst_gl_colorscale_start (GstBaseTransform * bt);
static gboolean gst_gl_colorscale_stop (GstBaseTransform* bt); static gboolean gst_gl_colorscale_stop (GstBaseTransform * bt);
static GstFlowReturn gst_gl_colorscale_transform (GstBaseTransform* trans, static GstFlowReturn gst_gl_colorscale_transform (GstBaseTransform * trans,
GstBuffer* inbuf, GstBuffer * outbuf); GstBuffer * inbuf, GstBuffer * outbuf);
static gboolean gst_gl_colorscale_get_unit_size (GstBaseTransform* trans, static gboolean gst_gl_colorscale_get_unit_size (GstBaseTransform * trans,
GstCaps* caps, guint* size); GstCaps * caps, guint * size);
static void static void
gst_gl_colorscale_base_init (gpointer klass) gst_gl_colorscale_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_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_colorscale_src_pad_template)); gst_static_pad_template_get (&gst_gl_colorscale_src_pad_template));
gst_element_class_add_pad_template (element_class, gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_gl_colorscale_sink_pad_template)); gst_static_pad_template_get (&gst_gl_colorscale_sink_pad_template));
} }
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;
gobject_class->get_property = gst_gl_colorscale_get_property; gobject_class->get_property = gst_gl_colorscale_get_property;
GST_BASE_TRANSFORM_CLASS (klass)->transform_caps = GST_BASE_TRANSFORM_CLASS (klass)->transform_caps =
gst_gl_colorscale_transform_caps; gst_gl_colorscale_transform_caps;
GST_BASE_TRANSFORM_CLASS (klass)->fixate_caps = gst_gl_colorscale_fixate_caps; GST_BASE_TRANSFORM_CLASS (klass)->fixate_caps = gst_gl_colorscale_fixate_caps;
GST_BASE_TRANSFORM_CLASS (klass)->transform = gst_gl_colorscale_transform; GST_BASE_TRANSFORM_CLASS (klass)->transform = gst_gl_colorscale_transform;
GST_BASE_TRANSFORM_CLASS (klass)->start = gst_gl_colorscale_start; GST_BASE_TRANSFORM_CLASS (klass)->start = gst_gl_colorscale_start;
GST_BASE_TRANSFORM_CLASS (klass)->stop = gst_gl_colorscale_stop; GST_BASE_TRANSFORM_CLASS (klass)->stop = gst_gl_colorscale_stop;
GST_BASE_TRANSFORM_CLASS (klass)->set_caps = gst_gl_colorscale_set_caps; GST_BASE_TRANSFORM_CLASS (klass)->set_caps = gst_gl_colorscale_set_caps;
GST_BASE_TRANSFORM_CLASS (klass)->get_unit_size = gst_gl_colorscale_get_unit_size; GST_BASE_TRANSFORM_CLASS (klass)->get_unit_size =
gst_gl_colorscale_get_unit_size;
} }
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);
} }
static void static void
gst_gl_colorscale_set_property (GObject* object, guint prop_id, gst_gl_colorscale_set_property (GObject * object, guint prop_id,
const GValue* value, GParamSpec* pspec) const GValue * value, GParamSpec * pspec)
{ {
//GstGLColorscale* colorscale = GST_GL_COLORSCALE (object); //GstGLColorscale* colorscale = GST_GL_COLORSCALE (object);
switch (prop_id) switch (prop_id) {
{ default:
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break;
break; }
}
} }
static void static void
gst_gl_colorscale_get_property (GObject* object, guint prop_id, gst_gl_colorscale_get_property (GObject * object, guint prop_id,
GValue* value, GParamSpec* pspec) GValue * value, GParamSpec * pspec)
{ {
//GstGLColorscale *colorscale = GST_GL_COLORSCALE (object); //GstGLColorscale *colorscale = GST_GL_COLORSCALE (object);
switch (prop_id) switch (prop_id) {
{ default:
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break;
break; }
}
} }
static void static void
gst_gl_colorscale_reset (GstGLColorscale* colorscale) gst_gl_colorscale_reset (GstGLColorscale * colorscale)
{ {
if (colorscale->display) if (colorscale->display) {
{ g_object_unref (colorscale->display);
g_object_unref (colorscale->display); colorscale->display = NULL;
colorscale->display = NULL; }
}
} }
static gboolean static gboolean
gst_gl_colorscale_start (GstBaseTransform* bt) gst_gl_colorscale_start (GstBaseTransform * bt)
{ {
//GstGLColorscale* colorscale = GST_GL_COLORSCALE (bt); //GstGLColorscale* colorscale = GST_GL_COLORSCALE (bt);
return TRUE; return TRUE;
} }
static gboolean static gboolean
gst_gl_colorscale_stop (GstBaseTransform* bt) gst_gl_colorscale_stop (GstBaseTransform * bt)
{ {
GstGLColorscale* colorscale = GST_GL_COLORSCALE (bt); GstGLColorscale *colorscale = GST_GL_COLORSCALE (bt);
gst_gl_colorscale_reset (colorscale); gst_gl_colorscale_reset (colorscale);
return TRUE; return TRUE;
} }
static GstCaps* static GstCaps *
gst_gl_colorscale_transform_caps (GstBaseTransform* bt, gst_gl_colorscale_transform_caps (GstBaseTransform * bt,
GstPadDirection direction, GstCaps* caps) GstPadDirection direction, GstCaps * caps)
{ {
//GstGLColorscale* colorscale = GST_GL_COLORSCALE (bt); //GstGLColorscale* colorscale = GST_GL_COLORSCALE (bt);
GstStructure* structure = gst_caps_get_structure (caps, 0); GstStructure *structure = gst_caps_get_structure (caps, 0);
GstCaps* newcaps = gst_caps_new_simple ("video/x-raw-yuv", NULL); GstCaps *newcaps = gst_caps_new_simple ("video/x-raw-yuv", NULL);
GstCaps* newothercaps = gst_caps_new_simple ("video/x-raw-rgb", NULL); GstCaps *newothercaps = gst_caps_new_simple ("video/x-raw-rgb", NULL);
const GValue* framerate_value = NULL; const GValue *framerate_value = NULL;
const GValue* par_value = NULL; const GValue *par_value = NULL;
GST_DEBUG ("transform caps %" GST_PTR_FORMAT, caps); GST_DEBUG ("transform caps %" GST_PTR_FORMAT, caps);
framerate_value = gst_structure_get_value (structure, "framerate"); framerate_value = gst_structure_get_value (structure, "framerate");
par_value = gst_structure_get_value (structure, "pixel-aspect-ratio"); par_value = gst_structure_get_value (structure, "pixel-aspect-ratio");
gst_caps_append(newcaps, newothercaps); gst_caps_append (newcaps, newothercaps);
structure = gst_structure_copy (gst_caps_get_structure (newcaps, 0)); structure = gst_structure_copy (gst_caps_get_structure (newcaps, 0));
gst_structure_set (structure, gst_structure_set (structure,
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT, "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"height", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
gst_structure_set_value (structure, "framerate", framerate_value); gst_structure_set_value (structure, "framerate", framerate_value);
if (par_value) if (par_value)
gst_structure_set_value (structure, "pixel-aspect-ratio", par_value); gst_structure_set_value (structure, "pixel-aspect-ratio", par_value);
else else
gst_structure_set (structure, "pixel-aspect-ratio", GST_TYPE_FRACTION, gst_structure_set (structure, "pixel-aspect-ratio", GST_TYPE_FRACTION,
1, 1, NULL); 1, 1, NULL);
gst_caps_merge_structure (newcaps, gst_structure_copy (structure)); gst_caps_merge_structure (newcaps, gst_structure_copy (structure));
GST_DEBUG ("new caps %" GST_PTR_FORMAT, newcaps); GST_DEBUG ("new caps %" GST_PTR_FORMAT, newcaps);
return newcaps; return newcaps;
} }
/* from gst-plugins-base "videoscale" code */ /* from gst-plugins-base "videoscale" code */
static void static void
gst_gl_colorscale_fixate_caps (GstBaseTransform* base, GstPadDirection direction, gst_gl_colorscale_fixate_caps (GstBaseTransform * base,
GstCaps* caps, GstCaps* othercaps) GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
{ {
GstStructure *ins, *outs; GstStructure *ins, *outs;
const GValue *from_par, *to_par; const GValue *from_par, *to_par;
g_return_if_fail (gst_caps_is_fixed (caps)); g_return_if_fail (gst_caps_is_fixed (caps));
GST_DEBUG_OBJECT (base, "trying to fixate othercaps %" GST_PTR_FORMAT GST_DEBUG_OBJECT (base, "trying to fixate othercaps %" GST_PTR_FORMAT
" based on caps %" GST_PTR_FORMAT, othercaps, caps); " based on caps %" GST_PTR_FORMAT, othercaps, caps);
ins = gst_caps_get_structure (caps, 0); ins = gst_caps_get_structure (caps, 0);
outs = gst_caps_get_structure (othercaps, 0); outs = gst_caps_get_structure (othercaps, 0);
from_par = gst_structure_get_value (ins, "pixel-aspect-ratio"); from_par = gst_structure_get_value (ins, "pixel-aspect-ratio");
to_par = gst_structure_get_value (outs, "pixel-aspect-ratio"); to_par = gst_structure_get_value (outs, "pixel-aspect-ratio");
//we have both PAR but they might not be fixated //we have both PAR but they might not be fixated
if (from_par && to_par) if (from_par && to_par) {
{ gint from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d;
gint from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d;
gint count = 0, w = 0, h = 0; gint count = 0, w = 0, h = 0;
guint num, den; guint num, den;
//from_par should be fixed //from_par should be fixed
g_return_if_fail (gst_value_is_fixed (from_par)); g_return_if_fail (gst_value_is_fixed (from_par));
from_par_n = gst_value_get_fraction_numerator (from_par); from_par_n = gst_value_get_fraction_numerator (from_par);
from_par_d = gst_value_get_fraction_denominator (from_par); from_par_d = gst_value_get_fraction_denominator (from_par);
//fixate the out PAR //fixate the out PAR
if (!gst_value_is_fixed (to_par)) if (!gst_value_is_fixed (to_par)) {
{ GST_DEBUG_OBJECT (base, "fixating to_par to %dx%d", from_par_n,
GST_DEBUG_OBJECT (base, "fixating to_par to %dx%d", from_par_n, from_par_d);
from_par_d); gst_structure_fixate_field_nearest_fraction (outs, "pixel-aspect-ratio",
gst_structure_fixate_field_nearest_fraction (outs, "pixel-aspect-ratio", from_par_n, from_par_d);
from_par_n, from_par_d);
}
to_par_n = gst_value_get_fraction_numerator (to_par);
to_par_d = gst_value_get_fraction_denominator (to_par);
//f both width and height are already fixed, we can't do anything
//about it anymore
if (gst_structure_get_int (outs, "width", &w))
++count;
if (gst_structure_get_int (outs, "height", &h))
++count;
if (count == 2)
{
GST_DEBUG_OBJECT (base, "dimensions already set to %dx%d, not fixating",
w, h);
return;
}
gst_structure_get_int (ins, "width", &from_w);
gst_structure_get_int (ins, "height", &from_h);
if (!gst_video_calculate_display_ratio (&num, &den, from_w, from_h,
from_par_n, from_par_d, to_par_n, to_par_d))
{
GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
("Error calculating the output scaled size - integer overflow"));
return;
}
GST_DEBUG_OBJECT (base,
"scaling input with %dx%d and PAR %d/%d to output PAR %d/%d",
from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d);
GST_DEBUG_OBJECT (base, "resulting output should respect ratio of %d/%d",
num, den);
//now find a width x height that respects this display ratio.
//prefer those that have one of w/h the same as the incoming video
//using wd / hd = num / den
//if one of the output width or height is fixed, we work from there
if (h)
{
GST_DEBUG_OBJECT (base, "height is fixed,scaling width");
w = (guint) gst_util_uint64_scale_int (h, num, den);
}
else if (w)
{
GST_DEBUG_OBJECT (base, "width is fixed, scaling height");
h = (guint) gst_util_uint64_scale_int (w, den, num);
}
else
{
//none of width or height is fixed, figure out both of them based only on
//the input width and height
//check hd / den is an integer scale factor, and scale wd with the PAR
if (from_h % den == 0)
{
GST_DEBUG_OBJECT (base, "keeping video height");
h = from_h;
w = (guint) gst_util_uint64_scale_int (h, num, den);
}
else if (from_w % num == 0)
{
GST_DEBUG_OBJECT (base, "keeping video width");
w = from_w;
h = (guint) gst_util_uint64_scale_int (w, den, num);
}
else
{
GST_DEBUG_OBJECT (base, "approximating but keeping video height");
h = from_h;
w = (guint) gst_util_uint64_scale_int (h, num, den);
}
}
GST_DEBUG_OBJECT (base, "scaling to %dx%d", w, h);
//now fixate
gst_structure_fixate_field_nearest_int (outs, "width", w);
gst_structure_fixate_field_nearest_int (outs, "height", h);
}
else
{
gint width, height;
if (gst_structure_get_int (ins, "width", &width))
{
if (gst_structure_has_field (outs, "width"))
gst_structure_fixate_field_nearest_int (outs, "width", width);
}
if (gst_structure_get_int (ins, "height", &height)) {
if (gst_structure_has_field (outs, "height")) {
gst_structure_fixate_field_nearest_int (outs, "height", height);
}
}
} }
GST_DEBUG_OBJECT (base, "fixated othercaps to %" GST_PTR_FORMAT, othercaps); to_par_n = gst_value_get_fraction_numerator (to_par);
to_par_d = gst_value_get_fraction_denominator (to_par);
//f both width and height are already fixed, we can't do anything
//about it anymore
if (gst_structure_get_int (outs, "width", &w))
++count;
if (gst_structure_get_int (outs, "height", &h))
++count;
if (count == 2) {
GST_DEBUG_OBJECT (base, "dimensions already set to %dx%d, not fixating",
w, h);
return;
}
gst_structure_get_int (ins, "width", &from_w);
gst_structure_get_int (ins, "height", &from_h);
if (!gst_video_calculate_display_ratio (&num, &den, from_w, from_h,
from_par_n, from_par_d, to_par_n, to_par_d)) {
GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
("Error calculating the output scaled size - integer overflow"));
return;
}
GST_DEBUG_OBJECT (base,
"scaling input with %dx%d and PAR %d/%d to output PAR %d/%d",
from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d);
GST_DEBUG_OBJECT (base, "resulting output should respect ratio of %d/%d",
num, den);
//now find a width x height that respects this display ratio.
//prefer those that have one of w/h the same as the incoming video
//using wd / hd = num / den
//if one of the output width or height is fixed, we work from there
if (h) {
GST_DEBUG_OBJECT (base, "height is fixed,scaling width");
w = (guint) gst_util_uint64_scale_int (h, num, den);
} else if (w) {
GST_DEBUG_OBJECT (base, "width is fixed, scaling height");
h = (guint) gst_util_uint64_scale_int (w, den, num);
} else {
//none of width or height is fixed, figure out both of them based only on
//the input width and height
//check hd / den is an integer scale factor, and scale wd with the PAR
if (from_h % den == 0) {
GST_DEBUG_OBJECT (base, "keeping video height");
h = from_h;
w = (guint) gst_util_uint64_scale_int (h, num, den);
} else if (from_w % num == 0) {
GST_DEBUG_OBJECT (base, "keeping video width");
w = from_w;
h = (guint) gst_util_uint64_scale_int (w, den, num);
} else {
GST_DEBUG_OBJECT (base, "approximating but keeping video height");
h = from_h;
w = (guint) gst_util_uint64_scale_int (h, num, den);
}
}
GST_DEBUG_OBJECT (base, "scaling to %dx%d", w, h);
//now fixate
gst_structure_fixate_field_nearest_int (outs, "width", w);
gst_structure_fixate_field_nearest_int (outs, "height", h);
} else {
gint width, height;
if (gst_structure_get_int (ins, "width", &width)) {
if (gst_structure_has_field (outs, "width"))
gst_structure_fixate_field_nearest_int (outs, "width", width);
}
if (gst_structure_get_int (ins, "height", &height)) {
if (gst_structure_has_field (outs, "height")) {
gst_structure_fixate_field_nearest_int (outs, "height", height);
}
}
}
GST_DEBUG_OBJECT (base, "fixated othercaps to %" GST_PTR_FORMAT, othercaps);
} }
static gboolean static gboolean
gst_gl_colorscale_set_caps (GstBaseTransform* bt, GstCaps* incaps, gst_gl_colorscale_set_caps (GstBaseTransform * bt, GstCaps * incaps,
GstCaps* outcaps) GstCaps * outcaps)
{ {
GstGLColorscale* colorscale = GST_GL_COLORSCALE (bt); GstGLColorscale *colorscale = GST_GL_COLORSCALE (bt);
gboolean ret = FALSE; gboolean ret = FALSE;
GST_DEBUG ("called with %" GST_PTR_FORMAT, incaps); GST_DEBUG ("called with %" GST_PTR_FORMAT, incaps);
ret = gst_video_format_parse_caps (outcaps, &colorscale->output_video_format, ret = gst_video_format_parse_caps (outcaps, &colorscale->output_video_format,
&colorscale->output_video_width, &colorscale->output_video_height); &colorscale->output_video_width, &colorscale->output_video_height);
ret |= gst_video_format_parse_caps (incaps, &colorscale->input_video_format, ret |= gst_video_format_parse_caps (incaps, &colorscale->input_video_format,
&colorscale->input_video_width, &colorscale->input_video_height); &colorscale->input_video_width, &colorscale->input_video_height);
if (!ret) if (!ret) {
{ GST_DEBUG ("bad caps");
GST_DEBUG ("bad caps"); return FALSE;
return FALSE; }
}
colorscale->display = gst_gl_display_new (); colorscale->display = gst_gl_display_new ();
//init unvisible opengl context //init unvisible opengl context
gst_gl_display_create_context (colorscale->display, gst_gl_display_create_context (colorscale->display,
colorscale->output_video_width, colorscale->output_video_height); colorscale->output_video_width, colorscale->output_video_height);
//blocking call, init colorspace conversion if needed //blocking call, init colorspace conversion if needed
gst_gl_display_init_upload (colorscale->display, colorscale->input_video_format, gst_gl_display_init_upload (colorscale->display,
colorscale->output_video_width, colorscale->output_video_height, colorscale->input_video_format, colorscale->output_video_width,
colorscale->input_video_width, colorscale->input_video_height); colorscale->output_video_height, colorscale->input_video_width,
colorscale->input_video_height);
//blocking call, init colorspace conversion if needed //blocking call, init colorspace conversion if needed
gst_gl_display_init_download (colorscale->display, colorscale->output_video_format, gst_gl_display_init_download (colorscale->display,
colorscale->output_video_width, colorscale->output_video_height); colorscale->output_video_format, colorscale->output_video_width,
colorscale->output_video_height);
return ret; return ret;
} }
static gboolean static gboolean
gst_gl_colorscale_get_unit_size (GstBaseTransform* trans, GstCaps* caps, gst_gl_colorscale_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
guint* size) guint * size)
{ {
gboolean ret; gboolean ret;
GstStructure *structure; GstStructure *structure;
gint width; gint width;
gint height; gint height;
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")) {
{ ret = gst_gl_buffer_parse_caps (caps, &width, &height);
ret = gst_gl_buffer_parse_caps (caps, &width, &height); if (ret)
if (ret) *size = gst_gl_buffer_get_size (width, height);
*size = gst_gl_buffer_get_size (width, height); } else {
} GstVideoFormat video_format;
else
{
GstVideoFormat video_format;
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)
*size = gst_video_format_get_size (video_format, width, height); *size = gst_video_format_get_size (video_format, width, height);
} }
return TRUE; return TRUE;
} }
static GstFlowReturn static GstFlowReturn
gst_gl_colorscale_transform (GstBaseTransform* trans, GstBuffer* inbuf, gst_gl_colorscale_transform (GstBaseTransform * trans, GstBuffer * inbuf,
GstBuffer* outbuf) GstBuffer * outbuf)
{ {
GstGLColorscale* colorscale = GST_GL_COLORSCALE (trans); GstGLColorscale *colorscale = GST_GL_COLORSCALE (trans);
gboolean isAlive = TRUE; gboolean isAlive = TRUE;
//blocking call //blocking call
GstGLBuffer* gl_temp_buffer = gst_gl_buffer_new (colorscale->display, GstGLBuffer *gl_temp_buffer = gst_gl_buffer_new (colorscale->display,
colorscale->output_video_width, colorscale->output_video_height); colorscale->output_video_width, colorscale->output_video_height);
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
isAlive = gst_gl_display_do_upload (colorscale->display, gl_temp_buffer->texture, isAlive =
colorscale->input_video_width, colorscale->input_video_height, gst_gl_display_do_upload (colorscale->display, gl_temp_buffer->texture,
GST_BUFFER_DATA (inbuf)); colorscale->input_video_width, colorscale->input_video_height,
GST_BUFFER_DATA (inbuf));
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
isAlive &= gst_gl_display_do_download(colorscale->display, gl_temp_buffer->texture, isAlive &=
gl_temp_buffer->width, gl_temp_buffer->height, gst_gl_display_do_download (colorscale->display, gl_temp_buffer->texture,
GST_BUFFER_DATA (outbuf)); gl_temp_buffer->width, gl_temp_buffer->height, GST_BUFFER_DATA (outbuf));
gst_buffer_unref (gl_temp_buffer); gst_buffer_unref (gl_temp_buffer);
if (isAlive) if (isAlive)
return GST_FLOW_OK; return GST_FLOW_OK;
else else
return GST_FLOW_UNEXPECTED; return GST_FLOW_UNEXPECTED;
} }

View file

@ -52,7 +52,7 @@ struct _GstGLDifferenceMatte
GstGLFilter filter; GstGLFilter filter;
GstGLShader *shader[4]; GstGLShader *shader[4];
gchar *location; gchar *location;
gboolean bg_has_changed; gboolean bg_has_changed;
@ -78,26 +78,26 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
GST_DEBUG_CATEGORY_INIT (gst_gl_differencematte_debug, "gldifferencematte", 0, "gldifferencematte element"); GST_DEBUG_CATEGORY_INIT (gst_gl_differencematte_debug, "gldifferencematte", 0, "gldifferencematte element");
GST_BOILERPLATE_FULL (GstGLDifferenceMatte, gst_gl_differencematte, GstGLFilter, GST_BOILERPLATE_FULL (GstGLDifferenceMatte, gst_gl_differencematte, GstGLFilter,
GST_TYPE_GL_FILTER, DEBUG_INIT); GST_TYPE_GL_FILTER, DEBUG_INIT);
static void gst_gl_differencematte_set_property (GObject * object, guint prop_id, static void gst_gl_differencematte_set_property (GObject * object,
const GValue * value, GParamSpec * pspec); guint prop_id, const GValue * value, GParamSpec * pspec);
static void gst_gl_differencematte_get_property (GObject * object, guint prop_id, static void gst_gl_differencematte_get_property (GObject * object,
GValue * value, GParamSpec * pspec); guint prop_id, GValue * value, GParamSpec * pspec);
static void gst_gl_differencematte_init_resources (GstGLFilter* filter); static void gst_gl_differencematte_init_resources (GstGLFilter * filter);
static void gst_gl_differencematte_reset_resources (GstGLFilter* filter); static void gst_gl_differencematte_reset_resources (GstGLFilter * filter);
static gboolean gst_gl_differencematte_filter (GstGLFilter * filter, static gboolean gst_gl_differencematte_filter (GstGLFilter * filter,
GstGLBuffer * inbuf, GstGLBuffer * outbuf); GstGLBuffer * inbuf, GstGLBuffer * outbuf);
static gboolean gst_gl_differencematte_loader (GstGLFilter* filter); static gboolean gst_gl_differencematte_loader (GstGLFilter * filter);
static const GstElementDetails element_details = GST_ELEMENT_DETAILS ( static const GstElementDetails element_details =
"Gstreamer OpenGL DifferenceMatte", GST_ELEMENT_DETAILS ("Gstreamer OpenGL DifferenceMatte",
"Filter/Effect", "Filter/Effect",
"Saves a background frame and replace it with a pixbuf", "Saves a background frame and replace it with a pixbuf",
"Filippo Argiolas <filippo.argiolas@gmail.com>"); "Filippo Argiolas <filippo.argiolas@gmail.com>");
enum enum
{ {
@ -108,53 +108,49 @@ enum
/* init resources that need a gl context */ /* init resources that need a gl context */
static void static void
gst_gl_differencematte_init_gl_resources (GstGLFilter *filter) gst_gl_differencematte_init_gl_resources (GstGLFilter * filter)
{ {
GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter); GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter);
gint i; gint i;
for (i=0; i<4; i++) { for (i = 0; i < 4; i++) {
glGenTextures (1, &differencematte->midtexture[i]); glGenTextures (1, &differencematte->midtexture[i]);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, differencematte->midtexture[i]); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, differencematte->midtexture[i]);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
filter->width, filter->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); filter->width, filter->height, 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_MAG_FILTER,
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); GL_LINEAR);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 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);
differencematte->shader[i] = gst_gl_shader_new (); differencematte->shader[i] = gst_gl_shader_new ();
} }
g_return_if_fail ( g_return_if_fail (gst_gl_shader_compile_and_check (differencematte->shader[0],
gst_gl_shader_compile_and_check (differencematte->shader[0], difference_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
difference_fragment_source, g_return_if_fail (gst_gl_shader_compile_and_check (differencematte->shader[1],
GST_GL_SHADER_FRAGMENT_SOURCE)); hconv9_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
g_return_if_fail (
gst_gl_shader_compile_and_check (differencematte->shader[1], g_return_if_fail (gst_gl_shader_compile_and_check (differencematte->shader[2],
hconv9_fragment_source, vconv9_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
GST_GL_SHADER_FRAGMENT_SOURCE));
g_return_if_fail (gst_gl_shader_compile_and_check (differencematte->shader[3],
g_return_if_fail ( texture_interp_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE));
gst_gl_shader_compile_and_check (differencematte->shader[2],
vconv9_fragment_source,
GST_GL_SHADER_FRAGMENT_SOURCE));
g_return_if_fail (
gst_gl_shader_compile_and_check (differencematte->shader[3],
texture_interp_fragment_source,
GST_GL_SHADER_FRAGMENT_SOURCE));
} }
/* free resources that need a gl context */ /* free resources that need a gl context */
static void static void
gst_gl_differencematte_reset_gl_resources (GstGLFilter *filter) gst_gl_differencematte_reset_gl_resources (GstGLFilter * filter)
{ {
GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter); GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter);
gint i; gint i;
glDeleteTextures (1, &differencematte->savedbgtexture); glDeleteTextures (1, &differencematte->savedbgtexture);
glDeleteTextures (1, &differencematte->newbgtexture); glDeleteTextures (1, &differencematte->newbgtexture);
for (i=0; i<4; i++) { for (i = 0; i < 4; i++) {
g_object_unref (differencematte->shader[i]); g_object_unref (differencematte->shader[i]);
differencematte->shader[i] = NULL; differencematte->shader[i] = NULL;
glDeleteTextures (1, &differencematte->midtexture[i]); glDeleteTextures (1, &differencematte->midtexture[i]);
@ -184,21 +180,23 @@ gst_gl_differencematte_class_init (GstGLDifferenceMatteClass * klass)
gobject_class->get_property = gst_gl_differencematte_get_property; gobject_class->get_property = gst_gl_differencematte_get_property;
GST_GL_FILTER_CLASS (klass)->filter = gst_gl_differencematte_filter; GST_GL_FILTER_CLASS (klass)->filter = gst_gl_differencematte_filter;
GST_GL_FILTER_CLASS (klass)->display_init_cb = gst_gl_differencematte_init_gl_resources; GST_GL_FILTER_CLASS (klass)->display_init_cb =
GST_GL_FILTER_CLASS (klass)->display_reset_cb = gst_gl_differencematte_reset_gl_resources; gst_gl_differencematte_init_gl_resources;
GST_GL_FILTER_CLASS (klass)->display_reset_cb =
gst_gl_differencematte_reset_gl_resources;
GST_GL_FILTER_CLASS (klass)->onStart = gst_gl_differencematte_init_resources; GST_GL_FILTER_CLASS (klass)->onStart = gst_gl_differencematte_init_resources;
GST_GL_FILTER_CLASS (klass)->onStop = gst_gl_differencematte_reset_resources; GST_GL_FILTER_CLASS (klass)->onStop = gst_gl_differencematte_reset_resources;
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_LOCATION, PROP_LOCATION,
g_param_spec_string ("location", g_param_spec_string ("location",
"Background image location", "Background image location",
"Background image location", "Background image location", NULL, G_PARAM_READWRITE));
NULL, G_PARAM_READWRITE));
} }
void void
gst_gl_differencematte_draw_texture (GstGLDifferenceMatte * differencematte, GLuint tex) gst_gl_differencematte_draw_texture (GstGLDifferenceMatte * differencematte,
GLuint tex)
{ {
GstGLFilter *filter = GST_GL_FILTER (differencematte); GstGLFilter *filter = GST_GL_FILTER (differencematte);
@ -210,19 +208,19 @@ gst_gl_differencematte_draw_texture (GstGLDifferenceMatte * differencematte, GLu
glTexCoord2f (0.0, 0.0); glTexCoord2f (0.0, 0.0);
glVertex2f (-1.0, -1.0); glVertex2f (-1.0, -1.0);
glTexCoord2f ((gfloat)filter->width, 0.0); glTexCoord2f ((gfloat) filter->width, 0.0);
glVertex2f (1.0, -1.0); glVertex2f (1.0, -1.0);
glTexCoord2f ((gfloat)filter->width, (gfloat)filter->height); glTexCoord2f ((gfloat) filter->width, (gfloat) filter->height);
glVertex2f (1.0, 1.0); glVertex2f (1.0, 1.0);
glTexCoord2f (0.0, (gfloat)filter->height); glTexCoord2f (0.0, (gfloat) filter->height);
glVertex2f (-1.0, 1.0); glVertex2f (-1.0, 1.0);
glEnd (); glEnd ();
} }
static void static void
gst_gl_differencematte_init (GstGLDifferenceMatte * differencematte, gst_gl_differencematte_init (GstGLDifferenceMatte * differencematte,
GstGLDifferenceMatteClass * klass) GstGLDifferenceMatteClass * klass)
{ {
differencematte->shader[0] = NULL; differencematte->shader[0] = NULL;
differencematte->shader[1] = NULL; differencematte->shader[1] = NULL;
@ -236,7 +234,7 @@ gst_gl_differencematte_init (GstGLDifferenceMatte * differencematte,
} }
static void static void
gst_gl_differencematte_reset_resources (GstGLFilter* filter) gst_gl_differencematte_reset_resources (GstGLFilter * filter)
{ {
// GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE(filter); // GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE(filter);
} }
@ -245,17 +243,18 @@ static void
gst_gl_differencematte_set_property (GObject * object, guint prop_id, gst_gl_differencematte_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec) const GValue * value, GParamSpec * pspec)
{ {
GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (object); GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (object);
switch (prop_id) { switch (prop_id) {
case PROP_LOCATION: case PROP_LOCATION:
if (differencematte->location != NULL) g_free (differencematte->location); if (differencematte->location != NULL)
differencematte->bg_has_changed = TRUE; g_free (differencematte->location);
differencematte->location = g_value_dup_string (value); differencematte->bg_has_changed = TRUE;
break; differencematte->location = g_value_dup_string (value);
default: break;
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); default:
break; G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
} }
} }
@ -266,61 +265,68 @@ gst_gl_differencematte_get_property (GObject * object, guint prop_id,
GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (object); GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (object);
switch (prop_id) { switch (prop_id) {
case PROP_LOCATION: case PROP_LOCATION:
g_value_set_string (value, differencematte->location); g_value_set_string (value, differencematte->location);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
} }
static void static void
gst_gl_differencematte_init_resources (GstGLFilter* filter) gst_gl_differencematte_init_resources (GstGLFilter * filter)
{ {
// GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter); // GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter);
} }
static void static void
gst_gl_differencematte_save_texture (gint width, gint height, guint texture, gpointer stuff) gst_gl_differencematte_save_texture (gint width, gint height, guint texture,
gpointer stuff)
{ {
GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE (stuff); GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (stuff);
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
gst_gl_differencematte_draw_texture (differencematte, texture); gst_gl_differencematte_draw_texture (differencematte, texture);
} }
static void init_pixbuf_texture (GstGLDisplay *display, gpointer data) static void
init_pixbuf_texture (GstGLDisplay * display, gpointer data)
{ {
GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (data); GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (data);
GstGLFilter *filter = GST_GL_FILTER (data); GstGLFilter *filter = GST_GL_FILTER (data);
glDeleteTextures (1, &differencematte->newbgtexture); glDeleteTextures (1, &differencematte->newbgtexture);
glGenTextures (1, &differencematte->newbgtexture); glGenTextures (1, &differencematte->newbgtexture);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, differencematte->newbgtexture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, differencematte->newbgtexture);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
filter->width, filter->height, 0, filter->width, filter->height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, differencematte->pixbuf); GL_RGBA, GL_UNSIGNED_BYTE, differencematte->pixbuf);
if (differencematte->savedbgtexture == 0) { if (differencematte->savedbgtexture == 0) {
glGenTextures (1, &differencematte->savedbgtexture); glGenTextures (1, &differencematte->savedbgtexture);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, differencematte->savedbgtexture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, differencematte->savedbgtexture);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
filter->width, filter->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); filter->width, filter->height, 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_MAG_FILTER,
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); GL_LINEAR);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 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);
} }
} }
static void static void
gst_gl_differencematte_diff (gint width, gint height, guint texture, gpointer stuff) gst_gl_differencematte_diff (gint width, gint height, guint texture,
gpointer stuff)
{ {
GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE (stuff); GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (stuff);
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
@ -329,8 +335,8 @@ gst_gl_differencematte_diff (gint width, gint height, guint texture, gpointer st
glActiveTexture (GL_TEXTURE0); glActiveTexture (GL_TEXTURE0);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
glDisable(GL_TEXTURE_RECTANGLE_ARB); glDisable (GL_TEXTURE_RECTANGLE_ARB);
gst_gl_shader_set_uniform_1i (differencematte->shader[0], "current", 0); gst_gl_shader_set_uniform_1i (differencematte->shader[0], "current", 0);
glActiveTexture (GL_TEXTURE1); glActiveTexture (GL_TEXTURE1);
@ -344,15 +350,16 @@ gst_gl_differencematte_diff (gint width, gint height, guint texture, gpointer st
} }
static void static void
gst_gl_differencematte_hblur (gint width, gint height, guint texture, gpointer stuff) gst_gl_differencematte_hblur (gint width, gint height, guint texture,
gpointer stuff)
{ {
GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE (stuff); GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (stuff);
gfloat gauss_kernel[9] = { gfloat gauss_kernel[9] = {
0.026995f, 0.064759f, 0.120985f, 0.026995f, 0.064759f, 0.120985f,
0.176033f, 0.199471f, 0.176033f, 0.176033f, 0.199471f, 0.176033f,
0.120985f, 0.064759f, 0.026995f 0.120985f, 0.064759f, 0.026995f
}; };
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
@ -361,27 +368,31 @@ gst_gl_differencematte_hblur (gint width, gint height, guint texture, gpointer s
glActiveTexture (GL_TEXTURE0); glActiveTexture (GL_TEXTURE0);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
glDisable(GL_TEXTURE_RECTANGLE_ARB); glDisable (GL_TEXTURE_RECTANGLE_ARB);
gst_gl_shader_set_uniform_1i (differencematte->shader[1], "tex", 0); gst_gl_shader_set_uniform_1i (differencematte->shader[1], "tex", 0);
gst_gl_shader_set_uniform_1fv (differencematte->shader[1], "kernel", 9, gauss_kernel); gst_gl_shader_set_uniform_1fv (differencematte->shader[1], "kernel", 9,
gst_gl_shader_set_uniform_1f (differencematte->shader[1], "norm_const", 0.977016f); gauss_kernel);
gst_gl_shader_set_uniform_1f (differencematte->shader[1], "norm_offset", 0.0f); gst_gl_shader_set_uniform_1f (differencematte->shader[1], "norm_const",
0.977016f);
gst_gl_shader_set_uniform_1f (differencematte->shader[1], "norm_offset",
0.0f);
gst_gl_differencematte_draw_texture (differencematte, texture); gst_gl_differencematte_draw_texture (differencematte, texture);
} }
static void static void
gst_gl_differencematte_vblur (gint width, gint height, guint texture, gpointer stuff) gst_gl_differencematte_vblur (gint width, gint height, guint texture,
gpointer stuff)
{ {
GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE (stuff); GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (stuff);
gfloat gauss_kernel[9] = { gfloat gauss_kernel[9] = {
0.026995f, 0.064759f, 0.120985f, 0.026995f, 0.064759f, 0.120985f,
0.176033f, 0.199471f, 0.176033f, 0.176033f, 0.199471f, 0.176033f,
0.120985f, 0.064759f, 0.026995f 0.120985f, 0.064759f, 0.026995f
}; };
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
@ -390,22 +401,26 @@ gst_gl_differencematte_vblur (gint width, gint height, guint texture, gpointer s
glActiveTexture (GL_TEXTURE0); glActiveTexture (GL_TEXTURE0);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
glDisable(GL_TEXTURE_RECTANGLE_ARB); glDisable (GL_TEXTURE_RECTANGLE_ARB);
gst_gl_shader_set_uniform_1i (differencematte->shader[2], "tex", 0); gst_gl_shader_set_uniform_1i (differencematte->shader[2], "tex", 0);
gst_gl_shader_set_uniform_1fv (differencematte->shader[2], "kernel", 9, gauss_kernel); gst_gl_shader_set_uniform_1fv (differencematte->shader[2], "kernel", 9,
gst_gl_shader_set_uniform_1f (differencematte->shader[2], "norm_const", 0.977016f); gauss_kernel);
gst_gl_shader_set_uniform_1f (differencematte->shader[2], "norm_offset", 0.0f); gst_gl_shader_set_uniform_1f (differencematte->shader[2], "norm_const",
0.977016f);
gst_gl_shader_set_uniform_1f (differencematte->shader[2], "norm_offset",
0.0f);
gst_gl_differencematte_draw_texture (differencematte, texture); gst_gl_differencematte_draw_texture (differencematte, texture);
} }
static void static void
gst_gl_differencematte_interp (gint width, gint height, guint texture, gpointer stuff) gst_gl_differencematte_interp (gint width, gint height, guint texture,
gpointer stuff)
{ {
GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE (stuff); GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (stuff);
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
@ -414,8 +429,8 @@ gst_gl_differencematte_interp (gint width, gint height, guint texture, gpointer
glActiveTexture (GL_TEXTURE0); glActiveTexture (GL_TEXTURE0);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
glDisable(GL_TEXTURE_RECTANGLE_ARB); glDisable (GL_TEXTURE_RECTANGLE_ARB);
gst_gl_shader_set_uniform_1i (differencematte->shader[3], "blend", 0); gst_gl_shader_set_uniform_1i (differencematte->shader[3], "blend", 0);
glActiveTexture (GL_TEXTURE1); glActiveTexture (GL_TEXTURE1);
@ -436,10 +451,11 @@ gst_gl_differencematte_interp (gint width, gint height, guint texture, gpointer
} }
static void static void
gst_gl_differencematte_identity (gint width, gint height, guint texture, gpointer stuff) gst_gl_differencematte_identity (gint width, gint height, guint texture,
gpointer stuff)
{ {
GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE (stuff); GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (stuff);
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
@ -447,10 +463,10 @@ gst_gl_differencematte_identity (gint width, gint height, guint texture, gpointe
} }
static gboolean static gboolean
gst_gl_differencematte_filter (GstGLFilter* filter, GstGLBuffer* inbuf, gst_gl_differencematte_filter (GstGLFilter * filter, GstGLBuffer * inbuf,
GstGLBuffer* outbuf) GstGLBuffer * outbuf)
{ {
GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE(filter); GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter);
differencematte->intexture = inbuf->texture; differencematte->intexture = inbuf->texture;
@ -460,14 +476,14 @@ gst_gl_differencematte_filter (GstGLFilter* filter, GstGLBuffer* inbuf,
differencematte->pixbuf = NULL; differencematte->pixbuf = NULL;
/* if loader failed then display is turned off */ /* if loader failed then display is turned off */
gst_gl_display_thread_add (filter->display, init_pixbuf_texture, differencematte); gst_gl_display_thread_add (filter->display, init_pixbuf_texture,
differencematte);
/* save current frame, needed to calculate difference between /* save current frame, needed to calculate difference between
* this frame and next ones */ * this frame and next ones */
gst_gl_filter_render_to_target (filter, inbuf->texture, gst_gl_filter_render_to_target (filter, inbuf->texture,
differencematte->savedbgtexture, differencematte->savedbgtexture,
gst_gl_differencematte_save_texture, gst_gl_differencematte_save_texture, differencematte);
differencematte);
if (differencematte->pixbuf) { if (differencematte->pixbuf) {
free (differencematte->pixbuf); free (differencematte->pixbuf);
@ -479,43 +495,41 @@ gst_gl_differencematte_filter (GstGLFilter* filter, GstGLBuffer* inbuf,
if (differencematte->savedbgtexture != 0) { if (differencematte->savedbgtexture != 0) {
gst_gl_filter_render_to_target (filter, gst_gl_filter_render_to_target (filter,
inbuf->texture, inbuf->texture,
differencematte->midtexture[0], differencematte->midtexture[0],
gst_gl_differencematte_diff, differencematte); gst_gl_differencematte_diff, differencematte);
gst_gl_filter_render_to_target (filter, gst_gl_filter_render_to_target (filter,
differencematte->midtexture[0], differencematte->midtexture[0],
differencematte->midtexture[1], differencematte->midtexture[1],
gst_gl_differencematte_hblur, differencematte); gst_gl_differencematte_hblur, differencematte);
gst_gl_filter_render_to_target (filter, gst_gl_filter_render_to_target (filter,
differencematte->midtexture[1], differencematte->midtexture[1],
differencematte->midtexture[2], differencematte->midtexture[2],
gst_gl_differencematte_vblur, differencematte); gst_gl_differencematte_vblur, differencematte);
gst_gl_filter_render_to_target (filter, gst_gl_filter_render_to_target (filter,
inbuf->texture, inbuf->texture,
outbuf->texture, outbuf->texture, gst_gl_differencematte_interp, differencematte);
gst_gl_differencematte_interp, differencematte);
} else { } else {
gst_gl_filter_render_to_target (filter, gst_gl_filter_render_to_target (filter,
inbuf->texture, inbuf->texture,
outbuf->texture, outbuf->texture, gst_gl_differencematte_identity, differencematte);
gst_gl_differencematte_identity, differencematte);
} }
return TRUE; return TRUE;
} }
static void static void
user_warning_fn(png_structp png_ptr, png_const_charp warning_msg) user_warning_fn (png_structp png_ptr, png_const_charp warning_msg)
{ {
g_warning("%s\n", warning_msg); g_warning ("%s\n", warning_msg);
} }
#define LOAD_ERROR(msg) { GST_WARNING ("unable to load %s: %s", differencematte->location, msg); return FALSE; } #define LOAD_ERROR(msg) { GST_WARNING ("unable to load %s: %s", differencematte->location, msg); return FALSE; }
static gboolean static gboolean
gst_gl_differencematte_loader (GstGLFilter* filter) gst_gl_differencematte_loader (GstGLFilter * filter)
{ {
GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE(filter); GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter);
png_structp png_ptr; png_structp png_ptr;
png_infop info_ptr; png_infop info_ptr;
@ -532,60 +546,58 @@ gst_gl_differencematte_loader (GstGLFilter* filter)
if (!filter->display) if (!filter->display)
return TRUE; return TRUE;
if ((fp = fopen(differencematte->location, "rb")) == NULL) if ((fp = fopen (differencematte->location, "rb")) == NULL)
LOAD_ERROR ("file not found"); LOAD_ERROR ("file not found");
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) if (png_ptr == NULL) {
{ fclose (fp);
fclose(fp);
LOAD_ERROR ("failed to initialize the png_struct"); LOAD_ERROR ("failed to initialize the png_struct");
} }
png_set_error_fn (png_ptr, NULL, NULL, user_warning_fn); png_set_error_fn (png_ptr, NULL, NULL, user_warning_fn);
info_ptr = png_create_info_struct(png_ptr); info_ptr = png_create_info_struct (png_ptr);
if (info_ptr == NULL) if (info_ptr == NULL) {
{ fclose (fp);
fclose(fp); png_destroy_read_struct (&png_ptr, png_infopp_NULL, png_infopp_NULL);
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
LOAD_ERROR ("failed to initialize the memory for image information"); LOAD_ERROR ("failed to initialize the memory for image information");
} }
png_init_io(png_ptr, fp); png_init_io (png_ptr, fp);
png_set_sig_bytes(png_ptr, sig_read); png_set_sig_bytes (png_ptr, sig_read);
png_read_info(png_ptr, info_ptr); png_read_info (png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
&interlace_type, int_p_NULL, int_p_NULL); &interlace_type, int_p_NULL, int_p_NULL);
if (color_type != PNG_COLOR_TYPE_RGB_ALPHA) if (color_type != PNG_COLOR_TYPE_RGB_ALPHA) {
{ fclose (fp);
fclose(fp); png_destroy_read_struct (&png_ptr, png_infopp_NULL, png_infopp_NULL);
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
LOAD_ERROR ("color type is not rgb"); LOAD_ERROR ("color type is not rgb");
} }
filter->width = width; filter->width = width;
filter->height = height; filter->height = height;
differencematte->pixbuf = (guchar*) malloc ( sizeof(guchar) * width * height * 4 ); differencematte->pixbuf =
(guchar *) malloc (sizeof (guchar) * width * height * 4);
rows = (guchar**)malloc(sizeof(guchar*) * height); rows = (guchar **) malloc (sizeof (guchar *) * height);
for (y = 0; y < height; ++y) for (y = 0; y < height; ++y)
rows[y] = (guchar*) (differencematte->pixbuf + y * width * 4); rows[y] = (guchar *) (differencematte->pixbuf + y * width * 4);
png_read_image(png_ptr, rows); png_read_image (png_ptr, rows);
free(rows); free (rows);
png_read_end(png_ptr, info_ptr); png_read_end (png_ptr, info_ptr);
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); png_destroy_read_struct (&png_ptr, &info_ptr, png_infopp_NULL);
fclose(fp); fclose (fp);
return TRUE; return TRUE;
} }

View file

@ -66,20 +66,19 @@
#include "gstgldownload.h" #include "gstgldownload.h"
#define GST_CAT_DEFAULT gst_gl_download_debug #define GST_CAT_DEFAULT gst_gl_download_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
static const GstElementDetails element_details = static const GstElementDetails element_details =
GST_ELEMENT_DETAILS ("OpenGL video maker", GST_ELEMENT_DETAILS ("OpenGL video maker",
"Filter/Effect", "Filter/Effect",
"A from GL to video flow filter", "A from GL to video flow filter",
"Julien Isorce <julien.isorce@gmail.com>"); "Julien Isorce <julien.isorce@gmail.com>");
static GstStaticPadTemplate gst_gl_download_src_pad_template = static GstStaticPadTemplate gst_gl_download_src_pad_template =
GST_STATIC_PAD_TEMPLATE ("src", GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC, GST_PAD_SRC,
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
GST_STATIC_CAPS ( GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB ";" GST_VIDEO_CAPS_BGR ";"
GST_VIDEO_CAPS_RGB ";" GST_VIDEO_CAPS_BGR ";"
GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_BGRx ";" GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_BGRx ";"
GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_xBGR ";" GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_xBGR ";"
GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_BGRA ";" GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_BGRA ";"
@ -96,7 +95,7 @@ GST_STATIC_PAD_TEMPLATE ("sink",
enum enum
{ {
PROP_0 PROP_0
}; };
#define DEBUG_INIT(bla) \ #define DEBUG_INIT(bla) \
@ -105,255 +104,246 @@ enum
GST_BOILERPLATE_FULL (GstGLDownload, gst_gl_download, GstBaseTransform, GST_BOILERPLATE_FULL (GstGLDownload, gst_gl_download, GstBaseTransform,
GST_TYPE_BASE_TRANSFORM, DEBUG_INIT); GST_TYPE_BASE_TRANSFORM, DEBUG_INIT);
static void gst_gl_download_set_property (GObject* object, guint prop_id, static void gst_gl_download_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec); const GValue * value, GParamSpec * pspec);
static void gst_gl_download_get_property (GObject* object, guint prop_id, static void gst_gl_download_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
static void gst_gl_download_reset (GstGLDownload* download); static void gst_gl_download_reset (GstGLDownload * download);
static gboolean gst_gl_download_set_caps (GstBaseTransform* bt, static gboolean gst_gl_download_set_caps (GstBaseTransform * bt,
GstCaps* incaps, GstCaps* outcaps); GstCaps * incaps, GstCaps * outcaps);
static GstCaps* gst_gl_download_transform_caps (GstBaseTransform* bt, static GstCaps *gst_gl_download_transform_caps (GstBaseTransform * bt,
GstPadDirection direction, GstCaps* caps); GstPadDirection direction, GstCaps * caps);
static gboolean gst_gl_download_start (GstBaseTransform* bt); static gboolean gst_gl_download_start (GstBaseTransform * bt);
static gboolean gst_gl_download_stop (GstBaseTransform* bt); static gboolean gst_gl_download_stop (GstBaseTransform * bt);
static GstFlowReturn gst_gl_download_transform (GstBaseTransform* trans, static GstFlowReturn gst_gl_download_transform (GstBaseTransform * trans,
GstBuffer* inbuf, GstBuffer* outbuf); GstBuffer * inbuf, GstBuffer * outbuf);
static gboolean gst_gl_download_get_unit_size (GstBaseTransform* trans, GstCaps* caps, static gboolean gst_gl_download_get_unit_size (GstBaseTransform * trans,
guint* size); GstCaps * caps, guint * size);
static void static void
gst_gl_download_base_init (gpointer klass) gst_gl_download_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_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_download_src_pad_template)); gst_static_pad_template_get (&gst_gl_download_src_pad_template));
gst_element_class_add_pad_template (element_class, gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_gl_download_sink_pad_template)); gst_static_pad_template_get (&gst_gl_download_sink_pad_template));
} }
static void static void
gst_gl_download_class_init (GstGLDownloadClass* klass) gst_gl_download_class_init (GstGLDownloadClass * klass)
{ {
GObjectClass* gobject_class; GObjectClass *gobject_class;
gobject_class = (GObjectClass *) klass; gobject_class = (GObjectClass *) klass;
gobject_class->set_property = gst_gl_download_set_property; gobject_class->set_property = gst_gl_download_set_property;
gobject_class->get_property = gst_gl_download_get_property; gobject_class->get_property = gst_gl_download_get_property;
GST_BASE_TRANSFORM_CLASS (klass)->transform_caps = GST_BASE_TRANSFORM_CLASS (klass)->transform_caps =
gst_gl_download_transform_caps; gst_gl_download_transform_caps;
GST_BASE_TRANSFORM_CLASS (klass)->transform = gst_gl_download_transform; GST_BASE_TRANSFORM_CLASS (klass)->transform = gst_gl_download_transform;
GST_BASE_TRANSFORM_CLASS (klass)->start = gst_gl_download_start; GST_BASE_TRANSFORM_CLASS (klass)->start = gst_gl_download_start;
GST_BASE_TRANSFORM_CLASS (klass)->stop = gst_gl_download_stop; GST_BASE_TRANSFORM_CLASS (klass)->stop = gst_gl_download_stop;
GST_BASE_TRANSFORM_CLASS (klass)->set_caps = gst_gl_download_set_caps; GST_BASE_TRANSFORM_CLASS (klass)->set_caps = gst_gl_download_set_caps;
GST_BASE_TRANSFORM_CLASS (klass)->get_unit_size = GST_BASE_TRANSFORM_CLASS (klass)->get_unit_size =
gst_gl_download_get_unit_size; gst_gl_download_get_unit_size;
} }
static void static void
gst_gl_download_init (GstGLDownload* download, GstGLDownloadClass* klass) gst_gl_download_init (GstGLDownload * download, GstGLDownloadClass * klass)
{ {
gst_gl_download_reset (download); gst_gl_download_reset (download);
} }
static void static void
gst_gl_download_set_property (GObject* object, guint prop_id, gst_gl_download_set_property (GObject * object, guint prop_id,
const GValue* value, GParamSpec* pspec) const GValue * value, GParamSpec * pspec)
{ {
//GstGLDownload *download = GST_GL_DOWNLOAD (object); //GstGLDownload *download = GST_GL_DOWNLOAD (object);
switch (prop_id) switch (prop_id) {
{ default:
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break;
break; }
}
} }
static void static void
gst_gl_download_get_property (GObject* object, guint prop_id, gst_gl_download_get_property (GObject * object, guint prop_id,
GValue* value, GParamSpec* pspec) GValue * value, GParamSpec * pspec)
{ {
//GstGLDownload *download = GST_GL_DOWNLOAD (object); //GstGLDownload *download = GST_GL_DOWNLOAD (object);
switch (prop_id) { switch (prop_id) {
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
} }
static void static void
gst_gl_download_reset (GstGLDownload* download) gst_gl_download_reset (GstGLDownload * download)
{ {
if (download->display) if (download->display) {
{ g_object_unref (download->display);
g_object_unref (download->display); download->display = NULL;
download->display = NULL; }
}
} }
static gboolean static gboolean
gst_gl_download_start (GstBaseTransform* bt) gst_gl_download_start (GstBaseTransform * bt)
{ {
//GstGLDownload* download = GST_GL_DOWNLOAD (bt); //GstGLDownload* download = GST_GL_DOWNLOAD (bt);
return TRUE; return TRUE;
} }
static gboolean static gboolean
gst_gl_download_stop (GstBaseTransform* bt) gst_gl_download_stop (GstBaseTransform * bt)
{ {
GstGLDownload* download = GST_GL_DOWNLOAD (bt); GstGLDownload *download = GST_GL_DOWNLOAD (bt);
gst_gl_download_reset (download); gst_gl_download_reset (download);
return TRUE; return TRUE;
} }
static GstCaps* static GstCaps *
gst_gl_download_transform_caps (GstBaseTransform * bt, gst_gl_download_transform_caps (GstBaseTransform * bt,
GstPadDirection direction, GstCaps* caps) GstPadDirection direction, GstCaps * caps)
{ {
GstGLDownload* download; GstGLDownload *download;
GstStructure* structure; GstStructure *structure;
GstCaps *newcaps, *newothercaps; GstCaps *newcaps, *newothercaps;
GstStructure* newstruct; GstStructure *newstruct;
const GValue* width_value; const GValue *width_value;
const GValue* height_value; const GValue *height_value;
const GValue* framerate_value; const GValue *framerate_value;
const GValue* par_value; const GValue *par_value;
download = GST_GL_DOWNLOAD (bt); download = GST_GL_DOWNLOAD (bt);
GST_DEBUG ("transform caps %" GST_PTR_FORMAT, caps); GST_DEBUG ("transform caps %" GST_PTR_FORMAT, caps);
structure = gst_caps_get_structure (caps, 0); structure = gst_caps_get_structure (caps, 0);
width_value = gst_structure_get_value (structure, "width"); width_value = gst_structure_get_value (structure, "width");
height_value = gst_structure_get_value (structure, "height"); height_value = gst_structure_get_value (structure, "height");
framerate_value = gst_structure_get_value (structure, "framerate"); framerate_value = gst_structure_get_value (structure, "framerate");
par_value = gst_structure_get_value (structure, "pixel-aspect-ratio"); par_value = gst_structure_get_value (structure, "pixel-aspect-ratio");
if (direction == GST_PAD_SINK) if (direction == GST_PAD_SINK) {
{ newothercaps = gst_caps_new_simple ("video/x-raw-rgb", NULL);
newothercaps = gst_caps_new_simple ("video/x-raw-rgb", NULL); newstruct = gst_caps_get_structure (newothercaps, 0);
newstruct = gst_caps_get_structure (newothercaps, 0);
gst_structure_set_value (newstruct, "width", width_value);
gst_structure_set_value (newstruct, "height", height_value);
gst_structure_set_value (newstruct, "framerate", framerate_value);
if (par_value)
gst_structure_set_value (newstruct, "pixel-aspect-ratio", par_value);
else
gst_structure_set (newstruct, "pixel-aspect-ratio", GST_TYPE_FRACTION,
1, 1, NULL);
newcaps = gst_caps_new_simple ("video/x-raw-yuv", NULL);
gst_caps_append(newcaps, newothercaps);
}
else newcaps = gst_caps_new_simple ("video/x-raw-gl", NULL);
newstruct = gst_caps_get_structure (newcaps, 0);
gst_structure_set_value (newstruct, "width", width_value); gst_structure_set_value (newstruct, "width", width_value);
gst_structure_set_value (newstruct, "height", height_value); gst_structure_set_value (newstruct, "height", height_value);
gst_structure_set_value (newstruct, "framerate", framerate_value); gst_structure_set_value (newstruct, "framerate", framerate_value);
if (par_value) if (par_value)
gst_structure_set_value (newstruct, "pixel-aspect-ratio", par_value); gst_structure_set_value (newstruct, "pixel-aspect-ratio", par_value);
else else
gst_structure_set (newstruct, "pixel-aspect-ratio", GST_TYPE_FRACTION, gst_structure_set (newstruct, "pixel-aspect-ratio", GST_TYPE_FRACTION,
1, 1, NULL); 1, 1, NULL);
newcaps = gst_caps_new_simple ("video/x-raw-yuv", NULL);
gst_caps_append (newcaps, newothercaps);
} else
newcaps = gst_caps_new_simple ("video/x-raw-gl", NULL);
GST_DEBUG ("new caps %" GST_PTR_FORMAT, newcaps); newstruct = gst_caps_get_structure (newcaps, 0);
gst_structure_set_value (newstruct, "width", width_value);
gst_structure_set_value (newstruct, "height", height_value);
gst_structure_set_value (newstruct, "framerate", framerate_value);
if (par_value)
gst_structure_set_value (newstruct, "pixel-aspect-ratio", par_value);
else
gst_structure_set (newstruct, "pixel-aspect-ratio", GST_TYPE_FRACTION,
1, 1, NULL);
return newcaps; GST_DEBUG ("new caps %" GST_PTR_FORMAT, newcaps);
return newcaps;
} }
static gboolean static gboolean
gst_gl_download_set_caps (GstBaseTransform* bt, GstCaps* incaps, gst_gl_download_set_caps (GstBaseTransform * bt, GstCaps * incaps,
GstCaps* outcaps) GstCaps * outcaps)
{ {
GstGLDownload* download; GstGLDownload *download;
gboolean ret; gboolean ret;
download = GST_GL_DOWNLOAD (bt); download = GST_GL_DOWNLOAD (bt);
GST_DEBUG ("called with %" GST_PTR_FORMAT, incaps); GST_DEBUG ("called with %" GST_PTR_FORMAT, incaps);
ret = gst_video_format_parse_caps (outcaps, &download->video_format, ret = gst_video_format_parse_caps (outcaps, &download->video_format,
&download->width, &download->height); &download->width, &download->height);
if (!ret) if (!ret) {
{ GST_ERROR ("bad caps");
GST_ERROR ("bad caps"); return FALSE;
return FALSE; }
}
return ret; return ret;
} }
static gboolean static gboolean
gst_gl_download_get_unit_size (GstBaseTransform* trans, GstCaps* caps, gst_gl_download_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
guint* size) guint * size)
{ {
gboolean ret; gboolean ret;
GstStructure *structure; GstStructure *structure;
gint width; gint width;
gint height; gint height;
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")) {
{ ret = gst_gl_buffer_parse_caps (caps, &width, &height);
ret = gst_gl_buffer_parse_caps (caps, &width, &height); if (ret)
if (ret) *size = gst_gl_buffer_get_size (width, height);
*size = gst_gl_buffer_get_size (width, height); } else {
} GstVideoFormat video_format;
else ret = gst_video_format_parse_caps (caps, &video_format, &width, &height);
{ if (ret)
GstVideoFormat video_format; *size = gst_video_format_get_size (video_format, width, height);
ret = gst_video_format_parse_caps (caps, &video_format, &width, &height); }
if (ret)
*size = gst_video_format_get_size (video_format, width, height);
}
return ret; return ret;
} }
static GstFlowReturn static GstFlowReturn
gst_gl_download_transform (GstBaseTransform* trans, GstBuffer* inbuf, gst_gl_download_transform (GstBaseTransform * trans, GstBuffer * inbuf,
GstBuffer* outbuf) GstBuffer * outbuf)
{ {
GstGLDownload* download = GST_GL_DOWNLOAD (trans); GstGLDownload *download = GST_GL_DOWNLOAD (trans);
GstGLBuffer* gl_inbuf = GST_GL_BUFFER (inbuf); GstGLBuffer *gl_inbuf = GST_GL_BUFFER (inbuf);
if (download->display == NULL) if (download->display == NULL) {
{ download->display = g_object_ref (gl_inbuf->display);
download->display = g_object_ref (gl_inbuf->display);
//blocking call, init color space conversion if needed //blocking call, init color space conversion if needed
gst_gl_display_init_download (download->display, download->video_format, gst_gl_display_init_download (download->display, download->video_format,
download->width, download->height); download->width, download->height);
} } else
else g_assert (download->display == gl_inbuf->display);
g_assert (download->display == gl_inbuf->display);
GST_DEBUG ("making video %p size %d", GST_DEBUG ("making video %p size %d",
GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf)); GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf));
//blocking call //blocking call
if (gst_gl_display_do_download(download->display, gl_inbuf->texture, if (gst_gl_display_do_download (download->display, gl_inbuf->texture,
gl_inbuf->width, gl_inbuf->height, GST_BUFFER_DATA (outbuf))) gl_inbuf->width, gl_inbuf->height, GST_BUFFER_DATA (outbuf)))
return GST_FLOW_OK; return GST_FLOW_OK;
else else
return GST_FLOW_UNEXPECTED; return GST_FLOW_UNEXPECTED;
} }

View file

@ -48,31 +48,33 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
GST_DEBUG_CATEGORY_INIT (gst_gl_effects_debug, "gleffects", 0, "gleffects element"); GST_DEBUG_CATEGORY_INIT (gst_gl_effects_debug, "gleffects", 0, "gleffects element");
GST_BOILERPLATE_FULL (GstGLEffects, gst_gl_effects, GstGLFilter, GST_BOILERPLATE_FULL (GstGLEffects, gst_gl_effects, GstGLFilter,
GST_TYPE_GL_FILTER, DEBUG_INIT); GST_TYPE_GL_FILTER, DEBUG_INIT);
static void gst_gl_effects_set_property (GObject * object, guint prop_id, static void gst_gl_effects_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec); const GValue * value, GParamSpec * pspec);
static void gst_gl_effects_get_property (GObject * object, guint prop_id, static void gst_gl_effects_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
static void gst_gl_effects_init_resources (GstGLFilter* filter); static void gst_gl_effects_init_resources (GstGLFilter * filter);
static void gst_gl_effects_reset_resources (GstGLFilter* filter); static void gst_gl_effects_reset_resources (GstGLFilter * filter);
static void gst_gl_effects_on_init_gl_context (GstGLFilter* filter); static void gst_gl_effects_on_init_gl_context (GstGLFilter * filter);
static void gst_gl_effects_ghash_func_clean (gpointer key, gpointer value, gpointer data); static void gst_gl_effects_ghash_func_clean (gpointer key, gpointer value,
gpointer data);
static gboolean gst_gl_effects_filter (GstGLFilter * filter, static gboolean gst_gl_effects_filter (GstGLFilter * filter,
GstGLBuffer * inbuf, GstGLBuffer * outbuf); GstGLBuffer * inbuf, GstGLBuffer * outbuf);
static const GstElementDetails element_details = GST_ELEMENT_DETAILS ( static const GstElementDetails element_details =
"Gstreamer OpenGL Effects", GST_ELEMENT_DETAILS ("Gstreamer OpenGL Effects",
"Filter/Effect", "Filter/Effect",
"GL Shading Language effects", "GL Shading Language effects",
"Filippo Argiolas <filippo.argiolas@gmail.com>"); "Filippo Argiolas <filippo.argiolas@gmail.com>");
/* dont' forget to edit the following when a new effect is added */ /* dont' forget to edit the following when a new effect is added */
typedef enum { typedef enum
{
GST_GL_EFFECT_IDENTITY, GST_GL_EFFECT_IDENTITY,
GST_GL_EFFECT_MIRROR, GST_GL_EFFECT_MIRROR,
GST_GL_EFFECT_SQUEEZE, GST_GL_EFFECT_SQUEEZE,
@ -97,122 +99,127 @@ static GType
gst_gl_effects_effect_get_type (void) gst_gl_effects_effect_get_type (void)
{ {
static GType gl_effects_effect_type = 0; static GType gl_effects_effect_type = 0;
static const GEnumValue effect_types [] = { static const GEnumValue effect_types[] = {
{ GST_GL_EFFECT_IDENTITY, "Do nothing Effect", "identity" }, {GST_GL_EFFECT_IDENTITY, "Do nothing Effect", "identity"},
{ GST_GL_EFFECT_MIRROR, "Mirror Effect", "mirror" }, {GST_GL_EFFECT_MIRROR, "Mirror Effect", "mirror"},
{ GST_GL_EFFECT_SQUEEZE, "Squeeze Effect", "squeeze" }, {GST_GL_EFFECT_SQUEEZE, "Squeeze Effect", "squeeze"},
{ GST_GL_EFFECT_STRETCH, "Stretch Effect", "stretch" }, {GST_GL_EFFECT_STRETCH, "Stretch Effect", "stretch"},
{ GST_GL_EFFECT_FISHEYE, "FishEye Effect", "fisheye" }, {GST_GL_EFFECT_FISHEYE, "FishEye Effect", "fisheye"},
{ GST_GL_EFFECT_TWIRL, "Twirl Effect", "twirl" }, {GST_GL_EFFECT_TWIRL, "Twirl Effect", "twirl"},
{ GST_GL_EFFECT_BULGE, "Bulge Effect", "bulge" }, {GST_GL_EFFECT_BULGE, "Bulge Effect", "bulge"},
{ GST_GL_EFFECT_TUNNEL, "Light Tunnel Effect", "tunnel" }, {GST_GL_EFFECT_TUNNEL, "Light Tunnel Effect", "tunnel"},
{ GST_GL_EFFECT_SQUARE, "Square Effect", "square" }, {GST_GL_EFFECT_SQUARE, "Square Effect", "square"},
{ GST_GL_EFFECT_HEAT, "Heat Signature Effect", "heat" }, {GST_GL_EFFECT_HEAT, "Heat Signature Effect", "heat"},
{ GST_GL_EFFECT_SEPIA, "Sepia Toning Effect", "sepia" }, {GST_GL_EFFECT_SEPIA, "Sepia Toning Effect", "sepia"},
{ GST_GL_EFFECT_XPRO, "Cross Processing Effect", "xpro" }, {GST_GL_EFFECT_XPRO, "Cross Processing Effect", "xpro"},
{ GST_GL_EFFECT_LUMA_XPRO, "Luma Cross Processing Effect", "lumaxpro" }, {GST_GL_EFFECT_LUMA_XPRO, "Luma Cross Processing Effect", "lumaxpro"},
{ GST_GL_EFFECT_XRAY, "Glowing negative effect", "xray" }, {GST_GL_EFFECT_XRAY, "Glowing negative effect", "xray"},
{ GST_GL_EFFECT_SIN, "All Grey but Red Effect", "sin" }, {GST_GL_EFFECT_SIN, "All Grey but Red Effect", "sin"},
{ GST_GL_EFFECT_GLOW, "Glow Lighting Effect", "glow" }, {GST_GL_EFFECT_GLOW, "Glow Lighting Effect", "glow"},
{ 0, NULL, NULL } {0, NULL, NULL}
}; };
if (!gl_effects_effect_type) { if (!gl_effects_effect_type) {
gl_effects_effect_type = gl_effects_effect_type =
g_enum_register_static ("GstGLEffectsEffect", effect_types); g_enum_register_static ("GstGLEffectsEffect", effect_types);
} }
return gl_effects_effect_type; return gl_effects_effect_type;
} }
static void static void
gst_gl_effects_set_effect (GstGLEffects *effects, gint effect_type) { gst_gl_effects_set_effect (GstGLEffects * effects, gint effect_type)
{
switch (effect_type) { switch (effect_type) {
case GST_GL_EFFECT_IDENTITY: case GST_GL_EFFECT_IDENTITY:
effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_identity; effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_identity;
break; break;
case GST_GL_EFFECT_MIRROR: case GST_GL_EFFECT_MIRROR:
effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_mirror; effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_mirror;
break; break;
case GST_GL_EFFECT_SQUEEZE: case GST_GL_EFFECT_SQUEEZE:
effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_squeeze; effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_squeeze;
break; break;
case GST_GL_EFFECT_STRETCH: case GST_GL_EFFECT_STRETCH:
effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_stretch; effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_stretch;
break; break;
case GST_GL_EFFECT_TUNNEL: case GST_GL_EFFECT_TUNNEL:
effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_tunnel; effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_tunnel;
break; break;
case GST_GL_EFFECT_FISHEYE: case GST_GL_EFFECT_FISHEYE:
effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_fisheye; effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_fisheye;
break; break;
case GST_GL_EFFECT_TWIRL: case GST_GL_EFFECT_TWIRL:
effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_twirl; effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_twirl;
break; break;
case GST_GL_EFFECT_BULGE: case GST_GL_EFFECT_BULGE:
effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_bulge; effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_bulge;
break; break;
case GST_GL_EFFECT_SQUARE: case GST_GL_EFFECT_SQUARE:
effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_square; effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_square;
break; break;
case GST_GL_EFFECT_HEAT: case GST_GL_EFFECT_HEAT:
effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_heat; effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_heat;
break; break;
case GST_GL_EFFECT_SEPIA: case GST_GL_EFFECT_SEPIA:
effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_sepia; effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_sepia;
break; break;
case GST_GL_EFFECT_XPRO: case GST_GL_EFFECT_XPRO:
effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_xpro; effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_xpro;
break; break;
case GST_GL_EFFECT_LUMA_XPRO: case GST_GL_EFFECT_LUMA_XPRO:
effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_luma_xpro; effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_luma_xpro;
break; break;
case GST_GL_EFFECT_XRAY: case GST_GL_EFFECT_XRAY:
effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_xray; effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_xray;
break; break;
case GST_GL_EFFECT_SIN: case GST_GL_EFFECT_SIN:
effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_sin; effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_sin;
break; break;
case GST_GL_EFFECT_GLOW: case GST_GL_EFFECT_GLOW:
effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_glow; effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_glow;
break; break;
default: default:
g_assert_not_reached (); g_assert_not_reached ();
} }
effects->current_effect = effect_type; effects->current_effect = effect_type;
} }
/* init resources that need a gl context */ /* init resources that need a gl context */
static void static void
gst_gl_effects_init_gl_resources (GstGLFilter *filter) gst_gl_effects_init_gl_resources (GstGLFilter * filter)
{ {
GstGLEffects *effects = GST_GL_EFFECTS (filter); GstGLEffects *effects = GST_GL_EFFECTS (filter);
gint i; gint i;
for (i=0; i<NEEDED_TEXTURES; i++) { for (i = 0; i < NEEDED_TEXTURES; i++) {
glGenTextures (1, &effects->midtexture[i]); glGenTextures (1, &effects->midtexture[i]);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, effects->midtexture[i]); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, effects->midtexture[i]);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
filter->width, filter->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); filter->width, filter->height, 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_MAG_FILTER,
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); GL_LINEAR);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 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);
} }
} }
/* free resources that need a gl context */ /* free resources that need a gl context */
static void static void
gst_gl_effects_reset_gl_resources (GstGLFilter *filter) gst_gl_effects_reset_gl_resources (GstGLFilter * filter)
{ {
GstGLEffects *effects = GST_GL_EFFECTS (filter); GstGLEffects *effects = GST_GL_EFFECTS (filter);
gint i; gint i;
for (i=0; i<10; i++) { for (i = 0; i < 10; i++) {
glDeleteTextures (1, &effects->midtexture[i]); glDeleteTextures (1, &effects->midtexture[i]);
effects->midtexture[i] = 0; effects->midtexture[i] = 0;
} }
for (i=0; i<GST_GL_EFFECTS_N_CURVES; i++) { for (i = 0; i < GST_GL_EFFECTS_N_CURVES; i++) {
glDeleteTextures (1, &effects->curve[i]); glDeleteTextures (1, &effects->curve[i]);
effects->curve[i] = 0; effects->curve[i] = 0;
} }
@ -236,29 +243,27 @@ gst_gl_effects_class_init (GstGLEffectsClass * klass)
gobject_class->get_property = gst_gl_effects_get_property; gobject_class->get_property = gst_gl_effects_get_property;
GST_GL_FILTER_CLASS (klass)->filter = gst_gl_effects_filter; GST_GL_FILTER_CLASS (klass)->filter = gst_gl_effects_filter;
GST_GL_FILTER_CLASS (klass)->display_init_cb = gst_gl_effects_init_gl_resources; GST_GL_FILTER_CLASS (klass)->display_init_cb =
GST_GL_FILTER_CLASS (klass)->display_reset_cb = gst_gl_effects_reset_gl_resources; gst_gl_effects_init_gl_resources;
GST_GL_FILTER_CLASS (klass)->display_reset_cb =
gst_gl_effects_reset_gl_resources;
GST_GL_FILTER_CLASS (klass)->onStart = gst_gl_effects_init_resources; GST_GL_FILTER_CLASS (klass)->onStart = gst_gl_effects_init_resources;
GST_GL_FILTER_CLASS (klass)->onStop = gst_gl_effects_reset_resources; GST_GL_FILTER_CLASS (klass)->onStop = gst_gl_effects_reset_resources;
GST_GL_FILTER_CLASS (klass)->onInitFBO = gst_gl_effects_on_init_gl_context; GST_GL_FILTER_CLASS (klass)->onInitFBO = gst_gl_effects_on_init_gl_context;
g_object_class_install_property ( g_object_class_install_property (gobject_class,
gobject_class, PROP_EFFECT,
PROP_EFFECT, g_param_spec_enum ("effect",
g_param_spec_enum ("effect", "Effect",
"Effect", "Select which effect apply to GL video texture",
"Select which effect apply to GL video texture", GST_TYPE_GL_EFFECTS_EFFECT,
GST_TYPE_GL_EFFECTS_EFFECT, GST_GL_EFFECT_IDENTITY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
GST_GL_EFFECT_IDENTITY, g_object_class_install_property (gobject_class,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); PROP_HSWAP,
g_object_class_install_property ( g_param_spec_boolean ("hswap",
gobject_class, "Horizontal Swap",
PROP_HSWAP, "Switch video texture left to right, useful with webcams",
g_param_spec_boolean ("hswap", FALSE, G_PARAM_READWRITE));
"Horizontal Swap",
"Switch video texture left to right, useful with webcams",
FALSE,
G_PARAM_READWRITE));
} }
void void
@ -274,18 +279,18 @@ gst_gl_effects_draw_texture (GstGLEffects * effects, GLuint tex)
glTexCoord2f (0.0, 0.0); glTexCoord2f (0.0, 0.0);
glVertex2f (-1.0, -1.0); glVertex2f (-1.0, -1.0);
glTexCoord2f ((gfloat)filter->width, 0.0); glTexCoord2f ((gfloat) filter->width, 0.0);
glVertex2f (1.0, -1.0); glVertex2f (1.0, -1.0);
glTexCoord2f ((gfloat)filter->width, (gfloat)filter->height); glTexCoord2f ((gfloat) filter->width, (gfloat) filter->height);
glVertex2f (1.0, 1.0); glVertex2f (1.0, 1.0);
glTexCoord2f (0.0, (gfloat)filter->height); glTexCoord2f (0.0, (gfloat) filter->height);
glVertex2f (-1.0, 1.0); glVertex2f (-1.0, 1.0);
glEnd (); glEnd ();
} }
static void static void
set_horizontal_swap (GstGLDisplay *display, gpointer data) set_horizontal_swap (GstGLDisplay * display, gpointer data)
{ {
// GstGLEffects *effects = GST_GL_EFFECTS (data); // GstGLEffects *effects = GST_GL_EFFECTS (data);
@ -310,8 +315,8 @@ gst_gl_effects_init (GstGLEffects * effects, GstGLEffectsClass * klass)
static void static void
gst_gl_effects_ghash_func_clean (gpointer key, gpointer value, gpointer data) gst_gl_effects_ghash_func_clean (gpointer key, gpointer value, gpointer data)
{ {
GstGLShader* shader = (GstGLShader*) value; GstGLShader *shader = (GstGLShader *) value;
GstGLFilter* filter = (GstGLFilter*) data; GstGLFilter *filter = (GstGLFilter *) data;
//blocking call, wait the opengl thread has destroyed the shader //blocking call, wait the opengl thread has destroyed the shader
gst_gl_display_del_shader (filter->display, shader); gst_gl_display_del_shader (filter->display, shader);
@ -320,15 +325,15 @@ gst_gl_effects_ghash_func_clean (gpointer key, gpointer value, gpointer data)
} }
static void static void
gst_gl_effects_reset_resources (GstGLFilter* filter) gst_gl_effects_reset_resources (GstGLFilter * filter)
{ {
GstGLEffects* effects = GST_GL_EFFECTS(filter); GstGLEffects *effects = GST_GL_EFFECTS (filter);
// g_message ("reset resources"); // g_message ("reset resources");
//release shaders in the gl thread //release shaders in the gl thread
g_hash_table_foreach (effects->shaderstable, gst_gl_effects_ghash_func_clean, g_hash_table_foreach (effects->shaderstable, gst_gl_effects_ghash_func_clean,
filter); filter);
//clean the htable without calling values destructors //clean the htable without calling values destructors
//because shaders have been released in the glthread //because shaders have been released in the glthread
@ -344,15 +349,15 @@ gst_gl_effects_set_property (GObject * object, guint prop_id,
GstGLEffects *effects = GST_GL_EFFECTS (object); GstGLEffects *effects = GST_GL_EFFECTS (object);
switch (prop_id) { switch (prop_id) {
case PROP_EFFECT: case PROP_EFFECT:
gst_gl_effects_set_effect (effects, g_value_get_enum (value)); gst_gl_effects_set_effect (effects, g_value_get_enum (value));
break; break;
case PROP_HSWAP: case PROP_HSWAP:
effects->horizontal_swap = g_value_get_boolean (value); effects->horizontal_swap = g_value_get_boolean (value);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
} }
@ -363,38 +368,37 @@ gst_gl_effects_get_property (GObject * object, guint prop_id,
GstGLEffects *effects = GST_GL_EFFECTS (object); GstGLEffects *effects = GST_GL_EFFECTS (object);
switch (prop_id) { switch (prop_id) {
case PROP_EFFECT: case PROP_EFFECT:
g_value_set_enum (value, effects->current_effect); g_value_set_enum (value, effects->current_effect);
break; break;
case PROP_HSWAP: case PROP_HSWAP:
g_value_set_boolean (value, effects->horizontal_swap); g_value_set_boolean (value, effects->horizontal_swap);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
} }
static void static void
gst_gl_effects_init_resources (GstGLFilter* filter) gst_gl_effects_init_resources (GstGLFilter * filter)
{ {
GstGLEffects *effects = GST_GL_EFFECTS (filter); GstGLEffects *effects = GST_GL_EFFECTS (filter);
gint i; gint i;
// g_message ("init resources"); // g_message ("init resources");
// g_message ("init hashtable"); // g_message ("init hashtable");
effects->shaderstable = g_hash_table_new (g_str_hash, effects->shaderstable = g_hash_table_new (g_str_hash, g_str_equal);
g_str_equal);
// g_message ("zero textures and curves"); // g_message ("zero textures and curves");
for (i=0; i<NEEDED_TEXTURES; i++) { for (i = 0; i < NEEDED_TEXTURES; i++) {
effects->midtexture[i] = 0; effects->midtexture[i] = 0;
} }
for (i=0; i<GST_GL_EFFECTS_N_CURVES; i++) { for (i = 0; i < GST_GL_EFFECTS_N_CURVES; i++) {
effects->curve[i] = 0; effects->curve[i] = 0;
} }
} }
static void static void
gst_gl_effects_on_init_gl_context (GstGLFilter* filter) gst_gl_effects_on_init_gl_context (GstGLFilter * filter)
{ {
//check that your hardware supports shader //check that your hardware supports shader
//if not the pipeline correctly shut down //if not the pipeline correctly shut down
@ -402,10 +406,10 @@ gst_gl_effects_on_init_gl_context (GstGLFilter* filter)
} }
static gboolean static gboolean
gst_gl_effects_filter (GstGLFilter* filter, GstGLBuffer* inbuf, gst_gl_effects_filter (GstGLFilter * filter, GstGLBuffer * inbuf,
GstGLBuffer* outbuf) GstGLBuffer * outbuf)
{ {
GstGLEffects* effects = GST_GL_EFFECTS(filter); GstGLEffects *effects = GST_GL_EFFECTS (filter);
effects->intexture = inbuf->texture; effects->intexture = inbuf->texture;
effects->outtexture = outbuf->texture; effects->outtexture = outbuf->texture;

View file

@ -45,17 +45,17 @@
#define GST_CAT_DEFAULT gst_gl_filter_app_debug #define GST_CAT_DEFAULT gst_gl_filter_app_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
static const GstElementDetails element_details = static const GstElementDetails element_details =
GST_ELEMENT_DETAILS ("OpenGL application filter", GST_ELEMENT_DETAILS ("OpenGL application filter",
"Filter/Effect", "Filter/Effect",
"Use client callbacks to define the scene", "Use client callbacks to define the scene",
"Julien Isorce <julien.isorce@gmail.com>"); "Julien Isorce <julien.isorce@gmail.com>");
enum enum
{ {
PROP_0, PROP_0,
PROP_CLIENT_RESHAPE_CALLBACK, PROP_CLIENT_RESHAPE_CALLBACK,
PROP_CLIENT_DRAW_CALLBACK PROP_CLIENT_DRAW_CALLBACK
}; };
#define DEBUG_INIT(bla) \ #define DEBUG_INIT(bla) \
@ -64,16 +64,17 @@ enum
GST_BOILERPLATE_FULL (GstGLFilterApp, gst_gl_filter_app, GstGLFilter, GST_BOILERPLATE_FULL (GstGLFilterApp, gst_gl_filter_app, GstGLFilter,
GST_TYPE_GL_FILTER, DEBUG_INIT); GST_TYPE_GL_FILTER, DEBUG_INIT);
static void gst_gl_filter_app_set_property (GObject* object, guint prop_id, static void gst_gl_filter_app_set_property (GObject * object, guint prop_id,
const GValue* value, GParamSpec* pspec); const GValue * value, GParamSpec * pspec);
static void gst_gl_filter_app_get_property (GObject* object, guint prop_id, static void gst_gl_filter_app_get_property (GObject * object, guint prop_id,
GValue* value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
static gboolean gst_gl_filter_app_set_caps (GstGLFilter* filter, static gboolean gst_gl_filter_app_set_caps (GstGLFilter * filter,
GstCaps* incaps, GstCaps* outcaps); GstCaps * incaps, GstCaps * outcaps);
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 (gint width, gint height, guint texture, gpointer stuff); static void gst_gl_filter_app_callback (gint width, gint height, guint texture,
gpointer stuff);
static void static void
@ -85,136 +86,135 @@ gst_gl_filter_app_base_init (gpointer klass)
} }
static void static void
gst_gl_filter_app_class_init (GstGLFilterAppClass* klass) gst_gl_filter_app_class_init (GstGLFilterAppClass * klass)
{ {
GObjectClass* gobject_class; GObjectClass *gobject_class;
gobject_class = (GObjectClass *) klass; gobject_class = (GObjectClass *) klass;
gobject_class->set_property = gst_gl_filter_app_set_property; gobject_class->set_property = gst_gl_filter_app_set_property;
gobject_class->get_property = gst_gl_filter_app_get_property; gobject_class->get_property = gst_gl_filter_app_get_property;
GST_GL_FILTER_CLASS (klass)->set_caps = gst_gl_filter_app_set_caps; GST_GL_FILTER_CLASS (klass)->set_caps = gst_gl_filter_app_set_caps;
GST_GL_FILTER_CLASS (klass)->filter = gst_gl_filter_app_filter; GST_GL_FILTER_CLASS (klass)->filter = gst_gl_filter_app_filter;
g_object_class_install_property (gobject_class, PROP_CLIENT_RESHAPE_CALLBACK, g_object_class_install_property (gobject_class, PROP_CLIENT_RESHAPE_CALLBACK,
g_param_spec_pointer ("client_reshape_callback", "Client reshape callback", g_param_spec_pointer ("client_reshape_callback",
"Define a custom reshape callback in a client code", "Client reshape callback",
"Define a custom reshape callback in a client code",
G_PARAM_WRITABLE)); G_PARAM_WRITABLE));
g_object_class_install_property (gobject_class, PROP_CLIENT_DRAW_CALLBACK, g_object_class_install_property (gobject_class, PROP_CLIENT_DRAW_CALLBACK,
g_param_spec_pointer ("client_draw_callback", "Client draw callback", g_param_spec_pointer ("client_draw_callback", "Client draw callback",
"Define a custom draw callback in a client code", "Define a custom draw callback in a client code", G_PARAM_WRITABLE));
G_PARAM_WRITABLE));
} }
static void static void
gst_gl_filter_app_init (GstGLFilterApp* filter, gst_gl_filter_app_init (GstGLFilterApp * filter, GstGLFilterAppClass * klass)
GstGLFilterAppClass* klass)
{ {
filter->clientReshapeCallback = NULL; filter->clientReshapeCallback = NULL;
filter->clientDrawCallback = NULL; filter->clientDrawCallback = NULL;
} }
static void static void
gst_gl_filter_app_set_property (GObject* object, guint prop_id, gst_gl_filter_app_set_property (GObject * object, guint prop_id,
const GValue* value, GParamSpec* pspec) const GValue * value, GParamSpec * pspec)
{ {
GstGLFilterApp* filter = GST_GL_FILTER_APP (object); GstGLFilterApp *filter = GST_GL_FILTER_APP (object);
switch (prop_id) { switch (prop_id) {
case PROP_CLIENT_RESHAPE_CALLBACK: case PROP_CLIENT_RESHAPE_CALLBACK:
{
filter->clientReshapeCallback = g_value_get_pointer (value);
break;
}
case PROP_CLIENT_DRAW_CALLBACK:
{
filter->clientDrawCallback = g_value_get_pointer (value);
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_gl_filter_app_get_property (GObject* object, guint prop_id,
GValue* value, GParamSpec* pspec)
{
//GstGLFilterApp* filter = GST_GL_FILTER_APP (object);
switch (prop_id)
{ {
default: filter->clientReshapeCallback = g_value_get_pointer (value);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break;
break;
} }
case PROP_CLIENT_DRAW_CALLBACK:
{
filter->clientDrawCallback = g_value_get_pointer (value);
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_gl_filter_app_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
//GstGLFilterApp* filter = GST_GL_FILTER_APP (object);
switch (prop_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
} }
static gboolean static gboolean
gst_gl_filter_app_set_caps (GstGLFilter* filter, GstCaps* incaps, gst_gl_filter_app_set_caps (GstGLFilter * filter, GstCaps * incaps,
GstCaps* outcaps) GstCaps * outcaps)
{ {
//GstGLFilterApp* app_filter = GST_GL_FILTER_APP(filter); //GstGLFilterApp* app_filter = GST_GL_FILTER_APP(filter);
return TRUE; return TRUE;
} }
static gboolean static gboolean
gst_gl_filter_app_filter (GstGLFilter* filter, GstGLBuffer* inbuf, gst_gl_filter_app_filter (GstGLFilter * filter, GstGLBuffer * inbuf,
GstGLBuffer* outbuf) GstGLBuffer * outbuf)
{ {
GstGLFilterApp* app_filter = GST_GL_FILTER_APP(filter); GstGLFilterApp *app_filter = GST_GL_FILTER_APP (filter);
if (app_filter->clientDrawCallback) if (app_filter->clientDrawCallback) {
{ //blocking call, use a FBO
//blocking call, use a FBO gst_gl_display_use_fbo (filter->display, filter->width, filter->height,
gst_gl_display_use_fbo (filter->display, filter->width, filter->height, filter->fbo, filter->depthbuffer, outbuf->texture,
filter->fbo, filter->depthbuffer, outbuf->texture, app_filter->clientDrawCallback, app_filter->clientDrawCallback, inbuf->width, inbuf->height,
inbuf->width, inbuf->height, inbuf->texture, inbuf->texture, 45, (gfloat) filter->width / (gfloat) filter->height,
45, (gfloat)filter->width / (gfloat)filter->height, 0.1, 100, 0.1, 100, GST_GL_DISPLAY_PROJECTION_PERSPECIVE, NULL);
GST_GL_DISPLAY_PROJECTION_PERSPECIVE, NULL); }
} //default
//default else {
else //blocking call, use a FBO
{ gst_gl_display_use_fbo (filter->display, filter->width, filter->height,
//blocking call, use a FBO filter->fbo, filter->depthbuffer, outbuf->texture,
gst_gl_display_use_fbo (filter->display, filter->width, filter->height, gst_gl_filter_app_callback, inbuf->width, inbuf->height, inbuf->texture,
filter->fbo, filter->depthbuffer, outbuf->texture, gst_gl_filter_app_callback, 0, filter->width, 0, filter->height, GST_GL_DISPLAY_PROJECTION_ORTHO2D,
inbuf->width, inbuf->height, inbuf->texture, NULL);
0, filter->width, 0, filter->height, }
GST_GL_DISPLAY_PROJECTION_ORTHO2D, NULL);
}
return TRUE; return TRUE;
} }
//opengl scene, params: input texture (not the output filter->texture) //opengl scene, params: input texture (not the output filter->texture)
static void static void
gst_gl_filter_app_callback (gint width, gint height, guint texture, gpointer stuff) gst_gl_filter_app_callback (gint width, gint height, guint texture,
gpointer stuff)
{ {
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
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_TO_EDGE); glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); GL_CLAMP_TO_EDGE);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 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); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glBegin (GL_QUADS); glMatrixMode (GL_PROJECTION);
glTexCoord2i (0, 0); glLoadIdentity ();
glVertex2f (-1.0f, -1.0f);
glTexCoord2i (width, 0); glBegin (GL_QUADS);
glVertex2f (1.0f, -1.0f); glTexCoord2i (0, 0);
glTexCoord2i (width, height); glVertex2f (-1.0f, -1.0f);
glVertex2f (1.0f, 1.0f); glTexCoord2i (width, 0);
glTexCoord2i (0, height); glVertex2f (1.0f, -1.0f);
glVertex2f (-1.0f, 1.0f); glTexCoord2i (width, height);
glEnd (); glVertex2f (1.0f, 1.0f);
glTexCoord2i (0, height);
glVertex2f (-1.0f, 1.0f);
glEnd ();
} }

View file

@ -66,45 +66,39 @@ GType gst_gl_glfilterblur_get_type (void);
/* horizontal convolution */ /* horizontal convolution */
static const gchar *hconv9_fragment_source = static const gchar *hconv9_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect tex;" "uniform sampler2DRect tex;"
"uniform float norm_const;" "uniform float norm_const;"
"uniform float norm_offset;" "uniform float norm_offset;"
"uniform float kernel[9];" "uniform float kernel[9];"
"void main () {" "void main () {"
" float offset[9] = float[9] (-4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0);" " float offset[9] = float[9] (-4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0);"
" vec2 texturecoord = gl_TexCoord[0].st;" " vec2 texturecoord = gl_TexCoord[0].st;"
" int i;" " int i;"
" vec4 sum = vec4 (0.0);" " vec4 sum = vec4 (0.0);"
" for (i = 0; i < 9; i++) { " " for (i = 0; i < 9; i++) { "
" if (kernel[i] != 0.0) {" " if (kernel[i] != 0.0) {"
" vec4 neighbor = texture2DRect(tex, vec2(texturecoord.s+offset[i], texturecoord.t)); " " vec4 neighbor = texture2DRect(tex, vec2(texturecoord.s+offset[i], texturecoord.t)); "
" sum += neighbor * kernel[i]/norm_const; " " sum += neighbor * kernel[i]/norm_const; "
" }" " }" " }" " gl_FragColor = sum + norm_offset;" "}";
" }"
" gl_FragColor = sum + norm_offset;"
"}";
/* vertical convolution */ /* vertical convolution */
static const gchar *vconv9_fragment_source = static const gchar *vconv9_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect tex;" "uniform sampler2DRect tex;"
"uniform float norm_const;" "uniform float norm_const;"
"uniform float norm_offset;" "uniform float norm_offset;"
"uniform float kernel[9];" "uniform float kernel[9];"
"void main () {" "void main () {"
" float offset[9] = float[9] (-4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0);" " float offset[9] = float[9] (-4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0);"
" vec2 texturecoord = gl_TexCoord[0].st;" " vec2 texturecoord = gl_TexCoord[0].st;"
" int i;" " int i;"
" vec4 sum = vec4 (0.0);" " vec4 sum = vec4 (0.0);"
" for (i = 0; i < 9; i++) { " " for (i = 0; i < 9; i++) { "
" if (kernel[i] != 0.0) {" " if (kernel[i] != 0.0) {"
" vec4 neighbor = texture2DRect(tex, vec2(texturecoord.s, texturecoord.t+offset[i])); " " vec4 neighbor = texture2DRect(tex, vec2(texturecoord.s, texturecoord.t+offset[i])); "
" sum += neighbor * kernel[i]/norm_const; " " sum += neighbor * kernel[i]/norm_const; "
" }" " }" " }" " gl_FragColor = sum + norm_offset;" "}";
" }"
" gl_FragColor = sum + norm_offset;"
"}";
#define GST_CAT_DEFAULT gst_gl_filterblur_debug #define GST_CAT_DEFAULT gst_gl_filterblur_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
@ -119,39 +113,44 @@ GST_ELEMENT_DETAILS ("Gstreamer OpenGL Blur",
GST_DEBUG_CATEGORY_INIT (gst_gl_filterblur_debug, "glfilterblur", 0, "glfilterblur element"); GST_DEBUG_CATEGORY_INIT (gst_gl_filterblur_debug, "glfilterblur", 0, "glfilterblur element");
GST_BOILERPLATE_FULL (GstGLFilterBlur, gst_gl_filterblur, GstGLFilter, GST_BOILERPLATE_FULL (GstGLFilterBlur, gst_gl_filterblur, GstGLFilter,
GST_TYPE_GL_FILTER, DEBUG_INIT); GST_TYPE_GL_FILTER, DEBUG_INIT);
static void gst_gl_filterblur_set_property (GObject * object, guint prop_id, static void gst_gl_filterblur_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec); const GValue * value, GParamSpec * pspec);
static void gst_gl_filterblur_get_property (GObject * object, guint prop_id, static void gst_gl_filterblur_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
static void gst_gl_filter_filterblur_reset (GstGLFilter* filter); static void gst_gl_filter_filterblur_reset (GstGLFilter * filter);
static void gst_gl_filterblur_draw_texture (GstGLFilterBlur * filterblur, GLuint tex); static void gst_gl_filterblur_draw_texture (GstGLFilterBlur * filterblur,
GLuint tex);
static void gst_gl_filterblur_init_shader (GstGLFilter* filter); static void gst_gl_filterblur_init_shader (GstGLFilter * filter);
static gboolean gst_gl_filterblur_filter (GstGLFilter * filter, static gboolean gst_gl_filterblur_filter (GstGLFilter * filter,
GstGLBuffer * inbuf, GstGLBuffer * outbuf); GstGLBuffer * inbuf, GstGLBuffer * outbuf);
static void gst_gl_filterblur_hcallback (gint width, gint height, guint texture, gpointer stuff); static void gst_gl_filterblur_hcallback (gint width, gint height, guint texture,
static void gst_gl_filterblur_vcallback (gint width, gint height, guint texture, gpointer stuff); gpointer stuff);
static void gst_gl_filterblur_vcallback (gint width, gint height, guint texture,
gpointer stuff);
static void static void
gst_gl_filterblur_init_resources (GstGLFilter *filter) gst_gl_filterblur_init_resources (GstGLFilter * filter)
{ {
GstGLFilterBlur *filterblur = GST_GL_FILTERBLUR (filter); GstGLFilterBlur *filterblur = GST_GL_FILTERBLUR (filter);
glGenTextures (1, &filterblur->midtexture); glGenTextures (1, &filterblur->midtexture);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, filterblur->midtexture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, filterblur->midtexture);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
filter->width, filter->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); filter->width, filter->height, 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_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_TO_EDGE); glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
} }
static void static void
gst_gl_filterblur_reset_resources (GstGLFilter *filter) gst_gl_filterblur_reset_resources (GstGLFilter * filter)
{ {
GstGLFilterBlur *filterblur = GST_GL_FILTERBLUR (filter); GstGLFilterBlur *filterblur = GST_GL_FILTERBLUR (filter);
@ -176,14 +175,17 @@ gst_gl_filterblur_class_init (GstGLFilterBlurClass * klass)
gobject_class->get_property = gst_gl_filterblur_get_property; gobject_class->get_property = gst_gl_filterblur_get_property;
GST_GL_FILTER_CLASS (klass)->filter = gst_gl_filterblur_filter; GST_GL_FILTER_CLASS (klass)->filter = gst_gl_filterblur_filter;
GST_GL_FILTER_CLASS (klass)->display_init_cb = gst_gl_filterblur_init_resources; GST_GL_FILTER_CLASS (klass)->display_init_cb =
GST_GL_FILTER_CLASS (klass)->display_reset_cb = gst_gl_filterblur_reset_resources; gst_gl_filterblur_init_resources;
GST_GL_FILTER_CLASS (klass)->display_reset_cb =
gst_gl_filterblur_reset_resources;
GST_GL_FILTER_CLASS (klass)->onInitFBO = gst_gl_filterblur_init_shader; GST_GL_FILTER_CLASS (klass)->onInitFBO = gst_gl_filterblur_init_shader;
GST_GL_FILTER_CLASS (klass)->onReset = gst_gl_filter_filterblur_reset; GST_GL_FILTER_CLASS (klass)->onReset = gst_gl_filter_filterblur_reset;
} }
static void static void
gst_gl_filterblur_init (GstGLFilterBlur * filterblur, GstGLFilterBlurClass * klass) gst_gl_filterblur_init (GstGLFilterBlur * filterblur,
GstGLFilterBlurClass * klass)
{ {
filterblur->shader0 = NULL; filterblur->shader0 = NULL;
filterblur->shader1 = NULL; filterblur->shader1 = NULL;
@ -191,9 +193,9 @@ gst_gl_filterblur_init (GstGLFilterBlur * filterblur, GstGLFilterBlurClass * kla
} }
static void static void
gst_gl_filter_filterblur_reset (GstGLFilter* filter) gst_gl_filter_filterblur_reset (GstGLFilter * filter)
{ {
GstGLFilterBlur* filterblur = GST_GL_FILTERBLUR(filter); GstGLFilterBlur *filterblur = GST_GL_FILTERBLUR (filter);
//blocking call, wait the opengl thread has destroyed the shader //blocking call, wait the opengl thread has destroyed the shader
gst_gl_display_del_shader (filter->display, filterblur->shader0); gst_gl_display_del_shader (filter->display, filterblur->shader0);
@ -229,15 +231,17 @@ gst_gl_filterblur_get_property (GObject * object, guint prop_id,
} }
static void static void
gst_gl_filterblur_init_shader (GstGLFilter* filter) gst_gl_filterblur_init_shader (GstGLFilter * filter)
{ {
GstGLFilterBlur* blur_filter = GST_GL_FILTERBLUR (filter); GstGLFilterBlur *blur_filter = GST_GL_FILTERBLUR (filter);
//blocking call, wait the opengl thread has compiled the shader //blocking call, wait the opengl thread has compiled the shader
gst_gl_display_gen_shader (filter->display, 0, hconv9_fragment_source, &blur_filter->shader0); gst_gl_display_gen_shader (filter->display, 0, hconv9_fragment_source,
&blur_filter->shader0);
//blocking call, wait the opengl thread has compiled the shader //blocking call, wait the opengl thread has compiled the shader
gst_gl_display_gen_shader (filter->display, 0, vconv9_fragment_source, &blur_filter->shader1); gst_gl_display_gen_shader (filter->display, 0, vconv9_fragment_source,
&blur_filter->shader1);
} }
static void static void
@ -253,18 +257,18 @@ gst_gl_filterblur_draw_texture (GstGLFilterBlur * filterblur, GLuint tex)
glTexCoord2f (0.0, 0.0); glTexCoord2f (0.0, 0.0);
glVertex2f (-1.0, -1.0); glVertex2f (-1.0, -1.0);
glTexCoord2f ((gfloat)filter->width, 0.0); glTexCoord2f ((gfloat) filter->width, 0.0);
glVertex2f (1.0, -1.0); glVertex2f (1.0, -1.0);
glTexCoord2f ((gfloat)filter->width, (gfloat)filter->height); glTexCoord2f ((gfloat) filter->width, (gfloat) filter->height);
glVertex2f (1.0, 1.0); glVertex2f (1.0, 1.0);
glTexCoord2f (0.0, (gfloat)filter->height); glTexCoord2f (0.0, (gfloat) filter->height);
glVertex2f (-1.0, 1.0); glVertex2f (-1.0, 1.0);
glEnd (); glEnd ();
} }
static void static void
change_view (GstGLDisplay *display, gpointer data) change_view (GstGLDisplay * display, gpointer data)
{ {
// GstGLFilterBlur *filterblur = GST_GL_FILTERBLUR (data); // GstGLFilterBlur *filterblur = GST_GL_FILTERBLUR (data);
@ -280,33 +284,35 @@ change_view (GstGLDisplay *display, gpointer data)
} }
static gboolean static gboolean
gst_gl_filterblur_filter (GstGLFilter* filter, GstGLBuffer* inbuf, gst_gl_filterblur_filter (GstGLFilter * filter, GstGLBuffer * inbuf,
GstGLBuffer* outbuf) GstGLBuffer * outbuf)
{ {
GstGLFilterBlur* filterblur = GST_GL_FILTERBLUR(filter); GstGLFilterBlur *filterblur = GST_GL_FILTERBLUR (filter);
gst_gl_filter_render_to_target (filter, inbuf->texture, filterblur->midtexture, gst_gl_filter_render_to_target (filter, inbuf->texture,
gst_gl_filterblur_hcallback, filterblur); filterblur->midtexture, gst_gl_filterblur_hcallback, filterblur);
gst_gl_display_thread_add (filter->display, change_view, filterblur); gst_gl_display_thread_add (filter->display, change_view, filterblur);
gst_gl_filter_render_to_target (filter, filterblur->midtexture, outbuf->texture, gst_gl_filter_render_to_target (filter, filterblur->midtexture,
gst_gl_filterblur_vcallback, filterblur); outbuf->texture, gst_gl_filterblur_vcallback, filterblur);
return TRUE; return TRUE;
} }
static void static void
gst_gl_filterblur_hcallback (gint width, gint height, guint texture, gpointer stuff) gst_gl_filterblur_hcallback (gint width, gint height, guint texture,
gpointer stuff)
{ {
GstGLFilterBlur* filterblur = GST_GL_FILTERBLUR (stuff); GstGLFilterBlur *filterblur = GST_GL_FILTERBLUR (stuff);
/* hard coded kernel, it could be easily generated at runtime with a /* hard coded kernel, it could be easily generated at runtime with a
* property to change standard deviation */ * property to change standard deviation */
gfloat gauss_kernel[9] = { gfloat gauss_kernel[9] = {
0.026995f, 0.064759f, 0.120985f, 0.026995f, 0.064759f, 0.120985f,
0.176033f, 0.199471f, 0.176033f, 0.176033f, 0.199471f, 0.176033f,
0.120985f, 0.064759f, 0.026995f }; 0.120985f, 0.064759f, 0.026995f
};
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
@ -320,7 +326,8 @@ gst_gl_filterblur_hcallback (gint width, gint height, guint texture, gpointer st
gst_gl_shader_set_uniform_1i (filterblur->shader0, "tex", 1); gst_gl_shader_set_uniform_1i (filterblur->shader0, "tex", 1);
gst_gl_shader_set_uniform_1fv (filterblur->shader0, "kernel", 9, gauss_kernel); gst_gl_shader_set_uniform_1fv (filterblur->shader0, "kernel", 9,
gauss_kernel);
gst_gl_shader_set_uniform_1f (filterblur->shader0, "norm_const", 0.977016f); gst_gl_shader_set_uniform_1f (filterblur->shader0, "norm_const", 0.977016f);
gst_gl_shader_set_uniform_1f (filterblur->shader0, "norm_offset", 0.0f); gst_gl_shader_set_uniform_1f (filterblur->shader0, "norm_offset", 0.0f);
@ -329,16 +336,18 @@ gst_gl_filterblur_hcallback (gint width, gint height, guint texture, gpointer st
static void static void
gst_gl_filterblur_vcallback (gint width, gint height, guint texture, gpointer stuff) gst_gl_filterblur_vcallback (gint width, gint height, guint texture,
gpointer stuff)
{ {
GstGLFilterBlur* filterblur = GST_GL_FILTERBLUR (stuff); GstGLFilterBlur *filterblur = GST_GL_FILTERBLUR (stuff);
/* hard coded kernel, it could be easily generated at runtime with a /* hard coded kernel, it could be easily generated at runtime with a
* property to change standard deviation */ * property to change standard deviation */
gfloat gauss_kernel[9] = { gfloat gauss_kernel[9] = {
0.026995f, 0.064759f, 0.120985f, 0.026995f, 0.064759f, 0.120985f,
0.176033f, 0.199471f, 0.176033f, 0.176033f, 0.199471f, 0.176033f,
0.120985f, 0.064759f, 0.026995f }; 0.120985f, 0.064759f, 0.026995f
};
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
@ -352,7 +361,8 @@ gst_gl_filterblur_vcallback (gint width, gint height, guint texture, gpointer st
gst_gl_shader_set_uniform_1i (filterblur->shader1, "tex", 1); gst_gl_shader_set_uniform_1i (filterblur->shader1, "tex", 1);
gst_gl_shader_set_uniform_1fv (filterblur->shader1, "kernel", 9, gauss_kernel); gst_gl_shader_set_uniform_1fv (filterblur->shader1, "kernel", 9,
gauss_kernel);
gst_gl_shader_set_uniform_1f (filterblur->shader1, "norm_const", 0.977016f); gst_gl_shader_set_uniform_1f (filterblur->shader1, "norm_const", 0.977016f);
gst_gl_shader_set_uniform_1f (filterblur->shader1, "norm_offset", 0.0f); gst_gl_shader_set_uniform_1f (filterblur->shader1, "norm_offset", 0.0f);

View file

@ -49,22 +49,22 @@
#define GST_CAT_DEFAULT gst_gl_filter_cube_debug #define GST_CAT_DEFAULT gst_gl_filter_cube_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
static const GstElementDetails element_details = static const GstElementDetails element_details =
GST_ELEMENT_DETAILS ("OpenGL cube filter", GST_ELEMENT_DETAILS ("OpenGL cube filter",
"Filter/Effect", "Filter/Effect",
"Map input texture on the 6 cube faces", "Map input texture on the 6 cube faces",
"Julien Isorce <julien.isorce@gmail.com>"); "Julien Isorce <julien.isorce@gmail.com>");
enum enum
{ {
PROP_0, PROP_0,
PROP_RED, PROP_RED,
PROP_GREEN, PROP_GREEN,
PROP_BLUE, PROP_BLUE,
PROP_FOVY, PROP_FOVY,
PROP_ASPECT, PROP_ASPECT,
PROP_ZNEAR, PROP_ZNEAR,
PROP_ZFAR PROP_ZFAR
}; };
#define DEBUG_INIT(bla) \ #define DEBUG_INIT(bla) \
@ -73,223 +73,249 @@ enum
GST_BOILERPLATE_FULL (GstGLFilterCube, gst_gl_filter_cube, GstGLFilter, GST_BOILERPLATE_FULL (GstGLFilterCube, gst_gl_filter_cube, GstGLFilter,
GST_TYPE_GL_FILTER, DEBUG_INIT); GST_TYPE_GL_FILTER, DEBUG_INIT);
static void gst_gl_filter_cube_set_property (GObject* object, guint prop_id, static void gst_gl_filter_cube_set_property (GObject * object, guint prop_id,
const GValue* value, GParamSpec * pspec); const GValue * value, GParamSpec * pspec);
static void gst_gl_filter_cube_get_property (GObject* object, guint prop_id, static void gst_gl_filter_cube_get_property (GObject * object, guint prop_id,
GValue* value, GParamSpec* pspec); GValue * value, GParamSpec * pspec);
static gboolean gst_gl_filter_cube_set_caps (GstGLFilter* filter, static gboolean gst_gl_filter_cube_set_caps (GstGLFilter * filter,
GstCaps* incaps, GstCaps* outcaps); GstCaps * incaps, GstCaps * outcaps);
static gboolean gst_gl_filter_cube_filter (GstGLFilter* filter, static gboolean gst_gl_filter_cube_filter (GstGLFilter * filter,
GstGLBuffer* inbuf, GstGLBuffer* outbuf); GstGLBuffer * inbuf, GstGLBuffer * outbuf);
static void gst_gl_filter_cube_callback (gint width, gint height, guint texture, gpointer stuff); static void gst_gl_filter_cube_callback (gint width, gint height, guint texture,
gpointer stuff);
static void static void
gst_gl_filter_cube_base_init (gpointer klass) gst_gl_filter_cube_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_set_details (element_class, &element_details);
} }
static void static void
gst_gl_filter_cube_class_init (GstGLFilterCubeClass * klass) gst_gl_filter_cube_class_init (GstGLFilterCubeClass * klass)
{ {
GObjectClass* gobject_class; GObjectClass *gobject_class;
gobject_class = (GObjectClass *) klass; gobject_class = (GObjectClass *) klass;
gobject_class->set_property = gst_gl_filter_cube_set_property; gobject_class->set_property = gst_gl_filter_cube_set_property;
gobject_class->get_property = gst_gl_filter_cube_get_property; gobject_class->get_property = gst_gl_filter_cube_get_property;
GST_GL_FILTER_CLASS (klass)->set_caps = gst_gl_filter_cube_set_caps; GST_GL_FILTER_CLASS (klass)->set_caps = gst_gl_filter_cube_set_caps;
GST_GL_FILTER_CLASS (klass)->filter = gst_gl_filter_cube_filter; GST_GL_FILTER_CLASS (klass)->filter = gst_gl_filter_cube_filter;
g_object_class_install_property (gobject_class, PROP_RED, g_object_class_install_property (gobject_class, PROP_RED,
g_param_spec_float ("red", "Red", "Background red color", g_param_spec_float ("red", "Red", "Background red color",
0.0f, 1.0f, 0.0f, G_PARAM_WRITABLE)); 0.0f, 1.0f, 0.0f, G_PARAM_WRITABLE));
g_object_class_install_property (gobject_class, PROP_GREEN, g_object_class_install_property (gobject_class, PROP_GREEN,
g_param_spec_float ("green", "Green", "Background reen color", g_param_spec_float ("green", "Green", "Background reen color",
0.0f, 1.0f, 0.0f, G_PARAM_WRITABLE)); 0.0f, 1.0f, 0.0f, G_PARAM_WRITABLE));
g_object_class_install_property (gobject_class, PROP_BLUE, g_object_class_install_property (gobject_class, PROP_BLUE,
g_param_spec_float ("blue", "Blue", "Background blue color", g_param_spec_float ("blue", "Blue", "Background blue color",
0.0f, 1.0f, 0.0f, G_PARAM_WRITABLE)); 0.0f, 1.0f, 0.0f, G_PARAM_WRITABLE));
g_object_class_install_property (gobject_class, PROP_FOVY, g_object_class_install_property (gobject_class, PROP_FOVY,
g_param_spec_double ("fovy", "Fovy", "Field of view angle in degrees", g_param_spec_double ("fovy", "Fovy", "Field of view angle in degrees",
0.0, 180.0, 45.0, G_PARAM_WRITABLE)); 0.0, 180.0, 45.0, G_PARAM_WRITABLE));
g_object_class_install_property (gobject_class, PROP_ASPECT, g_object_class_install_property (gobject_class, PROP_ASPECT,
g_param_spec_double ("aspect", "Aspect", "Field of view in the x direction", g_param_spec_double ("aspect", "Aspect",
0.0, 100, 0.0, G_PARAM_WRITABLE)); "Field of view in the x direction", 0.0, 100, 0.0, G_PARAM_WRITABLE));
g_object_class_install_property (gobject_class, PROP_ZNEAR, g_object_class_install_property (gobject_class, PROP_ZNEAR,
g_param_spec_double ("znear", "Znear", g_param_spec_double ("znear", "Znear",
"Specifies the distance from the viewer to the near clipping plane", "Specifies the distance from the viewer to the near clipping plane",
0.0, 100.0, 0.1, G_PARAM_WRITABLE)); 0.0, 100.0, 0.1, G_PARAM_WRITABLE));
g_object_class_install_property (gobject_class, PROP_ZFAR, g_object_class_install_property (gobject_class, PROP_ZFAR,
g_param_spec_double ("zfar", "Zfar", g_param_spec_double ("zfar", "Zfar",
"Specifies the distance from the viewer to the far clipping plane", "Specifies the distance from the viewer to the far clipping plane",
0.0, 1000.0, 100.0, G_PARAM_WRITABLE)); 0.0, 1000.0, 100.0, G_PARAM_WRITABLE));
} }
static void static void
gst_gl_filter_cube_init (GstGLFilterCube* filter, gst_gl_filter_cube_init (GstGLFilterCube * filter, GstGLFilterCubeClass * klass)
GstGLFilterCubeClass* klass)
{ {
filter->fovy = 45; filter->fovy = 45;
filter->aspect = 0; filter->aspect = 0;
filter->znear = 0.1; filter->znear = 0.1;
filter->zfar = 100; filter->zfar = 100;
} }
static void static void
gst_gl_filter_cube_set_property (GObject* object, guint prop_id, gst_gl_filter_cube_set_property (GObject * object, guint prop_id,
const GValue* value, GParamSpec* pspec) const GValue * value, GParamSpec * pspec)
{ {
GstGLFilterCube* filter = GST_GL_FILTER_CUBE (object); GstGLFilterCube *filter = GST_GL_FILTER_CUBE (object);
switch (prop_id) switch (prop_id) {
{ case PROP_RED:
case PROP_RED: filter->red = g_value_get_float (value);
filter->red = g_value_get_float (value); break;
break; case PROP_GREEN:
case PROP_GREEN: filter->green = g_value_get_float (value);
filter->green = g_value_get_float (value); break;
break; case PROP_BLUE:
case PROP_BLUE: filter->blue = g_value_get_float (value);
filter->blue = g_value_get_float (value); break;
break; case PROP_FOVY:
case PROP_FOVY: filter->fovy = g_value_get_double (value);
filter->fovy = g_value_get_double (value); break;
break; case PROP_ASPECT:
case PROP_ASPECT: filter->aspect = g_value_get_double (value);
filter->aspect = g_value_get_double (value); break;
break; case PROP_ZNEAR:
case PROP_ZNEAR: filter->znear = g_value_get_double (value);
filter->znear = g_value_get_double (value); break;
break; case PROP_ZFAR:
case PROP_ZFAR: filter->zfar = g_value_get_double (value);
filter->zfar = g_value_get_double (value); break;
break; default:
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break;
break; }
}
} }
static void static void
gst_gl_filter_cube_get_property (GObject* object, guint prop_id, gst_gl_filter_cube_get_property (GObject * object, guint prop_id,
GValue* value, GParamSpec* pspec) GValue * value, GParamSpec * pspec)
{ {
//GstGLFilterCube* filter = GST_GL_FILTER_CUBE (object); //GstGLFilterCube* filter = GST_GL_FILTER_CUBE (object);
switch (prop_id) switch (prop_id) {
{ default:
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break;
break; }
}
} }
static gboolean static gboolean
gst_gl_filter_cube_set_caps (GstGLFilter* filter, GstCaps* incaps, gst_gl_filter_cube_set_caps (GstGLFilter * filter, GstCaps * incaps,
GstCaps* outcaps) GstCaps * outcaps)
{ {
GstGLFilterCube* cube_filter = GST_GL_FILTER_CUBE (filter); GstGLFilterCube *cube_filter = GST_GL_FILTER_CUBE (filter);
if (cube_filter->aspect == 0) if (cube_filter->aspect == 0)
cube_filter->aspect = (gdouble)filter->width / (gdouble)filter->height; cube_filter->aspect = (gdouble) filter->width / (gdouble) filter->height;
return TRUE; return TRUE;
} }
static gboolean static gboolean
gst_gl_filter_cube_filter (GstGLFilter* filter, GstGLBuffer* inbuf, gst_gl_filter_cube_filter (GstGLFilter * filter, GstGLBuffer * inbuf,
GstGLBuffer* outbuf) GstGLBuffer * outbuf)
{ {
GstGLFilterCube* cube_filter = GST_GL_FILTER_CUBE (filter); GstGLFilterCube *cube_filter = GST_GL_FILTER_CUBE (filter);
//blocking call, use a FBO
gst_gl_display_use_fbo (filter->display, filter->width, filter->height,
filter->fbo, filter->depthbuffer, outbuf->texture, gst_gl_filter_cube_callback,
inbuf->width, inbuf->height, inbuf->texture,
cube_filter->fovy, cube_filter->aspect, cube_filter->znear, cube_filter->zfar,
GST_GL_DISPLAY_PROJECTION_PERSPECIVE, (gpointer)cube_filter);
return TRUE; //blocking call, use a FBO
gst_gl_display_use_fbo (filter->display, filter->width, filter->height,
filter->fbo, filter->depthbuffer, outbuf->texture,
gst_gl_filter_cube_callback, inbuf->width, inbuf->height, inbuf->texture,
cube_filter->fovy, cube_filter->aspect, cube_filter->znear,
cube_filter->zfar, GST_GL_DISPLAY_PROJECTION_PERSPECIVE,
(gpointer) cube_filter);
return TRUE;
} }
//opengl scene, params: input texture (not the output filter->texture) //opengl scene, params: input texture (not the output filter->texture)
static void static void
gst_gl_filter_cube_callback (gint width, gint height, guint texture, gpointer stuff) gst_gl_filter_cube_callback (gint width, gint height, guint texture,
gpointer stuff)
{ {
static GLfloat xrot = 0; static GLfloat xrot = 0;
static GLfloat yrot = 0; static GLfloat yrot = 0;
static GLfloat zrot = 0; static GLfloat zrot = 0;
GstGLFilterCube* cube_filter = GST_GL_FILTER_CUBE (stuff); GstGLFilterCube *cube_filter = GST_GL_FILTER_CUBE (stuff);
glEnable(GL_DEPTH_TEST); glEnable (GL_DEPTH_TEST);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
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_TO_EDGE); glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); GL_CLAMP_TO_EDGE);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glClearColor(cube_filter->red, cube_filter->green, cube_filter->blue, 0.0); glClearColor (cube_filter->red, cube_filter->green, cube_filter->blue, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW); glMatrixMode (GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity ();
glTranslatef(0.0f,0.0f,-5.0f);
glRotatef(xrot,1.0f,0.0f,0.0f); glTranslatef (0.0f, 0.0f, -5.0f);
glRotatef(yrot,0.0f,1.0f,0.0f);
glRotatef(zrot,0.0f,0.0f,1.0f);
glBegin(GL_QUADS); glRotatef (xrot, 1.0f, 0.0f, 0.0f);
// Front Face glRotatef (yrot, 0.0f, 1.0f, 0.0f);
glTexCoord2f((gfloat)width, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glRotatef (zrot, 0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(0.0f, (gfloat)height); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f((gfloat)width, (gfloat)height); glVertex3f(-1.0f, 1.0f, 1.0f);
// Back Face
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, (gfloat)height); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f((gfloat)width, (gfloat)height); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f((gfloat)width, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
// Top Face
glTexCoord2f((gfloat)width, (gfloat)height); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f((gfloat)width, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, (gfloat)height); glVertex3f( 1.0f, 1.0f, -1.0f);
// Bottom Face
glTexCoord2f((gfloat)width, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, (gfloat)height); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f((gfloat)width,(gfloat)height); glVertex3f(-1.0f, -1.0f, 1.0f);
// Right face
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, (gfloat)height); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f((gfloat)width, (gfloat)height); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f((gfloat)width, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
// Left Face
glTexCoord2f((gfloat)width, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(0.0f, (gfloat)height); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f((gfloat)width, (gfloat)height); glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd();
xrot+=0.3f; glBegin (GL_QUADS);
yrot+=0.2f; // Front Face
zrot+=0.4f; glTexCoord2f ((gfloat) width, 0.0f);
glVertex3f (-1.0f, -1.0f, 1.0f);
glTexCoord2f (0.0f, 0.0f);
glVertex3f (1.0f, -1.0f, 1.0f);
glTexCoord2f (0.0f, (gfloat) height);
glVertex3f (1.0f, 1.0f, 1.0f);
glTexCoord2f ((gfloat) width, (gfloat) height);
glVertex3f (-1.0f, 1.0f, 1.0f);
// Back Face
glTexCoord2f (0.0f, 0.0f);
glVertex3f (-1.0f, -1.0f, -1.0f);
glTexCoord2f (0.0f, (gfloat) height);
glVertex3f (-1.0f, 1.0f, -1.0f);
glTexCoord2f ((gfloat) width, (gfloat) height);
glVertex3f (1.0f, 1.0f, -1.0f);
glTexCoord2f ((gfloat) width, 0.0f);
glVertex3f (1.0f, -1.0f, -1.0f);
// Top Face
glTexCoord2f ((gfloat) width, (gfloat) height);
glVertex3f (-1.0f, 1.0f, -1.0f);
glTexCoord2f ((gfloat) width, 0.0f);
glVertex3f (-1.0f, 1.0f, 1.0f);
glTexCoord2f (0.0f, 0.0f);
glVertex3f (1.0f, 1.0f, 1.0f);
glTexCoord2f (0.0f, (gfloat) height);
glVertex3f (1.0f, 1.0f, -1.0f);
// Bottom Face
glTexCoord2f ((gfloat) width, 0.0f);
glVertex3f (-1.0f, -1.0f, -1.0f);
glTexCoord2f (0.0f, 0.0f);
glVertex3f (1.0f, -1.0f, -1.0f);
glTexCoord2f (0.0f, (gfloat) height);
glVertex3f (1.0f, -1.0f, 1.0f);
glTexCoord2f ((gfloat) width, (gfloat) height);
glVertex3f (-1.0f, -1.0f, 1.0f);
// Right face
glTexCoord2f (0.0f, 0.0f);
glVertex3f (1.0f, -1.0f, -1.0f);
glTexCoord2f (0.0f, (gfloat) height);
glVertex3f (1.0f, 1.0f, -1.0f);
glTexCoord2f ((gfloat) width, (gfloat) height);
glVertex3f (1.0f, 1.0f, 1.0f);
glTexCoord2f ((gfloat) width, 0.0f);
glVertex3f (1.0f, -1.0f, 1.0f);
// Left Face
glTexCoord2f ((gfloat) width, 0.0f);
glVertex3f (-1.0f, -1.0f, -1.0f);
glTexCoord2f (0.0f, 0.0f);
glVertex3f (-1.0f, -1.0f, 1.0f);
glTexCoord2f (0.0f, (gfloat) height);
glVertex3f (-1.0f, 1.0f, 1.0f);
glTexCoord2f ((gfloat) width, (gfloat) height);
glVertex3f (-1.0f, 1.0f, -1.0f);
glEnd ();
glDisable(GL_DEPTH_TEST); xrot += 0.3f;
yrot += 0.2f;
zrot += 0.4f;
glDisable (GL_DEPTH_TEST);
} }

View file

@ -47,10 +47,10 @@
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
static const GstElementDetails element_details = static const GstElementDetails element_details =
GST_ELEMENT_DETAILS ("OpenGL glass filter", GST_ELEMENT_DETAILS ("OpenGL glass filter",
"Filter/Effect", "Filter/Effect",
"Glass Filter", "Glass Filter",
"Julien Isorce <julien.isorce@gmail.com>"); "Julien Isorce <julien.isorce@gmail.com>");
enum enum
{ {
@ -61,52 +61,49 @@ enum
GST_DEBUG_CATEGORY_INIT (gst_gl_filter_glass_debug, "glfilterglass", 0, "glfilterglass element"); GST_DEBUG_CATEGORY_INIT (gst_gl_filter_glass_debug, "glfilterglass", 0, "glfilterglass element");
GST_BOILERPLATE_FULL (GstGLFilterGlass, gst_gl_filter_glass, GstGLFilter, GST_BOILERPLATE_FULL (GstGLFilterGlass, gst_gl_filter_glass, GstGLFilter,
GST_TYPE_GL_FILTER, DEBUG_INIT); GST_TYPE_GL_FILTER, DEBUG_INIT);
static void gst_gl_filter_glass_set_property (GObject * object, guint prop_id, static void gst_gl_filter_glass_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec); const GValue * value, GParamSpec * pspec);
static void gst_gl_filter_glass_get_property (GObject * object, guint prop_id, static void gst_gl_filter_glass_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
static void gst_gl_filter_glass_reset (GstGLFilter* filter); static void gst_gl_filter_glass_reset (GstGLFilter * filter);
static void gst_gl_filter_glass_init_shader (GstGLFilter* filter); static void gst_gl_filter_glass_init_shader (GstGLFilter * filter);
static gboolean gst_gl_filter_glass_filter (GstGLFilter * filter, static gboolean gst_gl_filter_glass_filter (GstGLFilter * filter,
GstGLBuffer * inbuf, GstGLBuffer * outbuf); GstGLBuffer * inbuf, GstGLBuffer * outbuf);
static void gst_gl_filter_glass_draw_background_gradient (); static void gst_gl_filter_glass_draw_background_gradient ();
static void gst_gl_filter_glass_draw_video_plane (GstGLFilter* filter, static void gst_gl_filter_glass_draw_video_plane (GstGLFilter * filter,
gint width, gint height, guint texture, gfloat center_x, gfloat center_y, gint width, gint height, guint texture, gfloat center_x, gfloat center_y,
gfloat start_alpha, gfloat stop_alpha, gboolean reversed); gfloat start_alpha, gfloat stop_alpha, gboolean reversed);
static void gst_gl_filter_glass_callback (gint width, gint height, guint texture, gpointer stuff); static void gst_gl_filter_glass_callback (gint width, gint height,
guint texture, gpointer stuff);
static const gchar *glass_fragment_source = static const gchar *glass_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect tex;" "uniform sampler2DRect tex;"
"uniform float width, height;" "uniform float width, height;"
"void main () {" "void main () {"
" float p = 0.0525;" " float p = 0.0525;"
" float L1 = p*width;" " float L1 = p*width;"
" float L2 = width - L1;" " float L2 = width - L1;"
" float L3 = height - L1;" " float L3 = height - L1;"
" float w = 1.0;" " float w = 1.0;"
" float r = L1;" " float r = L1;"
" if (gl_TexCoord[0].x < L1 && gl_TexCoord[0].y < L1)" " if (gl_TexCoord[0].x < L1 && gl_TexCoord[0].y < L1)"
" r = sqrt( (gl_TexCoord[0].x - L1) * (gl_TexCoord[0].x - L1) + (gl_TexCoord[0].y - L1) * (gl_TexCoord[0].y - L1) );" " r = sqrt( (gl_TexCoord[0].x - L1) * (gl_TexCoord[0].x - L1) + (gl_TexCoord[0].y - L1) * (gl_TexCoord[0].y - L1) );"
" else if (gl_TexCoord[0].x > L2 && gl_TexCoord[0].y < L1)"
" else if (gl_TexCoord[0].x > L2 && gl_TexCoord[0].y < L1)" " r = sqrt( (gl_TexCoord[0].x - L2) * (gl_TexCoord[0].x - L2) + (gl_TexCoord[0].y - L1) * (gl_TexCoord[0].y - L1) );"
" r = sqrt( (gl_TexCoord[0].x - L2) * (gl_TexCoord[0].x - L2) + (gl_TexCoord[0].y - L1) * (gl_TexCoord[0].y - L1) );" " else if (gl_TexCoord[0].x > L2 && gl_TexCoord[0].y > L3)"
" r = sqrt( (gl_TexCoord[0].x - L2) * (gl_TexCoord[0].x - L2) + (gl_TexCoord[0].y - L3) * (gl_TexCoord[0].y - L3) );"
" else if (gl_TexCoord[0].x > L2 && gl_TexCoord[0].y > L3)" " else if (gl_TexCoord[0].x < L1 && gl_TexCoord[0].y > L3)"
" r = sqrt( (gl_TexCoord[0].x - L2) * (gl_TexCoord[0].x - L2) + (gl_TexCoord[0].y - L3) * (gl_TexCoord[0].y - L3) );" " r = sqrt( (gl_TexCoord[0].x - L1) * (gl_TexCoord[0].x - L1) + (gl_TexCoord[0].y - L3) * (gl_TexCoord[0].y - L3) );"
" if (r > L1)"
" else if (gl_TexCoord[0].x < L1 && gl_TexCoord[0].y > L3)" " w = 0.0;"
" r = sqrt( (gl_TexCoord[0].x - L1) * (gl_TexCoord[0].x - L1) + (gl_TexCoord[0].y - L3) * (gl_TexCoord[0].y - L3) );" " vec4 color = texture2DRect (tex, gl_TexCoord[0].st);"
" if (r > L1)" " gl_FragColor = vec4(color.rgb, gl_Color.a * w);" "}";
" w = 0.0;"
" vec4 color = texture2DRect (tex, gl_TexCoord[0].st);"
" gl_FragColor = vec4(color.rgb, gl_Color.a * w);"
"}";
static void static void
gst_gl_filter_glass_base_init (gpointer klass) gst_gl_filter_glass_base_init (gpointer klass)
@ -117,9 +114,9 @@ gst_gl_filter_glass_base_init (gpointer klass)
} }
static void static void
gst_gl_filter_glass_class_init (GstGLFilterGlassClass* klass) gst_gl_filter_glass_class_init (GstGLFilterGlassClass * klass)
{ {
GObjectClass* gobject_class; GObjectClass *gobject_class;
gobject_class = (GObjectClass *) klass; gobject_class = (GObjectClass *) klass;
gobject_class->set_property = gst_gl_filter_glass_set_property; gobject_class->set_property = gst_gl_filter_glass_set_property;
@ -131,72 +128,71 @@ gst_gl_filter_glass_class_init (GstGLFilterGlassClass* klass)
} }
static void static void
gst_gl_filter_glass_init (GstGLFilterGlass* filter, gst_gl_filter_glass_init (GstGLFilterGlass * filter,
GstGLFilterGlassClass* klass) GstGLFilterGlassClass * klass)
{ {
filter->shader = NULL; filter->shader = NULL;
filter->timestamp = 0; filter->timestamp = 0;
} }
static void static void
gst_gl_filter_glass_reset (GstGLFilter* filter) gst_gl_filter_glass_reset (GstGLFilter * filter)
{ {
GstGLFilterGlass* glass_filter = GST_GL_FILTER_GLASS(filter); GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter);
//blocking call, wait the opengl thread has destroyed the shader //blocking call, wait the opengl thread has destroyed the shader
gst_gl_display_del_shader (filter->display, glass_filter->shader); gst_gl_display_del_shader (filter->display, glass_filter->shader);
} }
static void static void
gst_gl_filter_glass_set_property (GObject* object, guint prop_id, gst_gl_filter_glass_set_property (GObject * object, guint prop_id,
const GValue* value, GParamSpec* pspec) const GValue * value, GParamSpec * pspec)
{ {
//GstGLFilterGlass *filter = GST_GL_FILTER_GLASS (object); //GstGLFilterGlass *filter = GST_GL_FILTER_GLASS (object);
switch (prop_id) switch (prop_id) {
{ default:
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break;
break;
} }
} }
static void static void
gst_gl_filter_glass_get_property (GObject* object, guint prop_id, gst_gl_filter_glass_get_property (GObject * object, guint prop_id,
GValue* value, GParamSpec* pspec) GValue * value, GParamSpec * pspec)
{ {
//GstGLFilterGlass *filter = GST_GL_FILTER_GLASS (object); //GstGLFilterGlass *filter = GST_GL_FILTER_GLASS (object);
switch (prop_id) switch (prop_id) {
{ default:
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break;
break;
} }
} }
static void static void
gst_gl_filter_glass_init_shader (GstGLFilter* filter) gst_gl_filter_glass_init_shader (GstGLFilter * filter)
{ {
GstGLFilterGlass* glass_filter = GST_GL_FILTER_GLASS (filter); GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter);
//blocking call, wait the opengl thread has compiled the shader //blocking call, wait the opengl thread has compiled the shader
gst_gl_display_gen_shader (filter->display, 0, glass_fragment_source, &glass_filter->shader); gst_gl_display_gen_shader (filter->display, 0, glass_fragment_source,
&glass_filter->shader);
} }
static gboolean static gboolean
gst_gl_filter_glass_filter (GstGLFilter* filter, GstGLBuffer* inbuf, gst_gl_filter_glass_filter (GstGLFilter * filter, GstGLBuffer * inbuf,
GstGLBuffer* outbuf) GstGLBuffer * outbuf)
{ {
gpointer glass_filter = GST_GL_FILTER_GLASS (filter); gpointer glass_filter = GST_GL_FILTER_GLASS (filter);
GST_GL_FILTER_GLASS(glass_filter)->timestamp = GST_BUFFER_TIMESTAMP (inbuf); GST_GL_FILTER_GLASS (glass_filter)->timestamp = GST_BUFFER_TIMESTAMP (inbuf);
//blocking call, use a FBO //blocking call, use a FBO
gst_gl_display_use_fbo (filter->display, filter->width, filter->height, gst_gl_display_use_fbo (filter->display, filter->width, filter->height,
filter->fbo, filter->depthbuffer, outbuf->texture, gst_gl_filter_glass_callback, filter->fbo, filter->depthbuffer, outbuf->texture,
inbuf->width, inbuf->height, inbuf->texture, gst_gl_filter_glass_callback, inbuf->width, inbuf->height, inbuf->texture,
80, (gdouble)filter->width/(gdouble)filter->height, 1.0, 5000.0, 80, (gdouble) filter->width / (gdouble) filter->height, 1.0, 5000.0,
GST_GL_DISPLAY_PROJECTION_PERSPECIVE, (gpointer)glass_filter); GST_GL_DISPLAY_PROJECTION_PERSPECIVE, (gpointer) glass_filter);
return TRUE; return TRUE;
} }
@ -204,60 +200,59 @@ gst_gl_filter_glass_filter (GstGLFilter* filter, GstGLBuffer* inbuf,
static gint64 static gint64
get_time (void) get_time (void)
{ {
static GTimeVal val; static GTimeVal val;
g_get_current_time (&val); g_get_current_time (&val);
return (val.tv_sec * G_USEC_PER_SEC) + val.tv_usec; return (val.tv_sec * G_USEC_PER_SEC) + val.tv_usec;
} }
static void static void
gst_gl_filter_glass_draw_background_gradient () gst_gl_filter_glass_draw_background_gradient ()
{ {
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glPushMatrix (); glPushMatrix ();
glLoadIdentity (); glLoadIdentity ();
glOrtho (-100, 100, -100, 100, -1000.0, 1000.0); glOrtho (-100, 100, -100, 100, -1000.0, 1000.0);
glBegin (GL_QUADS); glBegin (GL_QUADS);
glColor4f (0.0f, 0.0f, 0.0f, 1.0f); glColor4f (0.0f, 0.0f, 0.0f, 1.0f);
glVertex2f (-100.0f, -100.0f); glVertex2f (-100.0f, -100.0f);
glVertex2f (100.0f, -100.0f); glVertex2f (100.0f, -100.0f);
glColor4f (0.0f, 0.0f, 0.2f, 1.0f); glColor4f (0.0f, 0.0f, 0.2f, 1.0f);
glVertex2f (100.0f, 80.0f); glVertex2f (100.0f, 80.0f);
glVertex2f (-100.0f, 80.0f); glVertex2f (-100.0f, 80.0f);
glVertex2f (100.0f, 80.0f); glVertex2f (100.0f, 80.0f);
glVertex2f (-100.0f, 80.0f); glVertex2f (-100.0f, 80.0f);
glVertex2f (-100.0f, 100.0f); glVertex2f (-100.0f, 100.0f);
glVertex2f (100.0f, 100.0f); glVertex2f (100.0f, 100.0f);
glEnd (); glEnd ();
glPopMatrix (); glPopMatrix ();
glMatrixMode (GL_MODELVIEW); glMatrixMode (GL_MODELVIEW);
} }
static void static void
gst_gl_filter_glass_draw_video_plane (GstGLFilter* filter, gst_gl_filter_glass_draw_video_plane (GstGLFilter * filter,
gint width, gint height, guint texture, gint width, gint height, guint texture,
gfloat center_x, gfloat center_y, gfloat center_x, gfloat center_y,
gfloat start_alpha, gfloat stop_alpha, gfloat start_alpha, gfloat stop_alpha, gboolean reversed)
gboolean reversed)
{ {
GstGLFilterGlass* glass_filter = GST_GL_FILTER_GLASS (filter); GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter);
gfloat topy; gfloat topy;
gfloat bottomy; gfloat bottomy;
if (reversed) { if (reversed) {
topy = center_y - 1.0f; topy = center_y - 1.0f;
bottomy = center_y + 1.0f; bottomy = center_y + 1.0f;
} else { } else {
topy = center_y + 1.0f; topy = center_y + 1.0f;
bottomy = center_y - 1.0f; bottomy = center_y - 1.0f;
} }
gst_gl_shader_use (glass_filter->shader); gst_gl_shader_use (glass_filter->shader);
@ -267,22 +262,23 @@ gst_gl_filter_glass_draw_video_plane (GstGLFilter* filter,
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
glDisable (GL_TEXTURE_RECTANGLE_ARB); glDisable (GL_TEXTURE_RECTANGLE_ARB);
gst_gl_shader_set_uniform_1i (glass_filter->shader, "tex", 0); gst_gl_shader_set_uniform_1i (glass_filter->shader, "tex", 0);
gst_gl_shader_set_uniform_1f (glass_filter->shader, "width", (gfloat)width); gst_gl_shader_set_uniform_1f (glass_filter->shader, "width", (gfloat) width);
gst_gl_shader_set_uniform_1f (glass_filter->shader, "height", (gfloat)height); gst_gl_shader_set_uniform_1f (glass_filter->shader, "height",
(gfloat) height);
glBegin (GL_QUADS); glBegin (GL_QUADS);
glColor4f (1.0f, 1.0f, 1.0f, start_alpha); glColor4f (1.0f, 1.0f, 1.0f, start_alpha);
glTexCoord2i (0, height); glTexCoord2i (0, height);
glVertex2f (center_x - 1.6f, topy); glVertex2f (center_x - 1.6f, topy);
glTexCoord2i (width, height); glTexCoord2i (width, height);
glVertex2f (center_x + 1.6f, topy); glVertex2f (center_x + 1.6f, topy);
glColor4f (1.0, 1.0, 1.0, stop_alpha); glColor4f (1.0, 1.0, 1.0, stop_alpha);
glTexCoord2i (width, 0); glTexCoord2i (width, 0);
glVertex2f (center_x + 1.6f, bottomy); glVertex2f (center_x + 1.6f, bottomy);
glTexCoord2i (0, 0); glTexCoord2i (0, 0);
glVertex2f (center_x - 1.6f, bottomy); glVertex2f (center_x - 1.6f, bottomy);
glEnd (); glEnd ();
gst_gl_shader_use (0); gst_gl_shader_use (0);
@ -290,35 +286,35 @@ gst_gl_filter_glass_draw_video_plane (GstGLFilter* filter,
//opengl scene, params: input texture (not the output filter->texture) //opengl scene, params: input texture (not the output filter->texture)
static void static void
gst_gl_filter_glass_callback (gint width, gint height, guint texture, gpointer stuff) gst_gl_filter_glass_callback (gint width, gint height, guint texture,
gpointer stuff)
{ {
static gint64 start_time = 0; static gint64 start_time = 0;
GstGLFilter* filter = GST_GL_FILTER (stuff); GstGLFilter *filter = GST_GL_FILTER (stuff);
GstGLFilterGlass* glass_filter = GST_GL_FILTER_GLASS (stuff); GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (stuff);
if (start_time == 0) if (start_time == 0)
start_time = get_time (); start_time = get_time ();
else else {
{ gint64 time_left =
gint64 time_left = (glass_filter->timestamp / 1000) - (get_time () - start_time); (glass_filter->timestamp / 1000) - (get_time () - start_time);
time_left -= 1000000 / 25; time_left -= 1000000 / 25;
if (time_left > 2000) if (time_left > 2000) {
{ GST_LOG ("escape");
GST_LOG ("escape"); return;
return;
} }
} }
glTranslatef(0.0f, 2.0f, -3.0f); glTranslatef (0.0f, 2.0f, -3.0f);
gst_gl_filter_glass_draw_background_gradient (); gst_gl_filter_glass_draw_background_gradient ();
//Rotation //Rotation
if (start_time != 0) { if (start_time != 0) {
gint64 time_passed = get_time () - start_time; gint64 time_passed = get_time () - start_time;
glRotated (sin (time_passed / 1200000.0) * 45.0, 0.0, 1.0, 0.0); glRotated (sin (time_passed / 1200000.0) * 45.0, 0.0, 1.0, 0.0);
} }
glEnable (GL_BLEND); glEnable (GL_BLEND);
@ -326,11 +322,11 @@ gst_gl_filter_glass_callback (gint width, gint height, guint texture, gpointer s
//Reflection //Reflection
gst_gl_filter_glass_draw_video_plane (filter, width, height, texture, gst_gl_filter_glass_draw_video_plane (filter, width, height, texture,
0.0f, 0.0f, 0.3f, 0.0f, TRUE); 0.0f, 0.0f, 0.3f, 0.0f, TRUE);
//Main video //Main video
gst_gl_filter_glass_draw_video_plane (filter, width, height, texture, gst_gl_filter_glass_draw_video_plane (filter, width, height, texture,
0.0f, -2.0f, 1.0f, 1.0f, FALSE); 0.0f, -2.0f, 1.0f, 1.0f, FALSE);
glDisable (GL_TEXTURE_RECTANGLE_ARB); glDisable (GL_TEXTURE_RECTANGLE_ARB);
glDisable (GL_BLEND); glDisable (GL_BLEND);

View file

@ -42,10 +42,10 @@
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
static const GstElementDetails element_details = static const GstElementDetails element_details =
GST_ELEMENT_DETAILS ("OpenGL laplacian filter", GST_ELEMENT_DETAILS ("OpenGL laplacian filter",
"Filter/Effect", "Filter/Effect",
"Laplacian Convolution Demo Filter", "Laplacian Convolution Demo Filter",
"Filippo Argiolas <filippo.argiolas@gmail.com>"); "Filippo Argiolas <filippo.argiolas@gmail.com>");
enum enum
{ {
@ -55,42 +55,40 @@ enum
#define DEBUG_INIT(bla) \ #define DEBUG_INIT(bla) \
GST_DEBUG_CATEGORY_INIT (gst_gl_filter_laplacian_debug, "glfilterlaplacian", 0, "glfilterlaplacian element"); GST_DEBUG_CATEGORY_INIT (gst_gl_filter_laplacian_debug, "glfilterlaplacian", 0, "glfilterlaplacian element");
GST_BOILERPLATE_FULL (GstGLFilterLaplacian, gst_gl_filter_laplacian, GstGLFilter, GST_BOILERPLATE_FULL (GstGLFilterLaplacian, gst_gl_filter_laplacian,
GST_TYPE_GL_FILTER, DEBUG_INIT); GstGLFilter, GST_TYPE_GL_FILTER, DEBUG_INIT);
static void gst_gl_filter_laplacian_set_property (GObject * object, guint prop_id, static void gst_gl_filter_laplacian_set_property (GObject * object,
const GValue * value, GParamSpec * pspec); guint prop_id, const GValue * value, GParamSpec * pspec);
static void gst_gl_filter_laplacian_get_property (GObject * object, guint prop_id, static void gst_gl_filter_laplacian_get_property (GObject * object,
GValue * value, GParamSpec * pspec); guint prop_id, GValue * value, GParamSpec * pspec);
static void gst_gl_filter_laplacian_reset (GstGLFilter* filter); static void gst_gl_filter_laplacian_reset (GstGLFilter * filter);
static void gst_gl_filter_laplacian_init_shader (GstGLFilter* filter); static void gst_gl_filter_laplacian_init_shader (GstGLFilter * filter);
static gboolean gst_gl_filter_laplacian_filter (GstGLFilter * filter, static gboolean gst_gl_filter_laplacian_filter (GstGLFilter * filter,
GstGLBuffer * inbuf, GstGLBuffer * outbuf); GstGLBuffer * inbuf, GstGLBuffer * outbuf);
static void gst_gl_filter_laplacian_callback (gint width, gint height, guint texture, gpointer stuff); static void gst_gl_filter_laplacian_callback (gint width, gint height,
guint texture, gpointer stuff);
static const gchar *convolution_fragment_source = static const gchar *convolution_fragment_source =
"#extension GL_ARB_texture_rectangle : enable\n" "#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect tex;" "uniform sampler2DRect tex;"
"uniform float norm_const;" "uniform float norm_const;"
"uniform float norm_offset;" "uniform float norm_offset;"
"uniform float kernel[9];" "uniform float kernel[9];"
"void main () {" "void main () {"
" vec2 offset[9] = vec2[9] (" " vec2 offset[9] = vec2[9] ("
" vec2(-1.0,-1.0), vec2( 0.0,-1.0), vec2( 1.0,-1.0)," " vec2(-1.0,-1.0), vec2( 0.0,-1.0), vec2( 1.0,-1.0),"
" vec2(-1.0, 0.0), vec2( 0.0, 0.0), vec2( 1.0, 0.0)," " vec2(-1.0, 0.0), vec2( 0.0, 0.0), vec2( 1.0, 0.0),"
" vec2(-1.0, 1.0), vec2( 0.0, 1.0), vec2( 1.0, 1.0) );" " vec2(-1.0, 1.0), vec2( 0.0, 1.0), vec2( 1.0, 1.0) );"
" vec2 texturecoord = gl_TexCoord[0].st;" " vec2 texturecoord = gl_TexCoord[0].st;"
" int i;" " int i;"
" vec4 sum = vec4 (0.0);" " vec4 sum = vec4 (0.0);"
" for (i = 0; i < 9; i++) { " " for (i = 0; i < 9; i++) { "
" if (kernel[i] != 0.0) {" " if (kernel[i] != 0.0) {"
" vec4 neighbor = texture2DRect(tex, texturecoord + vec2(offset[i])); " " vec4 neighbor = texture2DRect(tex, texturecoord + vec2(offset[i])); "
" sum += neighbor * kernel[i]/norm_const; " " sum += neighbor * kernel[i]/norm_const; "
" }" " }" " }" " gl_FragColor = sum + norm_offset;" "}";
" }"
" gl_FragColor = sum + norm_offset;"
"}";
static void static void
gst_gl_filter_laplacian_base_init (gpointer klass) gst_gl_filter_laplacian_base_init (gpointer klass)
@ -101,9 +99,9 @@ gst_gl_filter_laplacian_base_init (gpointer klass)
} }
static void static void
gst_gl_filter_laplacian_class_init (GstGLFilterLaplacianClass* klass) gst_gl_filter_laplacian_class_init (GstGLFilterLaplacianClass * klass)
{ {
GObjectClass* gobject_class; GObjectClass *gobject_class;
gobject_class = (GObjectClass *) klass; gobject_class = (GObjectClass *) klass;
gobject_class->set_property = gst_gl_filter_laplacian_set_property; gobject_class->set_property = gst_gl_filter_laplacian_set_property;
@ -115,83 +113,84 @@ gst_gl_filter_laplacian_class_init (GstGLFilterLaplacianClass* klass)
} }
static void static void
gst_gl_filter_laplacian_init (GstGLFilterLaplacian* filter, gst_gl_filter_laplacian_init (GstGLFilterLaplacian * filter,
GstGLFilterLaplacianClass* klass) GstGLFilterLaplacianClass * klass)
{ {
filter->shader = NULL; filter->shader = NULL;
} }
static void static void
gst_gl_filter_laplacian_reset (GstGLFilter* filter) gst_gl_filter_laplacian_reset (GstGLFilter * filter)
{ {
GstGLFilterLaplacian* laplacian_filter = GST_GL_FILTER_LAPLACIAN(filter); GstGLFilterLaplacian *laplacian_filter = GST_GL_FILTER_LAPLACIAN (filter);
//blocking call, wait the opengl thread has destroyed the shader //blocking call, wait the opengl thread has destroyed the shader
gst_gl_display_del_shader (filter->display, laplacian_filter->shader); gst_gl_display_del_shader (filter->display, laplacian_filter->shader);
} }
static void static void
gst_gl_filter_laplacian_set_property (GObject* object, guint prop_id, gst_gl_filter_laplacian_set_property (GObject * object, guint prop_id,
const GValue* value, GParamSpec* pspec) const GValue * value, GParamSpec * pspec)
{ {
//GstGLFilterLaplacian *filter = GST_GL_FILTER_LAPLACIAN (object); //GstGLFilterLaplacian *filter = GST_GL_FILTER_LAPLACIAN (object);
switch (prop_id) switch (prop_id) {
{ default:
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break;
break;
} }
} }
static void static void
gst_gl_filter_laplacian_get_property (GObject* object, guint prop_id, gst_gl_filter_laplacian_get_property (GObject * object, guint prop_id,
GValue* value, GParamSpec* pspec) GValue * value, GParamSpec * pspec)
{ {
//GstGLFilterLaplacian *filter = GST_GL_FILTER_LAPLACIAN (object); //GstGLFilterLaplacian *filter = GST_GL_FILTER_LAPLACIAN (object);
switch (prop_id) switch (prop_id) {
{ default:
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break;
break;
} }
} }
static void static void
gst_gl_filter_laplacian_init_shader (GstGLFilter* filter) gst_gl_filter_laplacian_init_shader (GstGLFilter * filter)
{ {
GstGLFilterLaplacian* laplacian_filter = GST_GL_FILTER_LAPLACIAN (filter); GstGLFilterLaplacian *laplacian_filter = GST_GL_FILTER_LAPLACIAN (filter);
//blocking call, wait the opengl thread has compiled the shader //blocking call, wait the opengl thread has compiled the shader
gst_gl_display_gen_shader (filter->display, 0, convolution_fragment_source, &laplacian_filter->shader); gst_gl_display_gen_shader (filter->display, 0, convolution_fragment_source,
&laplacian_filter->shader);
} }
static gboolean static gboolean
gst_gl_filter_laplacian_filter (GstGLFilter* filter, GstGLBuffer* inbuf, gst_gl_filter_laplacian_filter (GstGLFilter * filter, GstGLBuffer * inbuf,
GstGLBuffer* outbuf) GstGLBuffer * outbuf)
{ {
gpointer laplacian_filter = GST_GL_FILTER_LAPLACIAN (filter); gpointer laplacian_filter = GST_GL_FILTER_LAPLACIAN (filter);
//blocking call, use a FBO //blocking call, use a FBO
gst_gl_display_use_fbo (filter->display, filter->width, filter->height, gst_gl_display_use_fbo (filter->display, filter->width, filter->height,
filter->fbo, filter->depthbuffer, outbuf->texture, gst_gl_filter_laplacian_callback, filter->fbo, filter->depthbuffer, outbuf->texture,
inbuf->width, inbuf->height, inbuf->texture, gst_gl_filter_laplacian_callback, inbuf->width, inbuf->height,
0, filter->width, 0, filter->height, inbuf->texture, 0, filter->width, 0, filter->height,
GST_GL_DISPLAY_PROJECTION_ORTHO2D, laplacian_filter); GST_GL_DISPLAY_PROJECTION_ORTHO2D, laplacian_filter);
return TRUE; return TRUE;
} }
//opengl scene, params: input texture (not the output filter->texture) //opengl scene, params: input texture (not the output filter->texture)
static void static void
gst_gl_filter_laplacian_callback (gint width, gint height, guint texture, gpointer stuff) gst_gl_filter_laplacian_callback (gint width, gint height, guint texture,
gpointer stuff)
{ {
GstGLFilterLaplacian* laplacian_filter = GST_GL_FILTER_LAPLACIAN (stuff); GstGLFilterLaplacian *laplacian_filter = GST_GL_FILTER_LAPLACIAN (stuff);
gfloat kernel[9] = { 0.0, -1.0, 0.0, gfloat kernel[9] = { 0.0, -1.0, 0.0,
-1.0, 4.0, -1.0, -1.0, 4.0, -1.0,
0.0, -1.0, 0.0 }; 0.0, -1.0, 0.0
};
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
@ -202,10 +201,10 @@ gst_gl_filter_laplacian_callback (gint width, gint height, guint texture, gpoint
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
gst_gl_shader_set_uniform_1i (laplacian_filter->shader, "tex", 0); gst_gl_shader_set_uniform_1i (laplacian_filter->shader, "tex", 0);
gst_gl_shader_set_uniform_1fv (laplacian_filter->shader, "kernel", 9, kernel); gst_gl_shader_set_uniform_1fv (laplacian_filter->shader, "kernel", 9, kernel);
gst_gl_shader_set_uniform_1f (laplacian_filter->shader, "norm_const", 1.0); gst_gl_shader_set_uniform_1f (laplacian_filter->shader, "norm_const", 1.0);
gst_gl_shader_set_uniform_1f (laplacian_filter->shader, "norm_offset", 0.0); //set to 0.5 to preserve overall greylevel gst_gl_shader_set_uniform_1f (laplacian_filter->shader, "norm_offset", 0.0); //set to 0.5 to preserve overall greylevel
glBegin (GL_QUADS); glBegin (GL_QUADS);

View file

@ -85,37 +85,41 @@ GST_ELEMENT_DETAILS ("Gstreamer OpenGL Sobel",
GST_DEBUG_CATEGORY_INIT (gst_gl_filtersobel_debug, "glfiltersobel", 0, "glfiltersobel element"); GST_DEBUG_CATEGORY_INIT (gst_gl_filtersobel_debug, "glfiltersobel", 0, "glfiltersobel element");
GST_BOILERPLATE_FULL (GstGLFilterSobel, gst_gl_filtersobel, GstGLFilter, GST_BOILERPLATE_FULL (GstGLFilterSobel, gst_gl_filtersobel, GstGLFilter,
GST_TYPE_GL_FILTER, DEBUG_INIT); GST_TYPE_GL_FILTER, DEBUG_INIT);
static void gst_gl_filtersobel_set_property (GObject * object, guint prop_id, static void gst_gl_filtersobel_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec); const GValue * value, GParamSpec * pspec);
static void gst_gl_filtersobel_get_property (GObject * object, guint prop_id, static void gst_gl_filtersobel_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
static void gst_gl_filter_filtersobel_reset (GstGLFilter* filter); static void gst_gl_filter_filtersobel_reset (GstGLFilter * filter);
static void gst_gl_filtersobel_draw_texture (GstGLFilterSobel * filtersobel, GLuint tex); static void gst_gl_filtersobel_draw_texture (GstGLFilterSobel * filtersobel,
GLuint tex);
static void gst_gl_filtersobel_init_shader (GstGLFilter* filter); static void gst_gl_filtersobel_init_shader (GstGLFilter * filter);
static gboolean gst_gl_filtersobel_filter (GstGLFilter * filter, static gboolean gst_gl_filtersobel_filter (GstGLFilter * filter,
GstGLBuffer * inbuf, GstGLBuffer * outbuf); GstGLBuffer * inbuf, GstGLBuffer * outbuf);
static void gst_gl_filtersobel_callback (gint width, gint height, guint texture, gpointer stuff); static void gst_gl_filtersobel_callback (gint width, gint height, guint texture,
gpointer stuff);
static void static void
gst_gl_filtersobel_init_resources (GstGLFilter *filter) gst_gl_filtersobel_init_resources (GstGLFilter * filter)
{ {
GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (filter); GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (filter);
glGenTextures (1, &filtersobel->midtexture); glGenTextures (1, &filtersobel->midtexture);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, filtersobel->midtexture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, filtersobel->midtexture);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
filter->width, filter->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); filter->width, filter->height, 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_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_TO_EDGE); glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
} }
static void static void
gst_gl_filtersobel_reset_resources (GstGLFilter *filter) gst_gl_filtersobel_reset_resources (GstGLFilter * filter)
{ {
GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (filter); GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (filter);
@ -140,23 +144,24 @@ gst_gl_filtersobel_class_init (GstGLFilterSobelClass * klass)
gobject_class->get_property = gst_gl_filtersobel_get_property; gobject_class->get_property = gst_gl_filtersobel_get_property;
GST_GL_FILTER_CLASS (klass)->filter = gst_gl_filtersobel_filter; GST_GL_FILTER_CLASS (klass)->filter = gst_gl_filtersobel_filter;
GST_GL_FILTER_CLASS (klass)->display_init_cb = gst_gl_filtersobel_init_resources; GST_GL_FILTER_CLASS (klass)->display_init_cb =
GST_GL_FILTER_CLASS (klass)->display_reset_cb = gst_gl_filtersobel_reset_resources; gst_gl_filtersobel_init_resources;
GST_GL_FILTER_CLASS (klass)->display_reset_cb =
gst_gl_filtersobel_reset_resources;
GST_GL_FILTER_CLASS (klass)->onInitFBO = gst_gl_filtersobel_init_shader; GST_GL_FILTER_CLASS (klass)->onInitFBO = gst_gl_filtersobel_init_shader;
GST_GL_FILTER_CLASS (klass)->onReset = gst_gl_filter_filtersobel_reset; GST_GL_FILTER_CLASS (klass)->onReset = gst_gl_filter_filtersobel_reset;
g_object_class_install_property ( g_object_class_install_property (gobject_class,
gobject_class, PROP_INVERT,
PROP_INVERT, g_param_spec_boolean ("invert",
g_param_spec_boolean ("invert", "Invert the colors",
"Invert the colors", "Invert colors to get dark edges on bright background",
"Invert colors to get dark edges on bright background", FALSE, G_PARAM_READWRITE));
FALSE,
G_PARAM_READWRITE));
} }
static void static void
gst_gl_filtersobel_init (GstGLFilterSobel * filtersobel, GstGLFilterSobelClass * klass) gst_gl_filtersobel_init (GstGLFilterSobel * filtersobel,
GstGLFilterSobelClass * klass)
{ {
filtersobel->shader0 = NULL; filtersobel->shader0 = NULL;
filtersobel->midtexture = 0; filtersobel->midtexture = 0;
@ -164,9 +169,9 @@ gst_gl_filtersobel_init (GstGLFilterSobel * filtersobel, GstGLFilterSobelClass *
} }
static void static void
gst_gl_filter_filtersobel_reset (GstGLFilter* filter) gst_gl_filter_filtersobel_reset (GstGLFilter * filter)
{ {
GstGLFilterSobel* filtersobel = GST_GL_FILTERSOBEL(filter); GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (filter);
//blocking call, wait the opengl thread has destroyed the shader //blocking call, wait the opengl thread has destroyed the shader
gst_gl_display_del_shader (filter->display, filtersobel->shader0); gst_gl_display_del_shader (filter->display, filtersobel->shader0);
@ -179,12 +184,12 @@ gst_gl_filtersobel_set_property (GObject * object, guint prop_id,
GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (object); GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (object);
switch (prop_id) { switch (prop_id) {
case PROP_INVERT: case PROP_INVERT:
filtersobel->invert = g_value_get_boolean (value); filtersobel->invert = g_value_get_boolean (value);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
} }
@ -195,22 +200,23 @@ gst_gl_filtersobel_get_property (GObject * object, guint prop_id,
GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (object); GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (object);
switch (prop_id) { switch (prop_id) {
case PROP_INVERT: case PROP_INVERT:
g_value_set_boolean (value, filtersobel->invert); g_value_set_boolean (value, filtersobel->invert);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
} }
static void static void
gst_gl_filtersobel_init_shader (GstGLFilter* filter) gst_gl_filtersobel_init_shader (GstGLFilter * filter)
{ {
GstGLFilterSobel* filtersobel = GST_GL_FILTERSOBEL (filter); GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (filter);
//blocking call, wait the opengl thread has compiled the shader //blocking call, wait the opengl thread has compiled the shader
gst_gl_display_gen_shader (filter->display, 0, sobel_fragment_source, &filtersobel->shader0); gst_gl_display_gen_shader (filter->display, 0, sobel_fragment_source,
&filtersobel->shader0);
} }
static void static void
@ -226,11 +232,11 @@ gst_gl_filtersobel_draw_texture (GstGLFilterSobel * filtersobel, GLuint tex)
glTexCoord2f (0.0, 0.0); glTexCoord2f (0.0, 0.0);
glVertex2f (-1.0, -1.0); glVertex2f (-1.0, -1.0);
glTexCoord2f ((gfloat)filter->width, 0.0); glTexCoord2f ((gfloat) filter->width, 0.0);
glVertex2f (1.0, -1.0); glVertex2f (1.0, -1.0);
glTexCoord2f ((gfloat)filter->width, (gfloat)filter->height); glTexCoord2f ((gfloat) filter->width, (gfloat) filter->height);
glVertex2f (1.0, 1.0); glVertex2f (1.0, 1.0);
glTexCoord2f (0.0, (gfloat)filter->height); glTexCoord2f (0.0, (gfloat) filter->height);
glVertex2f (-1.0, 1.0); glVertex2f (-1.0, 1.0);
glEnd (); glEnd ();
@ -253,33 +259,34 @@ change_view (GstGLDisplay *display, gpointer data)
}*/ }*/
static gboolean static gboolean
gst_gl_filtersobel_filter (GstGLFilter* filter, GstGLBuffer* inbuf, gst_gl_filtersobel_filter (GstGLFilter * filter, GstGLBuffer * inbuf,
GstGLBuffer* outbuf) GstGLBuffer * outbuf)
{ {
GstGLFilterSobel* filtersobel = GST_GL_FILTERSOBEL(filter); GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (filter);
// gst_gl_display_thread_add (filter->display, change_view, filtersobel); // gst_gl_display_thread_add (filter->display, change_view, filtersobel);
gst_gl_filter_render_to_target (filter, inbuf->texture, outbuf->texture, gst_gl_filter_render_to_target (filter, inbuf->texture, outbuf->texture,
gst_gl_filtersobel_callback, filtersobel); gst_gl_filtersobel_callback, filtersobel);
return TRUE; return TRUE;
} }
static void static void
gst_gl_filtersobel_callback (gint width, gint height, guint texture, gpointer stuff) gst_gl_filtersobel_callback (gint width, gint height, guint texture,
gpointer stuff)
{ {
GstGLFilterSobel* filtersobel = GST_GL_FILTERSOBEL (stuff); GstGLFilterSobel *filtersobel = GST_GL_FILTERSOBEL (stuff);
gfloat hkern[9] = { gfloat hkern[9] = {
1.0, 0.0, -1.0, 1.0, 0.0, -1.0,
2.0, 0.0, -2.0, 2.0, 0.0, -2.0,
1.0, 0.0, -1.0 1.0, 0.0, -1.0
}; };
gfloat vkern[9] = { gfloat vkern[9] = {
1.0, 2.0, 1.0, 1.0, 2.0, 1.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
-1.0, -2.0, -1.0 -1.0, -2.0, -1.0
}; };
@ -298,7 +305,8 @@ gst_gl_filtersobel_callback (gint width, gint height, guint texture, gpointer st
gst_gl_shader_set_uniform_1fv (filtersobel->shader0, "hkern", 9, hkern); gst_gl_shader_set_uniform_1fv (filtersobel->shader0, "hkern", 9, hkern);
gst_gl_shader_set_uniform_1fv (filtersobel->shader0, "vkern", 9, vkern); gst_gl_shader_set_uniform_1fv (filtersobel->shader0, "vkern", 9, vkern);
gst_gl_shader_set_uniform_1i (filtersobel->shader0, "invert", filtersobel->invert); gst_gl_shader_set_uniform_1i (filtersobel->shader0, "invert",
filtersobel->invert);
gst_gl_filtersobel_draw_texture (filtersobel, texture); gst_gl_filtersobel_draw_texture (filtersobel, texture);
} }

View file

@ -119,10 +119,10 @@ static void gst_glimage_sink_implements_init (GstImplementsInterfaceClass *
klass); klass);
static const GstElementDetails gst_glimage_sink_details = static const GstElementDetails gst_glimage_sink_details =
GST_ELEMENT_DETAILS ("OpenGL video sink", GST_ELEMENT_DETAILS ("OpenGL video sink",
"Sink/Video", "Sink/Video",
"A videosink based on OpenGL", "A videosink based on OpenGL",
"Julien Isorce <julien.isorce@gmail.com>"); "Julien Isorce <julien.isorce@gmail.com>");
static GstStaticPadTemplate gst_glimage_sink_template = static GstStaticPadTemplate gst_glimage_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink", GST_STATIC_PAD_TEMPLATE ("sink",
@ -139,10 +139,10 @@ static GstStaticPadTemplate gst_glimage_sink_template =
enum enum
{ {
ARG_0, ARG_0,
ARG_DISPLAY, ARG_DISPLAY,
PROP_CLIENT_RESHAPE_CALLBACK, PROP_CLIENT_RESHAPE_CALLBACK,
PROP_CLIENT_DRAW_CALLBACK PROP_CLIENT_DRAW_CALLBACK
}; };
GST_BOILERPLATE_FULL (GstGLImageSink, gst_glimage_sink, GstVideoSink, GST_BOILERPLATE_FULL (GstGLImageSink, gst_glimage_sink, GstVideoSink,
@ -158,7 +158,7 @@ gst_glimage_sink_init_interfaces (GType type)
NULL NULL
}; };
static const GInterfaceInfo xoverlay_info = { static const GInterfaceInfo xoverlay_info = {
(GInterfaceInitFunc) gst_glimage_sink_xoverlay_init, (GInterfaceInitFunc) gst_glimage_sink_xoverlay_init,
NULL, NULL,
NULL, NULL,
@ -170,7 +170,7 @@ gst_glimage_sink_init_interfaces (GType type)
g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &xoverlay_info); g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &xoverlay_info);
GST_DEBUG_CATEGORY_INIT (gst_debug_glimage_sink, "glimagesink", 0, GST_DEBUG_CATEGORY_INIT (gst_debug_glimage_sink, "glimagesink", 0,
"OpenGL Video Sink"); "OpenGL Video Sink");
} }
static void static void
@ -185,127 +185,125 @@ gst_glimage_sink_base_init (gpointer g_class)
} }
static void static void
gst_glimage_sink_class_init (GstGLImageSinkClass* klass) gst_glimage_sink_class_init (GstGLImageSinkClass * klass)
{ {
GObjectClass *gobject_class; GObjectClass *gobject_class;
GstElementClass *gstelement_class; GstElementClass *gstelement_class;
GstBaseSinkClass *gstbasesink_class; GstBaseSinkClass *gstbasesink_class;
gobject_class = (GObjectClass *) klass; gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass; gstelement_class = (GstElementClass *) klass;
gstbasesink_class = (GstBaseSinkClass *) klass; gstbasesink_class = (GstBaseSinkClass *) klass;
gobject_class->set_property = gst_glimage_sink_set_property; gobject_class->set_property = gst_glimage_sink_set_property;
gobject_class->get_property = gst_glimage_sink_get_property; gobject_class->get_property = gst_glimage_sink_get_property;
g_object_class_install_property (gobject_class, ARG_DISPLAY, g_object_class_install_property (gobject_class, ARG_DISPLAY,
g_param_spec_string ("display", "Display", "Display name", g_param_spec_string ("display", "Display", "Display name",
NULL, G_PARAM_READWRITE)); NULL, G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, PROP_CLIENT_RESHAPE_CALLBACK, g_object_class_install_property (gobject_class, PROP_CLIENT_RESHAPE_CALLBACK,
g_param_spec_pointer ("client_reshape_callback", "Client reshape callback", g_param_spec_pointer ("client_reshape_callback",
"Client reshape callback",
"Define a custom reshape callback in a client code", "Define a custom reshape callback in a client code",
G_PARAM_WRITABLE)); G_PARAM_WRITABLE));
g_object_class_install_property (gobject_class, PROP_CLIENT_DRAW_CALLBACK, g_object_class_install_property (gobject_class, PROP_CLIENT_DRAW_CALLBACK,
g_param_spec_pointer ("client_draw_callback", "Client draw callback", g_param_spec_pointer ("client_draw_callback", "Client draw callback",
"Define a custom draw callback in a client code", "Define a custom draw callback in a client code", G_PARAM_WRITABLE));
G_PARAM_WRITABLE));
gobject_class->finalize = gst_glimage_sink_finalize; gobject_class->finalize = gst_glimage_sink_finalize;
gstelement_class->change_state = gst_glimage_sink_change_state; gstelement_class->change_state = gst_glimage_sink_change_state;
gstbasesink_class->set_caps = gst_glimage_sink_set_caps; gstbasesink_class->set_caps = gst_glimage_sink_set_caps;
gstbasesink_class->get_times = gst_glimage_sink_get_times; gstbasesink_class->get_times = gst_glimage_sink_get_times;
gstbasesink_class->preroll = gst_glimage_sink_render; gstbasesink_class->preroll = gst_glimage_sink_render;
gstbasesink_class->render = gst_glimage_sink_render; gstbasesink_class->render = gst_glimage_sink_render;
gstbasesink_class->start = gst_glimage_sink_start; gstbasesink_class->start = gst_glimage_sink_start;
gstbasesink_class->stop = gst_glimage_sink_stop; gstbasesink_class->stop = gst_glimage_sink_stop;
} }
static void static void
gst_glimage_sink_init (GstGLImageSink* glimage_sink, gst_glimage_sink_init (GstGLImageSink * glimage_sink,
GstGLImageSinkClass* glimage_sink_class) GstGLImageSinkClass * glimage_sink_class)
{ {
glimage_sink->display_name = NULL; glimage_sink->display_name = NULL;
glimage_sink->window_id = 0; glimage_sink->window_id = 0;
glimage_sink->display = NULL; glimage_sink->display = NULL;
glimage_sink->stored_buffer = NULL; glimage_sink->stored_buffer = NULL;
glimage_sink->clientReshapeCallback = NULL; glimage_sink->clientReshapeCallback = NULL;
glimage_sink->clientDrawCallback = NULL; glimage_sink->clientDrawCallback = NULL;
} }
static void static void
gst_glimage_sink_set_property (GObject* object, guint prop_id, gst_glimage_sink_set_property (GObject * object, guint prop_id,
const GValue* value, GParamSpec* pspec) const GValue * value, GParamSpec * pspec)
{ {
GstGLImageSink *glimage_sink; GstGLImageSink *glimage_sink;
g_return_if_fail (GST_IS_GLIMAGE_SINK (object)); g_return_if_fail (GST_IS_GLIMAGE_SINK (object));
glimage_sink = GST_GLIMAGE_SINK (object); glimage_sink = GST_GLIMAGE_SINK (object);
switch (prop_id) switch (prop_id) {
case ARG_DISPLAY:
{ {
case ARG_DISPLAY: g_free (glimage_sink->display_name);
{ glimage_sink->display_name = g_strdup (g_value_get_string (value));
g_free (glimage_sink->display_name); break;
glimage_sink->display_name = g_strdup (g_value_get_string (value));
break;
}
case PROP_CLIENT_RESHAPE_CALLBACK:
{
glimage_sink->clientReshapeCallback = g_value_get_pointer (value);
break;
}
case PROP_CLIENT_DRAW_CALLBACK:
{
glimage_sink->clientDrawCallback = g_value_get_pointer (value);
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
} }
} case PROP_CLIENT_RESHAPE_CALLBACK:
static void
gst_glimage_sink_finalize (GObject* object)
{
GstGLImageSink* glimage_sink;
g_return_if_fail (GST_IS_GLIMAGE_SINK (object));
glimage_sink = GST_GLIMAGE_SINK (object);
if (glimage_sink->caps)
gst_caps_unref (glimage_sink->caps);
g_free (glimage_sink->display_name);
GST_DEBUG ("finalized");
}
static void
gst_glimage_sink_get_property (GObject* object, guint prop_id,
GValue* value, GParamSpec* pspec)
{
GstGLImageSink *glimage_sink;
g_return_if_fail (GST_IS_GLIMAGE_SINK (object));
glimage_sink = GST_GLIMAGE_SINK (object);
switch (prop_id)
{ {
case ARG_DISPLAY: glimage_sink->clientReshapeCallback = g_value_get_pointer (value);
g_value_set_string (value, glimage_sink->display_name); break;
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
} }
case PROP_CLIENT_DRAW_CALLBACK:
{
glimage_sink->clientDrawCallback = g_value_get_pointer (value);
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_glimage_sink_finalize (GObject * object)
{
GstGLImageSink *glimage_sink;
g_return_if_fail (GST_IS_GLIMAGE_SINK (object));
glimage_sink = GST_GLIMAGE_SINK (object);
if (glimage_sink->caps)
gst_caps_unref (glimage_sink->caps);
g_free (glimage_sink->display_name);
GST_DEBUG ("finalized");
}
static void
gst_glimage_sink_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstGLImageSink *glimage_sink;
g_return_if_fail (GST_IS_GLIMAGE_SINK (object));
glimage_sink = GST_GLIMAGE_SINK (object);
switch (prop_id) {
case ARG_DISPLAY:
g_value_set_string (value, glimage_sink->display_name);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
} }
/* /*
@ -313,49 +311,47 @@ gst_glimage_sink_get_property (GObject* object, guint prop_id,
*/ */
static GstStateChangeReturn static GstStateChangeReturn
gst_glimage_sink_change_state (GstElement* element, GstStateChange transition) gst_glimage_sink_change_state (GstElement * element, GstStateChange transition)
{ {
GstGLImageSink* glimage_sink; GstGLImageSink *glimage_sink;
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
GST_DEBUG ("change state"); GST_DEBUG ("change state");
glimage_sink = GST_GLIMAGE_SINK (element); glimage_sink = GST_GLIMAGE_SINK (element);
switch (transition) switch (transition) {
{ case GST_STATE_CHANGE_NULL_TO_READY:
case GST_STATE_CHANGE_NULL_TO_READY: break;
break; case GST_STATE_CHANGE_READY_TO_PAUSED:
case GST_STATE_CHANGE_READY_TO_PAUSED: break;
break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
case GST_STATE_CHANGE_PAUSED_TO_PLAYING: break;
break; default:
default: break;
break; }
}
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
if (ret == GST_STATE_CHANGE_FAILURE)
return ret;
switch (transition)
{
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
gst_glimage_sink_stop (GST_BASE_SINK (glimage_sink));
glimage_sink->fps_n = 0;
glimage_sink->fps_d = 1;
GST_VIDEO_SINK_WIDTH (glimage_sink) = 0;
GST_VIDEO_SINK_HEIGHT (glimage_sink) = 0;
break;
case GST_STATE_CHANGE_READY_TO_NULL:
break;
default:
break;
}
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
if (ret == GST_STATE_CHANGE_FAILURE)
return ret; return ret;
switch (transition) {
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
gst_glimage_sink_stop (GST_BASE_SINK (glimage_sink));
glimage_sink->fps_n = 0;
glimage_sink->fps_d = 1;
GST_VIDEO_SINK_WIDTH (glimage_sink) = 0;
GST_VIDEO_SINK_HEIGHT (glimage_sink) = 0;
break;
case GST_STATE_CHANGE_READY_TO_NULL:
break;
default:
break;
}
return ret;
} }
/* /*
@ -363,248 +359,239 @@ gst_glimage_sink_change_state (GstElement* element, GstStateChange transition)
*/ */
static gboolean static gboolean
gst_glimage_sink_start (GstBaseSink* bsink) gst_glimage_sink_start (GstBaseSink * bsink)
{ {
//GstGLImageSink* glimage_sink = GST_GLIMAGE_SINK (bsink); //GstGLImageSink* glimage_sink = GST_GLIMAGE_SINK (bsink);
GST_DEBUG ("start"); GST_DEBUG ("start");
return TRUE; return TRUE;
} }
static gboolean static gboolean
gst_glimage_sink_stop (GstBaseSink* bsink) gst_glimage_sink_stop (GstBaseSink * bsink)
{ {
GstGLImageSink* glimage_sink; GstGLImageSink *glimage_sink;
GST_DEBUG ("stop"); GST_DEBUG ("stop");
glimage_sink = GST_GLIMAGE_SINK (bsink); glimage_sink = GST_GLIMAGE_SINK (bsink);
if (glimage_sink->stored_buffer) if (glimage_sink->stored_buffer) {
{ gst_buffer_unref (glimage_sink->stored_buffer);
gst_buffer_unref (glimage_sink->stored_buffer); glimage_sink->stored_buffer = NULL;
glimage_sink->stored_buffer = NULL; }
} if (glimage_sink->display) {
if (glimage_sink->display) g_object_unref (glimage_sink->display);
{ glimage_sink->display = NULL;
g_object_unref (glimage_sink->display); }
glimage_sink->display = NULL;
}
return TRUE; return TRUE;
} }
static void static void
gst_glimage_sink_get_times (GstBaseSink* bsink, GstBuffer* buf, gst_glimage_sink_get_times (GstBaseSink * bsink, GstBuffer * buf,
GstClockTime* start, GstClockTime* end) GstClockTime * start, GstClockTime * end)
{ {
GstGLImageSink* glimagesink; GstGLImageSink *glimagesink;
glimagesink = GST_GLIMAGE_SINK (bsink); glimagesink = GST_GLIMAGE_SINK (bsink);
if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
{ *start = GST_BUFFER_TIMESTAMP (buf);
*start = GST_BUFFER_TIMESTAMP (buf); if (GST_BUFFER_DURATION_IS_VALID (buf))
if (GST_BUFFER_DURATION_IS_VALID (buf)) *end = *start + GST_BUFFER_DURATION (buf);
*end = *start + GST_BUFFER_DURATION (buf); else {
else if (glimagesink->fps_n > 0) {
{ *end = *start +
if (glimagesink->fps_n > 0) { gst_util_uint64_scale_int (GST_SECOND, glimagesink->fps_d,
*end = *start + glimagesink->fps_n);
gst_util_uint64_scale_int (GST_SECOND, glimagesink->fps_d, }
glimagesink->fps_n);
}
}
} }
}
} }
static gboolean static gboolean
gst_glimage_sink_set_caps (GstBaseSink* bsink, GstCaps* caps) gst_glimage_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
{ {
GstGLImageSink* glimage_sink; GstGLImageSink *glimage_sink;
gint width; gint width;
gint height; gint height;
gboolean ok; gboolean ok;
gint fps_n, fps_d; gint fps_n, fps_d;
gint par_n, par_d; gint par_n, par_d;
GstVideoFormat format; GstVideoFormat format;
GstStructure *structure; GstStructure *structure;
gboolean is_gl; gboolean is_gl;
GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps); GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps);
glimage_sink = GST_GLIMAGE_SINK (bsink); glimage_sink = GST_GLIMAGE_SINK (bsink);
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")) {
is_gl = TRUE; is_gl = TRUE;
format = GST_VIDEO_FORMAT_UNKNOWN; format = GST_VIDEO_FORMAT_UNKNOWN;
ok = gst_structure_get_int (structure, "width", &width); ok = gst_structure_get_int (structure, "width", &width);
ok &= gst_structure_get_int (structure, "height", &height); ok &= gst_structure_get_int (structure, "height", &height);
} else { } else {
is_gl = FALSE; is_gl = FALSE;
ok = gst_video_format_parse_caps (caps, &format, &width, &height); ok = gst_video_format_parse_caps (caps, &format, &width, &height);
} }
ok &= gst_video_parse_caps_framerate (caps, &fps_n, &fps_d); ok &= gst_video_parse_caps_framerate (caps, &fps_n, &fps_d);
ok &= gst_video_parse_caps_pixel_aspect_ratio (caps, &par_n, &par_d); ok &= gst_video_parse_caps_pixel_aspect_ratio (caps, &par_n, &par_d);
if (!ok) if (!ok)
return FALSE; return FALSE;
GST_VIDEO_SINK_WIDTH (glimage_sink) = width; GST_VIDEO_SINK_WIDTH (glimage_sink) = width;
GST_VIDEO_SINK_HEIGHT (glimage_sink) = height; GST_VIDEO_SINK_HEIGHT (glimage_sink) = height;
glimage_sink->is_gl = is_gl; glimage_sink->is_gl = is_gl;
glimage_sink->format = format; glimage_sink->format = format;
glimage_sink->width = width; glimage_sink->width = width;
glimage_sink->height = height; glimage_sink->height = height;
glimage_sink->fps_n = fps_n; glimage_sink->fps_n = fps_n;
glimage_sink->fps_d = fps_d; glimage_sink->fps_d = fps_d;
glimage_sink->par_n = par_n; glimage_sink->par_n = par_n;
glimage_sink->par_d = par_d; glimage_sink->par_d = par_d;
if (!glimage_sink->window_id) if (!glimage_sink->window_id)
gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (glimage_sink)); gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (glimage_sink));
return TRUE; return TRUE;
} }
static GstFlowReturn static GstFlowReturn
gst_glimage_sink_render (GstBaseSink* bsink, GstBuffer* buf) gst_glimage_sink_render (GstBaseSink * bsink, GstBuffer * buf)
{ {
GstGLImageSink* glimage_sink = NULL; GstGLImageSink *glimage_sink = NULL;
GstGLBuffer* gl_buffer = NULL; GstGLBuffer *gl_buffer = NULL;
glimage_sink = GST_GLIMAGE_SINK (bsink); glimage_sink = GST_GLIMAGE_SINK (bsink);
GST_INFO ("buffer size: %d", GST_BUFFER_SIZE (buf)); GST_INFO ("buffer size: %d", GST_BUFFER_SIZE (buf));
//is gl //is gl
if (glimage_sink->is_gl) if (glimage_sink->is_gl) {
{ //increment gl buffer ref before storage
//increment gl buffer ref before storage gl_buffer = GST_GL_BUFFER (gst_buffer_ref (buf));
gl_buffer = GST_GL_BUFFER (gst_buffer_ref (buf));
//if glimagesink has not the display yet //if glimagesink has not the display yet
if (glimage_sink->display == NULL) if (glimage_sink->display == NULL) {
{ glimage_sink->display = g_object_ref (gl_buffer->display);
glimage_sink->display = g_object_ref (gl_buffer->display);
if (glimage_sink->window_id) if (glimage_sink->window_id)
gst_gl_display_set_window_id (glimage_sink->display, glimage_sink->window_id); gst_gl_display_set_window_id (glimage_sink->display,
glimage_sink->window_id);
gst_gl_display_set_client_reshape_callback (glimage_sink->display, gst_gl_display_set_client_reshape_callback (glimage_sink->display,
glimage_sink->clientReshapeCallback); glimage_sink->clientReshapeCallback);
gst_gl_display_set_client_draw_callback (glimage_sink->display, gst_gl_display_set_client_draw_callback (glimage_sink->display,
glimage_sink->clientDrawCallback); glimage_sink->clientDrawCallback);
}
} }
//is not gl }
else //is not gl
{ else {
//if glimagesink has not the display yet //if glimagesink has not the display yet
if (glimage_sink->display == NULL) if (glimage_sink->display == NULL) {
{ //create a display
//create a display glimage_sink->display = gst_gl_display_new ();
glimage_sink->display = gst_gl_display_new ();
//init opengl context //init opengl context
gst_gl_display_create_context (glimage_sink->display, gst_gl_display_create_context (glimage_sink->display,
glimage_sink->width, glimage_sink->height); glimage_sink->width, glimage_sink->height);
if (glimage_sink->window_id) if (glimage_sink->window_id)
gst_gl_display_set_window_id (glimage_sink->display, glimage_sink->window_id); gst_gl_display_set_window_id (glimage_sink->display,
glimage_sink->window_id);
//init colorspace conversion if needed //init colorspace conversion if needed
gst_gl_display_init_upload (glimage_sink->display, glimage_sink->format, gst_gl_display_init_upload (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);
gst_gl_display_set_client_reshape_callback (glimage_sink->display, gst_gl_display_set_client_reshape_callback (glimage_sink->display,
glimage_sink->clientReshapeCallback); glimage_sink->clientReshapeCallback);
gst_gl_display_set_client_draw_callback (glimage_sink->display, gst_gl_display_set_client_draw_callback (glimage_sink->display,
glimage_sink->clientDrawCallback); glimage_sink->clientDrawCallback);
}
//blocking call
gl_buffer = gst_gl_buffer_new (glimage_sink->display,
glimage_sink->width, glimage_sink->height);
//blocking call
gst_gl_display_do_upload(glimage_sink->display, gl_buffer->texture,
glimage_sink->width, glimage_sink->height, GST_BUFFER_DATA (buf));
//gl_buffer is created in this block, so the gl buffer is already referenced
} }
//blocking call
gl_buffer = gst_gl_buffer_new (glimage_sink->display,
glimage_sink->width, glimage_sink->height);
//the buffer is cleared when an other comes in //blocking call
if (glimage_sink->stored_buffer) gst_gl_display_do_upload (glimage_sink->display, gl_buffer->texture,
{ glimage_sink->width, glimage_sink->height, GST_BUFFER_DATA (buf));
gst_buffer_unref (glimage_sink->stored_buffer);
glimage_sink->stored_buffer = NULL;
}
//store current buffer //gl_buffer is created in this block, so the gl buffer is already referenced
glimage_sink->stored_buffer = gl_buffer; }
//redisplay opengl scene //the buffer is cleared when an other comes in
if (gl_buffer->texture && if (glimage_sink->stored_buffer) {
gst_gl_display_redisplay (glimage_sink->display, gst_buffer_unref (glimage_sink->stored_buffer);
gl_buffer->texture, gl_buffer->width, gl_buffer->height)) glimage_sink->stored_buffer = NULL;
return GST_FLOW_OK; }
else //store current buffer
return GST_FLOW_UNEXPECTED; glimage_sink->stored_buffer = gl_buffer;
//redisplay opengl scene
if (gl_buffer->texture &&
gst_gl_display_redisplay (glimage_sink->display,
gl_buffer->texture, gl_buffer->width, gl_buffer->height))
return GST_FLOW_OK;
else
return GST_FLOW_UNEXPECTED;
} }
static void static void
gst_glimage_sink_xoverlay_init (GstXOverlayClass* iface) gst_glimage_sink_xoverlay_init (GstXOverlayClass * iface)
{ {
iface->set_xwindow_id = gst_glimage_sink_set_xwindow_id; iface->set_xwindow_id = gst_glimage_sink_set_xwindow_id;
iface->expose = gst_glimage_sink_expose; iface->expose = gst_glimage_sink_expose;
} }
static void static void
gst_glimage_sink_set_xwindow_id (GstXOverlay* overlay, gulong window_id) gst_glimage_sink_set_xwindow_id (GstXOverlay * overlay, gulong window_id)
{ {
GstGLImageSink* glimage_sink = GST_GLIMAGE_SINK (overlay); GstGLImageSink *glimage_sink = GST_GLIMAGE_SINK (overlay);
g_return_if_fail (GST_IS_GLIMAGE_SINK (overlay)); g_return_if_fail (GST_IS_GLIMAGE_SINK (overlay));
GST_DEBUG ("set_xwindow_id %ld", window_id); GST_DEBUG ("set_xwindow_id %ld", window_id);
if (glimage_sink->window_id == window_id) if (glimage_sink->window_id == window_id)
return; return;
if (window_id) if (window_id)
glimage_sink->window_id = window_id; glimage_sink->window_id = window_id;
} }
static void static void
gst_glimage_sink_expose (GstXOverlay* overlay) gst_glimage_sink_expose (GstXOverlay * overlay)
{ {
GstGLImageSink* glimage_sink = GST_GLIMAGE_SINK (overlay); GstGLImageSink *glimage_sink = GST_GLIMAGE_SINK (overlay);
//redisplay opengl scene //redisplay opengl scene
if (glimage_sink->display && glimage_sink->window_id) if (glimage_sink->display && glimage_sink->window_id)
gst_gl_display_redisplay (glimage_sink->display, 0, 0, 0); gst_gl_display_redisplay (glimage_sink->display, 0, 0, 0);
} }
static gboolean static gboolean
gst_glimage_sink_interface_supported (GstImplementsInterface* iface, gst_glimage_sink_interface_supported (GstImplementsInterface * iface,
GType type) GType type)
{ {
return TRUE; return TRUE;
} }
static void static void
gst_glimage_sink_implements_init (GstImplementsInterfaceClass* klass) gst_glimage_sink_implements_init (GstImplementsInterfaceClass * klass)
{ {
klass->supported = gst_glimage_sink_interface_supported; klass->supported = gst_glimage_sink_interface_supported;
} }

View file

@ -76,26 +76,26 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
GST_DEBUG_CATEGORY_INIT (gst_gl_overlay_debug, "gloverlay", 0, "gloverlay element"); GST_DEBUG_CATEGORY_INIT (gst_gl_overlay_debug, "gloverlay", 0, "gloverlay element");
GST_BOILERPLATE_FULL (GstGLOverlay, gst_gl_overlay, GstGLFilter, GST_BOILERPLATE_FULL (GstGLOverlay, gst_gl_overlay, GstGLFilter,
GST_TYPE_GL_FILTER, DEBUG_INIT); GST_TYPE_GL_FILTER, DEBUG_INIT);
static void gst_gl_overlay_set_property (GObject * object, guint prop_id, static void gst_gl_overlay_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec); const GValue * value, GParamSpec * pspec);
static void gst_gl_overlay_get_property (GObject * object, guint prop_id, static void gst_gl_overlay_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
static void gst_gl_overlay_init_resources (GstGLFilter* filter); static void gst_gl_overlay_init_resources (GstGLFilter * filter);
static void gst_gl_overlay_reset_resources (GstGLFilter* filter); static void gst_gl_overlay_reset_resources (GstGLFilter * filter);
static gboolean gst_gl_overlay_filter (GstGLFilter * filter, static gboolean gst_gl_overlay_filter (GstGLFilter * filter,
GstGLBuffer * inbuf, GstGLBuffer * outbuf); GstGLBuffer * inbuf, GstGLBuffer * outbuf);
static gboolean gst_gl_overlay_loader (GstGLFilter* filter); static gboolean gst_gl_overlay_loader (GstGLFilter * filter);
static const GstElementDetails element_details = GST_ELEMENT_DETAILS ( static const GstElementDetails element_details =
"Gstreamer OpenGL Overlay", GST_ELEMENT_DETAILS ("Gstreamer OpenGL Overlay",
"Filter/Effect", "Filter/Effect",
"Overlay GL video texture with a PNG image", "Overlay GL video texture with a PNG image",
"Filippo Argiolas <filippo.argiolas@gmail.com>"); "Filippo Argiolas <filippo.argiolas@gmail.com>");
enum enum
{ {
@ -112,17 +112,17 @@ enum
/* init resources that need a gl context */ /* init resources that need a gl context */
static void static void
gst_gl_overlay_init_gl_resources (GstGLFilter *filter) gst_gl_overlay_init_gl_resources (GstGLFilter * filter)
{ {
// GstGLOverlay *overlay = GST_GL_OVERLAY (filter); // GstGLOverlay *overlay = GST_GL_OVERLAY (filter);
} }
/* free resources that need a gl context */ /* free resources that need a gl context */
static void static void
gst_gl_overlay_reset_gl_resources (GstGLFilter *filter) gst_gl_overlay_reset_gl_resources (GstGLFilter * filter)
{ {
GstGLOverlay *overlay = GST_GL_OVERLAY (filter); GstGLOverlay *overlay = GST_GL_OVERLAY (filter);
glDeleteTextures (1, &overlay->pbuftexture); glDeleteTextures (1, &overlay->pbuftexture);
} }
@ -144,25 +144,26 @@ gst_gl_overlay_class_init (GstGLOverlayClass * klass)
gobject_class->get_property = gst_gl_overlay_get_property; gobject_class->get_property = gst_gl_overlay_get_property;
GST_GL_FILTER_CLASS (klass)->filter = gst_gl_overlay_filter; GST_GL_FILTER_CLASS (klass)->filter = gst_gl_overlay_filter;
GST_GL_FILTER_CLASS (klass)->display_init_cb = gst_gl_overlay_init_gl_resources; GST_GL_FILTER_CLASS (klass)->display_init_cb =
GST_GL_FILTER_CLASS (klass)->display_reset_cb = gst_gl_overlay_reset_gl_resources; gst_gl_overlay_init_gl_resources;
GST_GL_FILTER_CLASS (klass)->display_reset_cb =
gst_gl_overlay_reset_gl_resources;
GST_GL_FILTER_CLASS (klass)->onStart = gst_gl_overlay_init_resources; GST_GL_FILTER_CLASS (klass)->onStart = gst_gl_overlay_init_resources;
GST_GL_FILTER_CLASS (klass)->onStop = gst_gl_overlay_reset_resources; GST_GL_FILTER_CLASS (klass)->onStop = gst_gl_overlay_reset_resources;
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_LOCATION, PROP_LOCATION,
g_param_spec_string ("location", g_param_spec_string ("location",
"Location of the image", "Location of the image",
"Location of the image", "Location of the image", NULL, G_PARAM_READWRITE));
NULL, G_PARAM_READWRITE));
/* /*
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_STRETCH, PROP_STRETCH,
g_param_spec_boolean ("stretch", g_param_spec_boolean ("stretch",
"Stretch the image to texture size", "Stretch the image to texture size",
"Stretch the image to fit video texture size", "Stretch the image to fit video texture size",
TRUE, G_PARAM_READWRITE)); TRUE, G_PARAM_READWRITE));
*/ */
} }
void void
@ -190,15 +191,16 @@ gst_gl_overlay_draw_texture (GstGLOverlay * overlay, GLuint tex)
glEnd (); glEnd ();
if (overlay->pbuftexture == 0) return; if (overlay->pbuftexture == 0)
return;
// if (overlay->stretch) { // if (overlay->stretch) {
width = (gfloat) overlay->width; width = (gfloat) overlay->width;
height = (gfloat) overlay->height; height = (gfloat) overlay->height;
// } // }
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND); glEnable (GL_BLEND);
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, overlay->pbuftexture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, overlay->pbuftexture);
@ -221,8 +223,7 @@ gst_gl_overlay_draw_texture (GstGLOverlay * overlay, GLuint tex)
} }
static void static void
gst_gl_overlay_init (GstGLOverlay * overlay, gst_gl_overlay_init (GstGLOverlay * overlay, GstGLOverlayClass * klass)
GstGLOverlayClass * klass)
{ {
overlay->location = NULL; overlay->location = NULL;
overlay->pixbuf = NULL; overlay->pixbuf = NULL;
@ -235,7 +236,7 @@ gst_gl_overlay_init (GstGLOverlay * overlay,
} }
static void static void
gst_gl_overlay_reset_resources (GstGLFilter* filter) gst_gl_overlay_reset_resources (GstGLFilter * filter)
{ {
// GstGLOverlay* overlay = GST_GL_OVERLAY(filter); // GstGLOverlay* overlay = GST_GL_OVERLAY(filter);
} }
@ -244,21 +245,22 @@ static void
gst_gl_overlay_set_property (GObject * object, guint prop_id, gst_gl_overlay_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec) const GValue * value, GParamSpec * pspec)
{ {
GstGLOverlay *overlay = GST_GL_OVERLAY (object); GstGLOverlay *overlay = GST_GL_OVERLAY (object);
switch (prop_id) { switch (prop_id) {
case PROP_LOCATION: case PROP_LOCATION:
if (overlay->location != NULL) g_free (overlay->location); if (overlay->location != NULL)
overlay->pbuf_has_changed = TRUE; g_free (overlay->location);
overlay->location = g_value_dup_string (value); overlay->pbuf_has_changed = TRUE;
break; overlay->location = g_value_dup_string (value);
break;
/* case PROP_STRETCH: /* case PROP_STRETCH:
overlay->stretch = g_value_get_boolean (value); overlay->stretch = g_value_get_boolean (value);
break; break;
*/ */
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
} }
@ -269,21 +271,21 @@ gst_gl_overlay_get_property (GObject * object, guint prop_id,
GstGLOverlay *overlay = GST_GL_OVERLAY (object); GstGLOverlay *overlay = GST_GL_OVERLAY (object);
switch (prop_id) { switch (prop_id) {
case PROP_LOCATION: case PROP_LOCATION:
g_value_set_string (value, overlay->location); g_value_set_string (value, overlay->location);
break; break;
/* case PROP_STRETCH: /* case PROP_STRETCH:
g_value_set_boolean (value, overlay->stretch); g_value_set_boolean (value, overlay->stretch);
break; break;
*/ */
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
} }
static void static void
gst_gl_overlay_init_resources (GstGLFilter* filter) gst_gl_overlay_init_resources (GstGLFilter * filter)
{ {
// GstGLOverlay *overlay = GST_GL_OVERLAY (filter); // GstGLOverlay *overlay = GST_GL_OVERLAY (filter);
} }
@ -291,42 +293,42 @@ gst_gl_overlay_init_resources (GstGLFilter* filter)
static void static void
gst_gl_overlay_callback (gint width, gint height, guint texture, gpointer stuff) gst_gl_overlay_callback (gint width, gint height, guint texture, gpointer stuff)
{ {
GstGLOverlay* overlay = GST_GL_OVERLAY (stuff); GstGLOverlay *overlay = GST_GL_OVERLAY (stuff);
glMatrixMode (GL_PROJECTION); glMatrixMode (GL_PROJECTION);
glLoadIdentity (); glLoadIdentity ();
gst_gl_overlay_draw_texture (overlay, texture); gst_gl_overlay_draw_texture (overlay, texture);
} }
static void init_pixbuf_texture (GstGLDisplay *display, gpointer data) static void
init_pixbuf_texture (GstGLDisplay * display, gpointer data)
{ {
GstGLOverlay *overlay = GST_GL_OVERLAY (data); GstGLOverlay *overlay = GST_GL_OVERLAY (data);
if (overlay->pixbuf) { if (overlay->pixbuf) {
glDeleteTextures (1, &overlay->pbuftexture); glDeleteTextures (1, &overlay->pbuftexture);
glGenTextures (1, &overlay->pbuftexture); glGenTextures (1, &overlay->pbuftexture);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, overlay->pbuftexture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, overlay->pbuftexture);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
(gint)overlay->width, (gint)overlay->height, 0, (gint) overlay->width, (gint) overlay->height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, overlay->pixbuf); GL_RGBA, GL_UNSIGNED_BYTE, overlay->pixbuf);
} } else
else
display->isAlive = FALSE; display->isAlive = FALSE;
} }
static gboolean static gboolean
gst_gl_overlay_filter (GstGLFilter* filter, GstGLBuffer* inbuf, gst_gl_overlay_filter (GstGLFilter * filter, GstGLBuffer * inbuf,
GstGLBuffer* outbuf) GstGLBuffer * outbuf)
{ {
GstGLOverlay* overlay = GST_GL_OVERLAY(filter); GstGLOverlay *overlay = GST_GL_OVERLAY (filter);
if (overlay->pbuf_has_changed && (overlay->location != NULL)) { if (overlay->pbuf_has_changed && (overlay->location != NULL)) {
if (!gst_gl_overlay_loader (filter)) if (!gst_gl_overlay_loader (filter))
overlay->pixbuf = NULL; overlay->pixbuf = NULL;
/* if loader failed then display is turned off */ /* if loader failed then display is turned off */
gst_gl_display_thread_add (filter->display, init_pixbuf_texture, overlay); gst_gl_display_thread_add (filter->display, init_pixbuf_texture, overlay);
@ -337,25 +339,25 @@ gst_gl_overlay_filter (GstGLFilter* filter, GstGLBuffer* inbuf,
overlay->pbuf_has_changed = FALSE; overlay->pbuf_has_changed = FALSE;
} }
gst_gl_filter_render_to_target (filter, inbuf->texture, outbuf->texture, gst_gl_filter_render_to_target (filter, inbuf->texture, outbuf->texture,
gst_gl_overlay_callback, overlay); gst_gl_overlay_callback, overlay);
return TRUE; return TRUE;
} }
static void static void
user_warning_fn(png_structp png_ptr, png_const_charp warning_msg) user_warning_fn (png_structp png_ptr, png_const_charp warning_msg)
{ {
g_warning("%s\n", warning_msg); g_warning ("%s\n", warning_msg);
} }
#define LOAD_ERROR(msg) { GST_WARNING ("unable to load %s: %s", overlay->location, msg); return FALSE; } #define LOAD_ERROR(msg) { GST_WARNING ("unable to load %s: %s", overlay->location, msg); return FALSE; }
static gboolean static gboolean
gst_gl_overlay_loader (GstGLFilter* filter) gst_gl_overlay_loader (GstGLFilter * filter)
{ {
GstGLOverlay* overlay = GST_GL_OVERLAY(filter); GstGLOverlay *overlay = GST_GL_OVERLAY (filter);
png_structp png_ptr; png_structp png_ptr;
png_infop info_ptr; png_infop info_ptr;
@ -372,60 +374,57 @@ gst_gl_overlay_loader (GstGLFilter* filter)
if (!filter->display) if (!filter->display)
return TRUE; return TRUE;
if ((fp = fopen(overlay->location, "rb")) == NULL) if ((fp = fopen (overlay->location, "rb")) == NULL)
LOAD_ERROR ("file not found"); LOAD_ERROR ("file not found");
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) if (png_ptr == NULL) {
{ fclose (fp);
fclose(fp);
LOAD_ERROR ("failed to initialize the png_struct"); LOAD_ERROR ("failed to initialize the png_struct");
} }
png_set_error_fn (png_ptr, NULL, NULL, user_warning_fn); png_set_error_fn (png_ptr, NULL, NULL, user_warning_fn);
info_ptr = png_create_info_struct(png_ptr); info_ptr = png_create_info_struct (png_ptr);
if (info_ptr == NULL) if (info_ptr == NULL) {
{ fclose (fp);
fclose(fp); png_destroy_read_struct (&png_ptr, png_infopp_NULL, png_infopp_NULL);
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
LOAD_ERROR ("failed to initialize the memory for image information"); LOAD_ERROR ("failed to initialize the memory for image information");
} }
png_init_io(png_ptr, fp); png_init_io (png_ptr, fp);
png_set_sig_bytes(png_ptr, sig_read); png_set_sig_bytes (png_ptr, sig_read);
png_read_info(png_ptr, info_ptr); png_read_info (png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
&interlace_type, int_p_NULL, int_p_NULL); &interlace_type, int_p_NULL, int_p_NULL);
if (color_type != PNG_COLOR_TYPE_RGB_ALPHA) if (color_type != PNG_COLOR_TYPE_RGB_ALPHA) {
{ fclose (fp);
fclose(fp); png_destroy_read_struct (&png_ptr, png_infopp_NULL, png_infopp_NULL);
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
LOAD_ERROR ("color type is not rgb"); LOAD_ERROR ("color type is not rgb");
} }
overlay->width = width; overlay->width = width;
overlay->height = height; overlay->height = height;
overlay->pixbuf = (guchar*) malloc ( sizeof(guchar) * width * height * 4 ); overlay->pixbuf = (guchar *) malloc (sizeof (guchar) * width * height * 4);
rows = (guchar**)malloc(sizeof(guchar*) * height); rows = (guchar **) malloc (sizeof (guchar *) * height);
for (y = 0; y < height; ++y) for (y = 0; y < height; ++y)
rows[y] = (guchar*) (overlay->pixbuf + y * width * 4); rows[y] = (guchar *) (overlay->pixbuf + y * width * 4);
png_read_image(png_ptr, rows); png_read_image (png_ptr, rows);
free(rows); free (rows);
png_read_end(png_ptr, info_ptr); png_read_end (png_ptr, info_ptr);
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); png_destroy_read_struct (&png_ptr, &info_ptr, png_infopp_NULL);
fclose(fp); fclose (fp);
return TRUE; return TRUE;
} }

View file

@ -60,548 +60,516 @@ GST_ELEMENT_DETAILS ("Video test source",
enum enum
{ {
PROP_0, PROP_0,
PROP_PATTERN, PROP_PATTERN,
PROP_TIMESTAMP_OFFSET, PROP_TIMESTAMP_OFFSET,
PROP_IS_LIVE PROP_IS_LIVE
/* FILL ME */ /* FILL ME */
}; };
GST_BOILERPLATE (GstGLTestSrc, gst_gl_test_src, GstPushSrc, GST_TYPE_PUSH_SRC); GST_BOILERPLATE (GstGLTestSrc, gst_gl_test_src, GstPushSrc, GST_TYPE_PUSH_SRC);
static void gst_gl_test_src_set_pattern (GstGLTestSrc* gltestsrc, static void gst_gl_test_src_set_pattern (GstGLTestSrc * gltestsrc,
int pattern_type); int pattern_type);
static void gst_gl_test_src_set_property (GObject* object, guint prop_id, static void gst_gl_test_src_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec); const GValue * value, GParamSpec * pspec);
static void gst_gl_test_src_get_property (GObject* object, guint prop_id, static void gst_gl_test_src_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
static gboolean gst_gl_test_src_setcaps (GstBaseSrc* bsrc, GstCaps* caps); static gboolean gst_gl_test_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps);
static void gst_gl_test_src_src_fixate (GstPad* pad, GstCaps* caps); static void gst_gl_test_src_src_fixate (GstPad * pad, GstCaps * caps);
static gboolean gst_gl_test_src_is_seekable (GstBaseSrc* psrc); static gboolean gst_gl_test_src_is_seekable (GstBaseSrc * psrc);
static gboolean gst_gl_test_src_do_seek (GstBaseSrc* bsrc, static gboolean gst_gl_test_src_do_seek (GstBaseSrc * bsrc,
GstSegment * segment); GstSegment * segment);
static gboolean gst_gl_test_src_query (GstBaseSrc* bsrc, GstQuery * query); static gboolean gst_gl_test_src_query (GstBaseSrc * bsrc, GstQuery * query);
static void gst_gl_test_src_get_times (GstBaseSrc* basesrc, static void gst_gl_test_src_get_times (GstBaseSrc * basesrc,
GstBuffer * buffer, GstClockTime* start, GstClockTime* end); GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
static GstFlowReturn gst_gl_test_src_create (GstPushSrc* psrc, static GstFlowReturn gst_gl_test_src_create (GstPushSrc * psrc,
GstBuffer** buffer); GstBuffer ** buffer);
static gboolean gst_gl_test_src_start (GstBaseSrc* basesrc); static gboolean gst_gl_test_src_start (GstBaseSrc * basesrc);
static gboolean gst_gl_test_src_stop (GstBaseSrc* basesrc); static gboolean gst_gl_test_src_stop (GstBaseSrc * basesrc);
static void gst_gl_test_src_callback (gint width, gint height, guint texture, gpointer stuff); static void gst_gl_test_src_callback (gint width, gint height, guint texture,
gpointer stuff);
#define GST_TYPE_GL_TEST_SRC_PATTERN (gst_gl_test_src_pattern_get_type ()) #define GST_TYPE_GL_TEST_SRC_PATTERN (gst_gl_test_src_pattern_get_type ())
static GType static GType
gst_gl_test_src_pattern_get_type (void) gst_gl_test_src_pattern_get_type (void)
{ {
static GType gl_test_src_pattern_type = 0; static GType gl_test_src_pattern_type = 0;
static const GEnumValue pattern_types[] = { static const GEnumValue pattern_types[] = {
{GST_GL_TEST_SRC_SMPTE, "SMPTE 100% color bars", "smpte"}, {GST_GL_TEST_SRC_SMPTE, "SMPTE 100% color bars", "smpte"},
{GST_GL_TEST_SRC_SNOW, "Random (television snow)", "snow"}, {GST_GL_TEST_SRC_SNOW, "Random (television snow)", "snow"},
{GST_GL_TEST_SRC_BLACK, "100% Black", "black"}, {GST_GL_TEST_SRC_BLACK, "100% Black", "black"},
{GST_GL_TEST_SRC_WHITE, "100% White", "white"}, {GST_GL_TEST_SRC_WHITE, "100% White", "white"},
{GST_GL_TEST_SRC_RED, "Red", "red"}, {GST_GL_TEST_SRC_RED, "Red", "red"},
{GST_GL_TEST_SRC_GREEN, "Green", "green"}, {GST_GL_TEST_SRC_GREEN, "Green", "green"},
{GST_GL_TEST_SRC_BLUE, "Blue", "blue"}, {GST_GL_TEST_SRC_BLUE, "Blue", "blue"},
{GST_GL_TEST_SRC_CHECKERS1, "Checkers 1px", "checkers-1"}, {GST_GL_TEST_SRC_CHECKERS1, "Checkers 1px", "checkers-1"},
{GST_GL_TEST_SRC_CHECKERS2, "Checkers 2px", "checkers-2"}, {GST_GL_TEST_SRC_CHECKERS2, "Checkers 2px", "checkers-2"},
{GST_GL_TEST_SRC_CHECKERS4, "Checkers 4px", "checkers-4"}, {GST_GL_TEST_SRC_CHECKERS4, "Checkers 4px", "checkers-4"},
{GST_GL_TEST_SRC_CHECKERS8, "Checkers 8px", "checkers-8"}, {GST_GL_TEST_SRC_CHECKERS8, "Checkers 8px", "checkers-8"},
{GST_GL_TEST_SRC_CIRCULAR, "Circular", "circular"}, {GST_GL_TEST_SRC_CIRCULAR, "Circular", "circular"},
{GST_GL_TEST_SRC_BLINK, "Blink", "blink"}, {GST_GL_TEST_SRC_BLINK, "Blink", "blink"},
{0, NULL, NULL} {0, NULL, NULL}
}; };
if (!gl_test_src_pattern_type) if (!gl_test_src_pattern_type) {
{ gl_test_src_pattern_type =
gl_test_src_pattern_type = g_enum_register_static ("GstGLTestSrcPattern", pattern_types);
g_enum_register_static ("GstGLTestSrcPattern", pattern_types); }
} return gl_test_src_pattern_type;
return gl_test_src_pattern_type;
} }
static void static void
gst_gl_test_src_base_init (gpointer g_class) gst_gl_test_src_base_init (gpointer g_class)
{ {
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_set_details (element_class, &gl_test_src_details); gst_element_class_set_details (element_class, &gl_test_src_details);
gst_element_class_add_pad_template (element_class, gst_element_class_add_pad_template (element_class,
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
gst_caps_from_string (GST_GL_VIDEO_CAPS))); gst_caps_from_string (GST_GL_VIDEO_CAPS)));
} }
static void static void
gst_gl_test_src_class_init (GstGLTestSrcClass* klass) gst_gl_test_src_class_init (GstGLTestSrcClass * klass)
{ {
GObjectClass *gobject_class; GObjectClass *gobject_class;
GstBaseSrcClass *gstbasesrc_class; GstBaseSrcClass *gstbasesrc_class;
GstPushSrcClass *gstpushsrc_class; GstPushSrcClass *gstpushsrc_class;
GST_DEBUG_CATEGORY_INIT (gl_test_src_debug, "gltestsrc", 0, GST_DEBUG_CATEGORY_INIT (gl_test_src_debug, "gltestsrc", 0,
"Video Test Source"); "Video Test Source");
gobject_class = (GObjectClass *) klass; gobject_class = (GObjectClass *) klass;
gstbasesrc_class = (GstBaseSrcClass *) klass; gstbasesrc_class = (GstBaseSrcClass *) klass;
gstpushsrc_class = (GstPushSrcClass *) klass; gstpushsrc_class = (GstPushSrcClass *) klass;
gobject_class->set_property = gst_gl_test_src_set_property; gobject_class->set_property = gst_gl_test_src_set_property;
gobject_class->get_property = gst_gl_test_src_get_property; gobject_class->get_property = gst_gl_test_src_get_property;
g_object_class_install_property (gobject_class, PROP_PATTERN, g_object_class_install_property (gobject_class, PROP_PATTERN,
g_param_spec_enum ("pattern", "Pattern", g_param_spec_enum ("pattern", "Pattern",
"Type of test pattern to generate", GST_TYPE_GL_TEST_SRC_PATTERN, "Type of test pattern to generate", GST_TYPE_GL_TEST_SRC_PATTERN,
GST_GL_TEST_SRC_SMPTE, G_PARAM_READWRITE)); GST_GL_TEST_SRC_SMPTE, G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset", PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset",
"Timestamp offset", "Timestamp offset",
"An offset added to timestamps set on buffers (in ns)", G_MININT64, "An offset added to timestamps set on buffers (in ns)", G_MININT64,
G_MAXINT64, 0, G_PARAM_READWRITE)); G_MAXINT64, 0, G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, PROP_IS_LIVE, g_object_class_install_property (gobject_class, PROP_IS_LIVE,
g_param_spec_boolean ("is-live", "Is Live", g_param_spec_boolean ("is-live", "Is Live",
"Whether to act as a live source", FALSE, G_PARAM_READWRITE)); "Whether to act as a live source", FALSE, G_PARAM_READWRITE));
gstbasesrc_class->set_caps = gst_gl_test_src_setcaps; gstbasesrc_class->set_caps = gst_gl_test_src_setcaps;
gstbasesrc_class->is_seekable = gst_gl_test_src_is_seekable; gstbasesrc_class->is_seekable = gst_gl_test_src_is_seekable;
gstbasesrc_class->do_seek = gst_gl_test_src_do_seek; gstbasesrc_class->do_seek = gst_gl_test_src_do_seek;
gstbasesrc_class->query = gst_gl_test_src_query; gstbasesrc_class->query = gst_gl_test_src_query;
gstbasesrc_class->get_times = gst_gl_test_src_get_times; gstbasesrc_class->get_times = gst_gl_test_src_get_times;
gstbasesrc_class->start = gst_gl_test_src_start; gstbasesrc_class->start = gst_gl_test_src_start;
gstbasesrc_class->stop = gst_gl_test_src_stop; gstbasesrc_class->stop = gst_gl_test_src_stop;
gstpushsrc_class->create = gst_gl_test_src_create; gstpushsrc_class->create = gst_gl_test_src_create;
} }
static void static void
gst_gl_test_src_init (GstGLTestSrc* src, GstGLTestSrcClass* g_class) gst_gl_test_src_init (GstGLTestSrc * src, GstGLTestSrcClass * g_class)
{ {
GstPad *pad = GST_BASE_SRC_PAD (src); GstPad *pad = GST_BASE_SRC_PAD (src);
gst_pad_set_fixatecaps_function (pad, gst_gl_test_src_src_fixate); gst_pad_set_fixatecaps_function (pad, gst_gl_test_src_src_fixate);
gst_gl_test_src_set_pattern (src, GST_GL_TEST_SRC_SMPTE); gst_gl_test_src_set_pattern (src, GST_GL_TEST_SRC_SMPTE);
src->timestamp_offset = 0; src->timestamp_offset = 0;
/* we operate in time */ /* we operate in time */
gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME); gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
gst_base_src_set_live (GST_BASE_SRC (src), FALSE); gst_base_src_set_live (GST_BASE_SRC (src), FALSE);
} }
static void static void
gst_gl_test_src_src_fixate (GstPad* pad, GstCaps* caps) gst_gl_test_src_src_fixate (GstPad * pad, GstCaps * caps)
{ {
GstStructure *structure; GstStructure *structure;
GST_DEBUG ("fixate"); GST_DEBUG ("fixate");
structure = gst_caps_get_structure (caps, 0); structure = gst_caps_get_structure (caps, 0);
gst_structure_fixate_field_nearest_int (structure, "width", 320); gst_structure_fixate_field_nearest_int (structure, "width", 320);
gst_structure_fixate_field_nearest_int (structure, "height", 240); gst_structure_fixate_field_nearest_int (structure, "height", 240);
gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1); gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1);
} }
static void static void
gst_gl_test_src_set_pattern (GstGLTestSrc* gltestsrc, gint pattern_type) gst_gl_test_src_set_pattern (GstGLTestSrc * gltestsrc, gint pattern_type)
{ {
gltestsrc->pattern_type = pattern_type; gltestsrc->pattern_type = pattern_type;
GST_DEBUG_OBJECT (gltestsrc, "setting pattern to %d", pattern_type); GST_DEBUG_OBJECT (gltestsrc, "setting pattern to %d", pattern_type);
switch (pattern_type) { switch (pattern_type) {
case GST_GL_TEST_SRC_SMPTE: case GST_GL_TEST_SRC_SMPTE:
gltestsrc->make_image = gst_gl_test_src_smpte; gltestsrc->make_image = gst_gl_test_src_smpte;
break; break;
case GST_GL_TEST_SRC_SNOW: case GST_GL_TEST_SRC_SNOW:
gltestsrc->make_image = gst_gl_test_src_snow; gltestsrc->make_image = gst_gl_test_src_snow;
break; break;
case GST_GL_TEST_SRC_BLACK: case GST_GL_TEST_SRC_BLACK:
gltestsrc->make_image = gst_gl_test_src_black; gltestsrc->make_image = gst_gl_test_src_black;
break; break;
case GST_GL_TEST_SRC_WHITE: case GST_GL_TEST_SRC_WHITE:
gltestsrc->make_image = gst_gl_test_src_white; gltestsrc->make_image = gst_gl_test_src_white;
break; break;
case GST_GL_TEST_SRC_RED: case GST_GL_TEST_SRC_RED:
gltestsrc->make_image = gst_gl_test_src_red; gltestsrc->make_image = gst_gl_test_src_red;
break; break;
case GST_GL_TEST_SRC_GREEN: case GST_GL_TEST_SRC_GREEN:
gltestsrc->make_image = gst_gl_test_src_green; gltestsrc->make_image = gst_gl_test_src_green;
break; break;
case GST_GL_TEST_SRC_BLUE: case GST_GL_TEST_SRC_BLUE:
gltestsrc->make_image = gst_gl_test_src_blue; gltestsrc->make_image = gst_gl_test_src_blue;
break; break;
case GST_GL_TEST_SRC_CHECKERS1: case GST_GL_TEST_SRC_CHECKERS1:
gltestsrc->make_image = gst_gl_test_src_checkers1; gltestsrc->make_image = gst_gl_test_src_checkers1;
break; break;
case GST_GL_TEST_SRC_CHECKERS2: case GST_GL_TEST_SRC_CHECKERS2:
gltestsrc->make_image = gst_gl_test_src_checkers2; gltestsrc->make_image = gst_gl_test_src_checkers2;
break; break;
case GST_GL_TEST_SRC_CHECKERS4: case GST_GL_TEST_SRC_CHECKERS4:
gltestsrc->make_image = gst_gl_test_src_checkers4; gltestsrc->make_image = gst_gl_test_src_checkers4;
break; break;
case GST_GL_TEST_SRC_CHECKERS8: case GST_GL_TEST_SRC_CHECKERS8:
gltestsrc->make_image = gst_gl_test_src_checkers8; gltestsrc->make_image = gst_gl_test_src_checkers8;
break; break;
case GST_GL_TEST_SRC_CIRCULAR: case GST_GL_TEST_SRC_CIRCULAR:
gltestsrc->make_image = gst_gl_test_src_circular; gltestsrc->make_image = gst_gl_test_src_circular;
break; break;
case GST_GL_TEST_SRC_BLINK: case GST_GL_TEST_SRC_BLINK:
gltestsrc->make_image = gst_gl_test_src_black; gltestsrc->make_image = gst_gl_test_src_black;
break; break;
default: default:
g_assert_not_reached (); g_assert_not_reached ();
} }
} }
static void static void
gst_gl_test_src_set_property (GObject* object, guint prop_id, gst_gl_test_src_set_property (GObject * object, guint prop_id,
const GValue* value, GParamSpec* pspec) const GValue * value, GParamSpec * pspec)
{ {
GstGLTestSrc* src = GST_GL_TEST_SRC (object); GstGLTestSrc *src = GST_GL_TEST_SRC (object);
switch (prop_id) switch (prop_id) {
{ case PROP_PATTERN:
case PROP_PATTERN: gst_gl_test_src_set_pattern (src, g_value_get_enum (value));
gst_gl_test_src_set_pattern (src, g_value_get_enum (value)); break;
break; case PROP_TIMESTAMP_OFFSET:
case PROP_TIMESTAMP_OFFSET: src->timestamp_offset = g_value_get_int64 (value);
src->timestamp_offset = g_value_get_int64 (value); break;
break; case PROP_IS_LIVE:
case PROP_IS_LIVE: gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value));
gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value)); break;
break; default:
default: break;
break; }
}
} }
static void static void
gst_gl_test_src_get_property (GObject* object, guint prop_id, gst_gl_test_src_get_property (GObject * object, guint prop_id,
GValue* value, GParamSpec* pspec) GValue * value, GParamSpec * pspec)
{ {
GstGLTestSrc* src = GST_GL_TEST_SRC (object); GstGLTestSrc *src = GST_GL_TEST_SRC (object);
switch (prop_id) { switch (prop_id) {
case PROP_PATTERN: case PROP_PATTERN:
g_value_set_enum (value, src->pattern_type); g_value_set_enum (value, src->pattern_type);
break; break;
case PROP_TIMESTAMP_OFFSET: case PROP_TIMESTAMP_OFFSET:
g_value_set_int64 (value, src->timestamp_offset); g_value_set_int64 (value, src->timestamp_offset);
break; break;
case PROP_IS_LIVE: case PROP_IS_LIVE:
g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src))); g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src)));
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
} }
static gboolean static gboolean
gst_gl_test_src_parse_caps (const GstCaps* caps, gst_gl_test_src_parse_caps (const GstCaps * caps,
gint* width, gint* height, gint* rate_numerator, gint* rate_denominator) gint * width, gint * height, gint * rate_numerator, gint * rate_denominator)
{ {
const GstStructure *structure; const GstStructure *structure;
GstPadLinkReturn ret; GstPadLinkReturn ret;
const GValue *framerate; const GValue *framerate;
GST_DEBUG ("parsing caps"); GST_DEBUG ("parsing caps");
if (gst_caps_get_size (caps) < 1) if (gst_caps_get_size (caps) < 1)
return FALSE; return FALSE;
structure = gst_caps_get_structure (caps, 0); structure = gst_caps_get_structure (caps, 0);
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);
framerate = gst_structure_get_value (structure, "framerate"); framerate = gst_structure_get_value (structure, "framerate");
if (framerate) if (framerate) {
{ *rate_numerator = gst_value_get_fraction_numerator (framerate);
*rate_numerator = gst_value_get_fraction_numerator (framerate); *rate_denominator = gst_value_get_fraction_denominator (framerate);
*rate_denominator = gst_value_get_fraction_denominator (framerate); } else
} goto no_framerate;
else
goto no_framerate;
return ret; return ret;
/* ERRORS */ /* ERRORS */
no_framerate: no_framerate:
{ {
GST_DEBUG ("gltestsrc no framerate given"); GST_DEBUG ("gltestsrc no framerate given");
return FALSE; return FALSE;
} }
} }
static gboolean static gboolean
gst_gl_test_src_setcaps (GstBaseSrc* bsrc, GstCaps* caps) gst_gl_test_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps)
{ {
gboolean res; gboolean res;
gint width, height, rate_denominator, rate_numerator; gint width, height, rate_denominator, rate_numerator;
GstGLTestSrc* gltestsrc; GstGLTestSrc *gltestsrc;
gltestsrc = GST_GL_TEST_SRC (bsrc); gltestsrc = GST_GL_TEST_SRC (bsrc);
GST_DEBUG ("setcaps"); GST_DEBUG ("setcaps");
res = gst_gl_test_src_parse_caps (caps, &width, &height, res = gst_gl_test_src_parse_caps (caps, &width, &height,
&rate_numerator, &rate_denominator); &rate_numerator, &rate_denominator);
if (res) if (res) {
{ /* looks ok here */
/* looks ok here */ gltestsrc->width = width;
gltestsrc->width = width; gltestsrc->height = height;
gltestsrc->height = height; gltestsrc->rate_numerator = rate_numerator;
gltestsrc->rate_numerator = rate_numerator; gltestsrc->rate_denominator = rate_denominator;
gltestsrc->rate_denominator = rate_denominator; gltestsrc->negotiated = TRUE;
gltestsrc->negotiated = TRUE;
GST_DEBUG_OBJECT (gltestsrc, "size %dx%d, %d/%d fps", GST_DEBUG_OBJECT (gltestsrc, "size %dx%d, %d/%d fps",
gltestsrc->width, gltestsrc->height, gltestsrc->width, gltestsrc->height,
gltestsrc->rate_numerator, gltestsrc->rate_denominator); gltestsrc->rate_numerator, gltestsrc->rate_denominator);
gltestsrc->display = gst_gl_display_new (); gltestsrc->display = gst_gl_display_new ();
gst_gl_display_create_context (gltestsrc->display, gst_gl_display_create_context (gltestsrc->display,
gltestsrc->width, gltestsrc->height); gltestsrc->width, gltestsrc->height);
gst_gl_display_gen_fbo (gltestsrc->display, gltestsrc->width, gltestsrc->height, gst_gl_display_gen_fbo (gltestsrc->display, gltestsrc->width,
&gltestsrc->fbo, &gltestsrc->depthbuffer); gltestsrc->height, &gltestsrc->fbo, &gltestsrc->depthbuffer);
} }
return res; return res;
} }
static gboolean static gboolean
gst_gl_test_src_query (GstBaseSrc* bsrc, GstQuery* query) gst_gl_test_src_query (GstBaseSrc * bsrc, GstQuery * query)
{ {
gboolean res; gboolean res;
GstGLTestSrc *src; GstGLTestSrc *src;
src = GST_GL_TEST_SRC (bsrc); src = GST_GL_TEST_SRC (bsrc);
switch (GST_QUERY_TYPE (query)) switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_CONVERT:
{ {
case GST_QUERY_CONVERT: GstFormat src_fmt, dest_fmt;
{ gint64 src_val, dest_val;
GstFormat src_fmt, dest_fmt;
gint64 src_val, dest_val;
gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
if (src_fmt == dest_fmt) if (src_fmt == dest_fmt) {
{ dest_val = src_val;
dest_val = src_val; goto done;
goto done; }
}
switch (src_fmt) switch (src_fmt) {
{ case GST_FORMAT_DEFAULT:
case GST_FORMAT_DEFAULT: switch (dest_fmt) {
switch (dest_fmt) case GST_FORMAT_TIME:
{ /* frames to time */
case GST_FORMAT_TIME: if (src->rate_numerator) {
/* frames to time */ dest_val = gst_util_uint64_scale (src_val,
if (src->rate_numerator) src->rate_denominator * GST_SECOND, src->rate_numerator);
{ } else
dest_val = gst_util_uint64_scale (src_val, dest_val = 0;
src->rate_denominator * GST_SECOND, src->rate_numerator); break;
} default:
else goto error;
dest_val = 0; }
break; break;
default: case GST_FORMAT_TIME:
goto error; switch (dest_fmt) {
} case GST_FORMAT_DEFAULT:
break; /* time to frames */
case GST_FORMAT_TIME: if (src->rate_numerator) {
switch (dest_fmt) dest_val = gst_util_uint64_scale (src_val,
{ src->rate_numerator, src->rate_denominator * GST_SECOND);
case GST_FORMAT_DEFAULT: } else
/* time to frames */ dest_val = 0;
if (src->rate_numerator) break;
{ default:
dest_val = gst_util_uint64_scale (src_val, goto error;
src->rate_numerator, src->rate_denominator * GST_SECOND); }
}
else
dest_val = 0;
break;
default:
goto error;
}
break;
default:
goto error;
}
done:
gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
res = TRUE;
break; break;
}
default: default:
res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query); goto error;
}
done:
gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
res = TRUE;
break;
} }
return res; default:
res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
}
return res;
/* ERROR */ /* ERROR */
error: error:
{ {
GST_DEBUG_OBJECT (src, "query failed"); GST_DEBUG_OBJECT (src, "query failed");
return FALSE; return FALSE;
} }
} }
static void static void
gst_gl_test_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer, gst_gl_test_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
GstClockTime * start, GstClockTime * end) GstClockTime * start, GstClockTime * end)
{ {
/* for live sources, sync on the timestamp of the buffer */ /* for live sources, sync on the timestamp of the buffer */
if (gst_base_src_is_live (basesrc)) if (gst_base_src_is_live (basesrc)) {
{ GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
if (GST_CLOCK_TIME_IS_VALID (timestamp)) if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
{ /* get duration to calculate end time */
/* get duration to calculate end time */ GstClockTime duration = GST_BUFFER_DURATION (buffer);
GstClockTime duration = GST_BUFFER_DURATION (buffer);
if (GST_CLOCK_TIME_IS_VALID (duration)) if (GST_CLOCK_TIME_IS_VALID (duration))
*end = timestamp + duration; *end = timestamp + duration;
*start = timestamp; *start = timestamp;
}
}
else
{
*start = -1;
*end = -1;
} }
} else {
*start = -1;
*end = -1;
}
} }
static gboolean static gboolean
gst_gl_test_src_do_seek (GstBaseSrc* bsrc, GstSegment* segment) gst_gl_test_src_do_seek (GstBaseSrc * bsrc, GstSegment * segment)
{ {
GstClockTime time; GstClockTime time;
GstGLTestSrc* src; GstGLTestSrc *src;
src = GST_GL_TEST_SRC (bsrc); src = GST_GL_TEST_SRC (bsrc);
segment->time = segment->start; segment->time = segment->start;
time = segment->last_stop; time = segment->last_stop;
/* now move to the time indicated */ /* now move to the time indicated */
if (src->rate_numerator) if (src->rate_numerator) {
{ src->n_frames = gst_util_uint64_scale (time,
src->n_frames = gst_util_uint64_scale (time,
src->rate_numerator, src->rate_denominator * GST_SECOND); src->rate_numerator, src->rate_denominator * GST_SECOND);
} } else
else src->n_frames = 0;
src->n_frames = 0;
if (src->rate_numerator) if (src->rate_numerator) {
{ src->running_time = gst_util_uint64_scale (src->n_frames,
src->running_time = gst_util_uint64_scale (src->n_frames,
src->rate_denominator * GST_SECOND, src->rate_numerator); src->rate_denominator * GST_SECOND, src->rate_numerator);
} } else {
else /* FIXME : Not sure what to set here */
{ src->running_time = 0;
/* FIXME : Not sure what to set here */ }
src->running_time = 0;
}
g_assert (src->running_time <= time); g_assert (src->running_time <= time);
return TRUE; return TRUE;
} }
static gboolean static gboolean
gst_gl_test_src_is_seekable (GstBaseSrc* psrc) gst_gl_test_src_is_seekable (GstBaseSrc * psrc)
{ {
/* we're seekable... */ /* we're seekable... */
return TRUE; return TRUE;
} }
static GstFlowReturn static GstFlowReturn
gst_gl_test_src_create (GstPushSrc* psrc, GstBuffer** buffer) gst_gl_test_src_create (GstPushSrc * psrc, GstBuffer ** buffer)
{ {
GstGLTestSrc* src; GstGLTestSrc *src;
GstGLBuffer* outbuf; GstGLBuffer *outbuf;
//GstFlowReturn res; //GstFlowReturn res;
GstClockTime next_time; GstClockTime next_time;
src = GST_GL_TEST_SRC (psrc); src = GST_GL_TEST_SRC (psrc);
if (G_UNLIKELY (!src->negotiated)) if (G_UNLIKELY (!src->negotiated))
goto not_negotiated; goto not_negotiated;
/* 0 framerate and we are at the second frame, eos */ /* 0 framerate and we are at the second frame, eos */
if (G_UNLIKELY (src->rate_numerator == 0 && src->n_frames == 1)) if (G_UNLIKELY (src->rate_numerator == 0 && src->n_frames == 1))
goto eos; goto eos;
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, outbuf = gst_gl_buffer_new (src->display, src->width, src->height);
src->width, src->height);
if (!outbuf->texture) if (!outbuf->texture) {
{ gst_buffer_unref (outbuf);
gst_buffer_unref (outbuf); goto eos;
goto eos; }
}
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)));
if (src->pattern_type == GST_GL_TEST_SRC_BLINK) if (src->pattern_type == GST_GL_TEST_SRC_BLINK) {
{ if (src->n_frames & 0x1)
if (src->n_frames & 0x1) src->make_image = gst_gl_test_src_white;
src->make_image = gst_gl_test_src_white; else
else src->make_image = gst_gl_test_src_black;
src->make_image = gst_gl_test_src_black; }
}
src->buffer = outbuf; src->buffer = outbuf;
//blocking call, generate a FBO
if(!gst_gl_display_use_fbo (src->display, src->width, src->height,
src->fbo, src->depthbuffer, outbuf->texture,
gst_gl_test_src_callback,
0, 0, 0, //no input texture
0, src->width, 0, src->height,
GST_GL_DISPLAY_PROJECTION_ORTHO2D,
(gpointer)src))
{
gst_buffer_unref (outbuf);
goto eos;
}
GST_BUFFER_TIMESTAMP (GST_BUFFER (outbuf)) = //blocking call, generate a FBO
src->timestamp_offset + src->running_time; if (!gst_gl_display_use_fbo (src->display, src->width, src->height, src->fbo, src->depthbuffer, outbuf->texture, gst_gl_test_src_callback, 0, 0, 0, //no input texture
GST_BUFFER_OFFSET (GST_BUFFER (outbuf)) = src->n_frames; 0, src->width, 0, src->height,
src->n_frames++; GST_GL_DISPLAY_PROJECTION_ORTHO2D, (gpointer) src)) {
GST_BUFFER_OFFSET_END (GST_BUFFER (outbuf)) = src->n_frames; gst_buffer_unref (outbuf);
if (src->rate_numerator) goto eos;
{ }
next_time = gst_util_uint64_scale_int (src->n_frames * GST_SECOND,
src->rate_denominator, src->rate_numerator);
GST_BUFFER_DURATION (GST_BUFFER (outbuf)) = next_time - src->running_time;
}
else {
next_time = src->timestamp_offset;
/* NONE means forever */
GST_BUFFER_DURATION (GST_BUFFER (outbuf)) = GST_CLOCK_TIME_NONE;
}
src->running_time = next_time; GST_BUFFER_TIMESTAMP (GST_BUFFER (outbuf)) =
src->timestamp_offset + src->running_time;
GST_BUFFER_OFFSET (GST_BUFFER (outbuf)) = src->n_frames;
src->n_frames++;
GST_BUFFER_OFFSET_END (GST_BUFFER (outbuf)) = src->n_frames;
if (src->rate_numerator) {
next_time = gst_util_uint64_scale_int (src->n_frames * GST_SECOND,
src->rate_denominator, src->rate_numerator);
GST_BUFFER_DURATION (GST_BUFFER (outbuf)) = next_time - src->running_time;
} else {
next_time = src->timestamp_offset;
/* NONE means forever */
GST_BUFFER_DURATION (GST_BUFFER (outbuf)) = GST_CLOCK_TIME_NONE;
}
*buffer = GST_BUFFER (outbuf); src->running_time = next_time;
return GST_FLOW_OK; *buffer = GST_BUFFER (outbuf);
return GST_FLOW_OK;
not_negotiated: not_negotiated:
{ {
@ -625,39 +593,38 @@ no_buffer:
} }
static gboolean static gboolean
gst_gl_test_src_start (GstBaseSrc* basesrc) gst_gl_test_src_start (GstBaseSrc * basesrc)
{ {
GstGLTestSrc* src = GST_GL_TEST_SRC (basesrc); GstGLTestSrc *src = GST_GL_TEST_SRC (basesrc);
src->running_time = 0; src->running_time = 0;
src->n_frames = 0; src->n_frames = 0;
src->negotiated = FALSE; src->negotiated = FALSE;
return TRUE; return TRUE;
} }
static gboolean static gboolean
gst_gl_test_src_stop (GstBaseSrc* basesrc) gst_gl_test_src_stop (GstBaseSrc * basesrc)
{ {
GstGLTestSrc* src = GST_GL_TEST_SRC (basesrc); GstGLTestSrc *src = GST_GL_TEST_SRC (basesrc);
if (src->display) if (src->display) {
{ //blocking call, delete the FBO
//blocking call, delete the FBO gst_gl_display_del_fbo (src->display, src->fbo, src->depthbuffer);
gst_gl_display_del_fbo (src->display, src->fbo, g_object_unref (src->display);
src->depthbuffer); src->display = NULL;
g_object_unref (src->display); }
src->display = NULL;
}
return TRUE; return TRUE;
} }
//opengl scene //opengl scene
static void static void
gst_gl_test_src_callback (gint width, gint height, guint texture, gpointer stuff) gst_gl_test_src_callback (gint width, gint height, guint texture,
gpointer stuff)
{ {
GstGLTestSrc* src = GST_GL_TEST_SRC (stuff); GstGLTestSrc *src = GST_GL_TEST_SRC (stuff);
src->make_image (src, src->buffer, src->width, src->height); src->make_image (src, src->buffer, src->width, src->height);
} }

View file

@ -75,10 +75,10 @@
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
static const GstElementDetails element_details = static const GstElementDetails element_details =
GST_ELEMENT_DETAILS ("OpenGL upload", GST_ELEMENT_DETAILS ("OpenGL upload",
"Filter/Effect", "Filter/Effect",
"A from video to GL flow filter", "A from video to GL flow filter",
"Julien Isorce <julien.isorce@gmail.com>"); "Julien Isorce <julien.isorce@gmail.com>");
/* Source pad definition */ /* Source pad definition */
static GstStaticPadTemplate gst_gl_upload_src_pad_template = static GstStaticPadTemplate gst_gl_upload_src_pad_template =
@ -93,8 +93,7 @@ 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_STATIC_CAPS (GST_VIDEO_CAPS_RGB ";" GST_VIDEO_CAPS_BGR ";"
GST_VIDEO_CAPS_RGB ";" GST_VIDEO_CAPS_BGR ";"
GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_BGRx ";" GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_BGRx ";"
GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_xBGR ";" GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_xBGR ";"
GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_BGRA ";" GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_BGRA ";"
@ -105,7 +104,7 @@ static GstStaticPadTemplate gst_gl_upload_sink_pad_template =
/* Properties */ /* Properties */
enum enum
{ {
PROP_0 PROP_0
}; };
#define DEBUG_INIT(bla) \ #define DEBUG_INIT(bla) \
@ -114,411 +113,384 @@ enum
GST_BOILERPLATE_FULL (GstGLUpload, gst_gl_upload, GstBaseTransform, GST_BOILERPLATE_FULL (GstGLUpload, gst_gl_upload, GstBaseTransform,
GST_TYPE_BASE_TRANSFORM, DEBUG_INIT); GST_TYPE_BASE_TRANSFORM, DEBUG_INIT);
static void gst_gl_upload_set_property (GObject* object, guint prop_id, static void gst_gl_upload_set_property (GObject * object, guint prop_id,
const GValue* value, GParamSpec* pspec); const GValue * value, GParamSpec * pspec);
static void gst_gl_upload_get_property (GObject* object, guint prop_id, static void gst_gl_upload_get_property (GObject * object, guint prop_id,
GValue* value, GParamSpec* pspec); GValue * value, GParamSpec * pspec);
static void gst_gl_upload_reset (GstGLUpload* upload); static void gst_gl_upload_reset (GstGLUpload * upload);
static gboolean gst_gl_upload_set_caps (GstBaseTransform* bt, static gboolean gst_gl_upload_set_caps (GstBaseTransform * bt,
GstCaps* incaps, GstCaps* outcaps); GstCaps * incaps, GstCaps * outcaps);
static GstCaps *gst_gl_upload_transform_caps (GstBaseTransform* bt, static GstCaps *gst_gl_upload_transform_caps (GstBaseTransform * bt,
GstPadDirection direction, GstCaps* caps); GstPadDirection direction, GstCaps * caps);
static void gst_gl_upload_fixate_caps (GstBaseTransform* base, GstPadDirection direction, static void gst_gl_upload_fixate_caps (GstBaseTransform * base,
GstCaps* caps, GstCaps* othercaps); GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
static gboolean gst_gl_upload_start (GstBaseTransform* bt); static gboolean gst_gl_upload_start (GstBaseTransform * bt);
static gboolean gst_gl_upload_stop (GstBaseTransform* bt); static gboolean gst_gl_upload_stop (GstBaseTransform * bt);
static GstFlowReturn gst_gl_upload_prepare_output_buffer (GstBaseTransform* trans, static GstFlowReturn gst_gl_upload_prepare_output_buffer (GstBaseTransform *
GstBuffer* input, gint size, GstCaps* caps, GstBuffer** buf); trans, GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf);
static GstFlowReturn gst_gl_upload_transform (GstBaseTransform* trans, static GstFlowReturn gst_gl_upload_transform (GstBaseTransform * trans,
GstBuffer* inbuf, GstBuffer * outbuf); GstBuffer * inbuf, GstBuffer * outbuf);
static gboolean gst_gl_upload_get_unit_size (GstBaseTransform* trans, static gboolean gst_gl_upload_get_unit_size (GstBaseTransform * trans,
GstCaps* caps, guint* size); GstCaps * caps, guint * size);
static void static void
gst_gl_upload_base_init (gpointer klass) gst_gl_upload_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_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_upload_src_pad_template)); gst_static_pad_template_get (&gst_gl_upload_src_pad_template));
gst_element_class_add_pad_template (element_class, gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_gl_upload_sink_pad_template)); gst_static_pad_template_get (&gst_gl_upload_sink_pad_template));
} }
static void static void
gst_gl_upload_class_init (GstGLUploadClass * klass) gst_gl_upload_class_init (GstGLUploadClass * klass)
{ {
GObjectClass *gobject_class; GObjectClass *gobject_class;
gobject_class = (GObjectClass *) klass; gobject_class = (GObjectClass *) klass;
gobject_class->set_property = gst_gl_upload_set_property; gobject_class->set_property = gst_gl_upload_set_property;
gobject_class->get_property = gst_gl_upload_get_property; gobject_class->get_property = gst_gl_upload_get_property;
GST_BASE_TRANSFORM_CLASS (klass)->transform_caps = GST_BASE_TRANSFORM_CLASS (klass)->transform_caps =
gst_gl_upload_transform_caps; gst_gl_upload_transform_caps;
GST_BASE_TRANSFORM_CLASS (klass)->fixate_caps = gst_gl_upload_fixate_caps; GST_BASE_TRANSFORM_CLASS (klass)->fixate_caps = gst_gl_upload_fixate_caps;
GST_BASE_TRANSFORM_CLASS (klass)->transform = gst_gl_upload_transform; GST_BASE_TRANSFORM_CLASS (klass)->transform = gst_gl_upload_transform;
GST_BASE_TRANSFORM_CLASS (klass)->start = gst_gl_upload_start; GST_BASE_TRANSFORM_CLASS (klass)->start = gst_gl_upload_start;
GST_BASE_TRANSFORM_CLASS (klass)->stop = gst_gl_upload_stop; GST_BASE_TRANSFORM_CLASS (klass)->stop = gst_gl_upload_stop;
GST_BASE_TRANSFORM_CLASS (klass)->set_caps = gst_gl_upload_set_caps; GST_BASE_TRANSFORM_CLASS (klass)->set_caps = gst_gl_upload_set_caps;
GST_BASE_TRANSFORM_CLASS (klass)->get_unit_size = gst_gl_upload_get_unit_size; GST_BASE_TRANSFORM_CLASS (klass)->get_unit_size = gst_gl_upload_get_unit_size;
GST_BASE_TRANSFORM_CLASS (klass)->prepare_output_buffer = GST_BASE_TRANSFORM_CLASS (klass)->prepare_output_buffer =
gst_gl_upload_prepare_output_buffer; gst_gl_upload_prepare_output_buffer;
} }
static void static void
gst_gl_upload_init (GstGLUpload* upload, GstGLUploadClass * klass) gst_gl_upload_init (GstGLUpload * upload, GstGLUploadClass * klass)
{ {
gst_gl_upload_reset (upload); gst_gl_upload_reset (upload);
} }
static void static void
gst_gl_upload_set_property (GObject* object, guint prop_id, gst_gl_upload_set_property (GObject * object, guint prop_id,
const GValue* value, GParamSpec* pspec) const GValue * value, GParamSpec * pspec)
{ {
//GstGLUpload* upload = GST_GL_UPLOAD (object); //GstGLUpload* upload = GST_GL_UPLOAD (object);
switch (prop_id) switch (prop_id) {
{ default:
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break;
break; }
}
} }
static void static void
gst_gl_upload_get_property (GObject* object, guint prop_id, gst_gl_upload_get_property (GObject * object, guint prop_id,
GValue* value, GParamSpec* pspec) GValue * value, GParamSpec * pspec)
{ {
//GstGLUpload *upload = GST_GL_UPLOAD (object); //GstGLUpload *upload = GST_GL_UPLOAD (object);
switch (prop_id) switch (prop_id) {
{ default:
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break;
break; }
}
} }
static void static void
gst_gl_upload_reset (GstGLUpload* upload) gst_gl_upload_reset (GstGLUpload * upload)
{ {
if (upload->display) if (upload->display) {
{ g_object_unref (upload->display);
g_object_unref (upload->display); upload->display = NULL;
upload->display = NULL; }
}
} }
static gboolean static gboolean
gst_gl_upload_start (GstBaseTransform* bt) gst_gl_upload_start (GstBaseTransform * bt)
{ {
//GstGLUpload* upload = GST_GL_UPLOAD (bt); //GstGLUpload* upload = GST_GL_UPLOAD (bt);
return TRUE; return TRUE;
} }
static gboolean static gboolean
gst_gl_upload_stop (GstBaseTransform* bt) gst_gl_upload_stop (GstBaseTransform * bt)
{ {
GstGLUpload* upload = GST_GL_UPLOAD (bt); GstGLUpload *upload = GST_GL_UPLOAD (bt);
gst_gl_upload_reset (upload); gst_gl_upload_reset (upload);
return TRUE; return TRUE;
} }
static GstCaps* static GstCaps *
gst_gl_upload_transform_caps (GstBaseTransform* bt, gst_gl_upload_transform_caps (GstBaseTransform * bt,
GstPadDirection direction, GstCaps* caps) GstPadDirection direction, GstCaps * caps)
{ {
//GstGLUpload* upload = GST_GL_UPLOAD (bt); //GstGLUpload* upload = GST_GL_UPLOAD (bt);
GstStructure* structure = gst_caps_get_structure (caps, 0); GstStructure *structure = gst_caps_get_structure (caps, 0);
GstCaps* newcaps = NULL; GstCaps *newcaps = NULL;
const GValue* framerate_value = NULL; const GValue *framerate_value = NULL;
const GValue* par_value = NULL; const GValue *par_value = NULL;
GST_DEBUG ("transform caps %" GST_PTR_FORMAT, caps); GST_DEBUG ("transform caps %" GST_PTR_FORMAT, caps);
framerate_value = gst_structure_get_value (structure, "framerate"); framerate_value = gst_structure_get_value (structure, "framerate");
par_value = gst_structure_get_value (structure, "pixel-aspect-ratio"); par_value = gst_structure_get_value (structure, "pixel-aspect-ratio");
if (direction == GST_PAD_SRC) if (direction == GST_PAD_SRC) {
{ GstCaps *newothercaps = gst_caps_new_simple ("video/x-raw-rgb", NULL);
GstCaps* newothercaps = gst_caps_new_simple ("video/x-raw-rgb", NULL);
newcaps = gst_caps_new_simple ("video/x-raw-yuv", NULL); newcaps = gst_caps_new_simple ("video/x-raw-yuv", NULL);
gst_caps_append(newcaps, newothercaps); gst_caps_append (newcaps, newothercaps);
} } else
else
newcaps = gst_caps_new_simple ("video/x-raw-gl", NULL); newcaps = gst_caps_new_simple ("video/x-raw-gl", NULL);
structure = gst_caps_get_structure (newcaps, 0); structure = gst_caps_get_structure (newcaps, 0);
gst_structure_set (structure, gst_structure_set (structure,
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT, "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"height", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
gst_structure_set_value (structure, "framerate", framerate_value); gst_structure_set_value (structure, "framerate", framerate_value);
if (par_value) if (par_value)
gst_structure_set_value (structure, "pixel-aspect-ratio", par_value); gst_structure_set_value (structure, "pixel-aspect-ratio", par_value);
else else
gst_structure_set (structure, "pixel-aspect-ratio", GST_TYPE_FRACTION, gst_structure_set (structure, "pixel-aspect-ratio", GST_TYPE_FRACTION,
1, 1, NULL); 1, 1, NULL);
gst_caps_merge_structure (newcaps, gst_structure_copy (structure)); gst_caps_merge_structure (newcaps, gst_structure_copy (structure));
GST_DEBUG ("new caps %" GST_PTR_FORMAT, newcaps); GST_DEBUG ("new caps %" GST_PTR_FORMAT, newcaps);
return newcaps; return newcaps;
} }
/* from gst-plugins-base "videoscale" code */ /* from gst-plugins-base "videoscale" code */
static void static void
gst_gl_upload_fixate_caps (GstBaseTransform* base, GstPadDirection direction, gst_gl_upload_fixate_caps (GstBaseTransform * base, GstPadDirection direction,
GstCaps* caps, GstCaps* othercaps) GstCaps * caps, GstCaps * othercaps)
{ {
GstStructure *ins, *outs; GstStructure *ins, *outs;
const GValue *from_par, *to_par; const GValue *from_par, *to_par;
g_return_if_fail (gst_caps_is_fixed (caps)); g_return_if_fail (gst_caps_is_fixed (caps));
GST_DEBUG_OBJECT (base, "trying to fixate othercaps %" GST_PTR_FORMAT GST_DEBUG_OBJECT (base, "trying to fixate othercaps %" GST_PTR_FORMAT
" based on caps %" GST_PTR_FORMAT, othercaps, caps); " based on caps %" GST_PTR_FORMAT, othercaps, caps);
ins = gst_caps_get_structure (caps, 0); ins = gst_caps_get_structure (caps, 0);
outs = gst_caps_get_structure (othercaps, 0); outs = gst_caps_get_structure (othercaps, 0);
from_par = gst_structure_get_value (ins, "pixel-aspect-ratio"); from_par = gst_structure_get_value (ins, "pixel-aspect-ratio");
to_par = gst_structure_get_value (outs, "pixel-aspect-ratio"); to_par = gst_structure_get_value (outs, "pixel-aspect-ratio");
//we have both PAR but they might not be fixated //we have both PAR but they might not be fixated
if (from_par && to_par) if (from_par && to_par) {
{ gint from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d;
gint from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d;
gint count = 0, w = 0, h = 0; gint count = 0, w = 0, h = 0;
guint num, den; guint num, den;
//from_par should be fixed //from_par should be fixed
g_return_if_fail (gst_value_is_fixed (from_par)); g_return_if_fail (gst_value_is_fixed (from_par));
from_par_n = gst_value_get_fraction_numerator (from_par); from_par_n = gst_value_get_fraction_numerator (from_par);
from_par_d = gst_value_get_fraction_denominator (from_par); from_par_d = gst_value_get_fraction_denominator (from_par);
//fixate the out PAR //fixate the out PAR
if (!gst_value_is_fixed (to_par)) if (!gst_value_is_fixed (to_par)) {
{ GST_DEBUG_OBJECT (base, "fixating to_par to %dx%d", from_par_n,
GST_DEBUG_OBJECT (base, "fixating to_par to %dx%d", from_par_n, from_par_d);
from_par_d); gst_structure_fixate_field_nearest_fraction (outs, "pixel-aspect-ratio",
gst_structure_fixate_field_nearest_fraction (outs, "pixel-aspect-ratio", from_par_n, from_par_d);
from_par_n, from_par_d);
}
to_par_n = gst_value_get_fraction_numerator (to_par);
to_par_d = gst_value_get_fraction_denominator (to_par);
//f both width and height are already fixed, we can't do anything
//about it anymore
if (gst_structure_get_int (outs, "width", &w))
++count;
if (gst_structure_get_int (outs, "height", &h))
++count;
if (count == 2)
{
GST_DEBUG_OBJECT (base, "dimensions already set to %dx%d, not fixating",
w, h);
return;
}
gst_structure_get_int (ins, "width", &from_w);
gst_structure_get_int (ins, "height", &from_h);
if (!gst_video_calculate_display_ratio (&num, &den, from_w, from_h,
from_par_n, from_par_d, to_par_n, to_par_d))
{
GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
("Error calculating the output scaled size - integer overflow"));
return;
}
GST_DEBUG_OBJECT (base,
"scaling input with %dx%d and PAR %d/%d to output PAR %d/%d",
from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d);
GST_DEBUG_OBJECT (base, "resulting output should respect ratio of %d/%d",
num, den);
//now find a width x height that respects this display ratio.
//prefer those that have one of w/h the same as the incoming video
//using wd / hd = num / den
//if one of the output width or height is fixed, we work from there
if (h)
{
GST_DEBUG_OBJECT (base, "height is fixed,scaling width");
w = (guint) gst_util_uint64_scale_int (h, num, den);
}
else if (w)
{
GST_DEBUG_OBJECT (base, "width is fixed, scaling height");
h = (guint) gst_util_uint64_scale_int (w, den, num);
}
else
{
//none of width or height is fixed, figure out both of them based only on
//the input width and height
//check hd / den is an integer scale factor, and scale wd with the PAR
if (from_h % den == 0)
{
GST_DEBUG_OBJECT (base, "keeping video height");
h = from_h;
w = (guint) gst_util_uint64_scale_int (h, num, den);
}
else if (from_w % num == 0)
{
GST_DEBUG_OBJECT (base, "keeping video width");
w = from_w;
h = (guint) gst_util_uint64_scale_int (w, den, num);
}
else
{
GST_DEBUG_OBJECT (base, "approximating but keeping video height");
h = from_h;
w = (guint) gst_util_uint64_scale_int (h, num, den);
}
}
GST_DEBUG_OBJECT (base, "scaling to %dx%d", w, h);
//now fixate
gst_structure_fixate_field_nearest_int (outs, "width", w);
gst_structure_fixate_field_nearest_int (outs, "height", h);
}
else
{
gint width, height;
if (gst_structure_get_int (ins, "width", &width))
{
if (gst_structure_has_field (outs, "width"))
gst_structure_fixate_field_nearest_int (outs, "width", width);
}
if (gst_structure_get_int (ins, "height", &height)) {
if (gst_structure_has_field (outs, "height")) {
gst_structure_fixate_field_nearest_int (outs, "height", height);
}
}
} }
GST_DEBUG_OBJECT (base, "fixated othercaps to %" GST_PTR_FORMAT, othercaps); to_par_n = gst_value_get_fraction_numerator (to_par);
to_par_d = gst_value_get_fraction_denominator (to_par);
//f both width and height are already fixed, we can't do anything
//about it anymore
if (gst_structure_get_int (outs, "width", &w))
++count;
if (gst_structure_get_int (outs, "height", &h))
++count;
if (count == 2) {
GST_DEBUG_OBJECT (base, "dimensions already set to %dx%d, not fixating",
w, h);
return;
}
gst_structure_get_int (ins, "width", &from_w);
gst_structure_get_int (ins, "height", &from_h);
if (!gst_video_calculate_display_ratio (&num, &den, from_w, from_h,
from_par_n, from_par_d, to_par_n, to_par_d)) {
GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
("Error calculating the output scaled size - integer overflow"));
return;
}
GST_DEBUG_OBJECT (base,
"scaling input with %dx%d and PAR %d/%d to output PAR %d/%d",
from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d);
GST_DEBUG_OBJECT (base, "resulting output should respect ratio of %d/%d",
num, den);
//now find a width x height that respects this display ratio.
//prefer those that have one of w/h the same as the incoming video
//using wd / hd = num / den
//if one of the output width or height is fixed, we work from there
if (h) {
GST_DEBUG_OBJECT (base, "height is fixed,scaling width");
w = (guint) gst_util_uint64_scale_int (h, num, den);
} else if (w) {
GST_DEBUG_OBJECT (base, "width is fixed, scaling height");
h = (guint) gst_util_uint64_scale_int (w, den, num);
} else {
//none of width or height is fixed, figure out both of them based only on
//the input width and height
//check hd / den is an integer scale factor, and scale wd with the PAR
if (from_h % den == 0) {
GST_DEBUG_OBJECT (base, "keeping video height");
h = from_h;
w = (guint) gst_util_uint64_scale_int (h, num, den);
} else if (from_w % num == 0) {
GST_DEBUG_OBJECT (base, "keeping video width");
w = from_w;
h = (guint) gst_util_uint64_scale_int (w, den, num);
} else {
GST_DEBUG_OBJECT (base, "approximating but keeping video height");
h = from_h;
w = (guint) gst_util_uint64_scale_int (h, num, den);
}
}
GST_DEBUG_OBJECT (base, "scaling to %dx%d", w, h);
//now fixate
gst_structure_fixate_field_nearest_int (outs, "width", w);
gst_structure_fixate_field_nearest_int (outs, "height", h);
} else {
gint width, height;
if (gst_structure_get_int (ins, "width", &width)) {
if (gst_structure_has_field (outs, "width"))
gst_structure_fixate_field_nearest_int (outs, "width", width);
}
if (gst_structure_get_int (ins, "height", &height)) {
if (gst_structure_has_field (outs, "height")) {
gst_structure_fixate_field_nearest_int (outs, "height", height);
}
}
}
GST_DEBUG_OBJECT (base, "fixated othercaps to %" GST_PTR_FORMAT, othercaps);
} }
static gboolean static gboolean
gst_gl_upload_set_caps (GstBaseTransform* bt, GstCaps* incaps, gst_gl_upload_set_caps (GstBaseTransform * bt, GstCaps * incaps,
GstCaps* outcaps) GstCaps * outcaps)
{ {
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;
GST_DEBUG ("called with %" GST_PTR_FORMAT, incaps);
ret = gst_video_format_parse_caps (outcaps, &video_format,
&upload->gl_width, &upload->gl_height);
ret |= gst_video_format_parse_caps (incaps, &upload->video_format,
&upload->video_width, &upload->video_height);
if (!ret) {
GST_DEBUG ("caps connot be parsed");
return FALSE;
}
//we have video and gl size, we can now init OpenGL stuffs
upload->display = gst_gl_display_new ();
//init unvisible opengl context
gst_gl_display_create_context (upload->display,
upload->gl_width, upload->gl_height);
//init colorspace conversion if needed
gst_gl_display_init_upload (upload->display, upload->video_format,
upload->gl_width, upload->gl_height,
upload->video_width, upload->video_height);
return ret;
}
static gboolean
gst_gl_upload_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
guint * size)
{
gboolean ret = FALSE;
GstStructure *structure = NULL;
gint width = 0;
gint height = 0;
structure = gst_caps_get_structure (caps, 0);
if (gst_structure_has_name (structure, "video/x-raw-gl")) {
ret = gst_gl_buffer_parse_caps (caps, &width, &height);
if (ret)
*size = gst_gl_buffer_get_size (width, height);
} else {
GstVideoFormat video_format = GST_VIDEO_FORMAT_UNKNOWN; GstVideoFormat video_format = GST_VIDEO_FORMAT_UNKNOWN;
GST_DEBUG ("called with %" GST_PTR_FORMAT, incaps); ret = gst_video_format_parse_caps (caps, &video_format, &width, &height);
if (ret)
*size = gst_video_format_get_size (video_format, width, height);
}
ret = gst_video_format_parse_caps (outcaps, &video_format, return TRUE;
&upload->gl_width, &upload->gl_height);
ret |= gst_video_format_parse_caps (incaps, &upload->video_format,
&upload->video_width, &upload->video_height);
if (!ret)
{
GST_DEBUG ("caps connot be parsed");
return FALSE;
}
//we have video and gl size, we can now init OpenGL stuffs
upload->display = gst_gl_display_new ();
//init unvisible opengl context
gst_gl_display_create_context (upload->display,
upload->gl_width, upload->gl_height);
//init colorspace conversion if needed
gst_gl_display_init_upload (upload->display, upload->video_format,
upload->gl_width, upload->gl_height,
upload->video_width, upload->video_height);
return ret;
}
static gboolean
gst_gl_upload_get_unit_size (GstBaseTransform* trans, GstCaps* caps,
guint* size)
{
gboolean ret = FALSE;
GstStructure* structure = NULL;
gint width = 0;
gint height = 0;
structure = gst_caps_get_structure (caps, 0);
if (gst_structure_has_name (structure, "video/x-raw-gl"))
{
ret = gst_gl_buffer_parse_caps (caps, &width, &height);
if (ret)
*size = gst_gl_buffer_get_size (width, height);
}
else
{
GstVideoFormat video_format = GST_VIDEO_FORMAT_UNKNOWN;
ret = gst_video_format_parse_caps (caps, &video_format, &width, &height);
if (ret)
*size = gst_video_format_get_size (video_format, width, height);
}
return TRUE;
} }
static GstFlowReturn 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 = GST_GL_UPLOAD (trans); GstGLUpload *upload = GST_GL_UPLOAD (trans);
//blocking call, request a texture and attach it to the upload FBO //blocking call, request a texture and attach it to the upload FBO
GstGLBuffer* gl_outbuf = gst_gl_buffer_new (upload->display, GstGLBuffer *gl_outbuf = gst_gl_buffer_new (upload->display,
upload->gl_width, upload->gl_height); upload->gl_width, upload->gl_height);
*buf = GST_BUFFER (gl_outbuf); *buf = GST_BUFFER (gl_outbuf);
gst_buffer_set_caps (*buf, caps); gst_buffer_set_caps (*buf, caps);
if (gl_outbuf->texture) if (gl_outbuf->texture)
return GST_FLOW_OK; return GST_FLOW_OK;
else else
return GST_FLOW_UNEXPECTED; return GST_FLOW_UNEXPECTED;
} }
static GstFlowReturn static GstFlowReturn
gst_gl_upload_transform (GstBaseTransform* trans, GstBuffer* inbuf, gst_gl_upload_transform (GstBaseTransform * trans, GstBuffer * inbuf,
GstBuffer* outbuf) GstBuffer * outbuf)
{ {
GstGLUpload* upload = GST_GL_UPLOAD (trans); GstGLUpload *upload = GST_GL_UPLOAD (trans);
GstGLBuffer* gl_outbuf = GST_GL_BUFFER (outbuf); GstGLBuffer *gl_outbuf = GST_GL_BUFFER (outbuf);
GST_DEBUG ("Upload %p size %d", GST_DEBUG ("Upload %p size %d",
GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf)); GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf));
//blocking call. //blocking call.
//Depending on the colorspace, video is upload into several textures. //Depending on the colorspace, video is upload into several textures.
//However, there is only one output texture. The one attached //However, there is only one output texture. The one attached
//to the upload FBO. //to the upload FBO.
if (gst_gl_display_do_upload (upload->display, gl_outbuf->texture, if (gst_gl_display_do_upload (upload->display, gl_outbuf->texture,
upload->video_width, upload->video_height, GST_BUFFER_DATA (inbuf))) upload->video_width, upload->video_height, GST_BUFFER_DATA (inbuf)))
return GST_FLOW_OK; return GST_FLOW_OK;
else else
return GST_FLOW_UNEXPECTED; return GST_FLOW_UNEXPECTED;
} }

View file

@ -91,30 +91,30 @@ plugin_init (GstPlugin * plugin)
return FALSE; return FALSE;
} }
if (!gst_element_register (plugin, "gloverlay", if (!gst_element_register (plugin, "gloverlay",
GST_RANK_NONE, gst_gl_overlay_get_type())) { GST_RANK_NONE, gst_gl_overlay_get_type ())) {
return FALSE; return FALSE;
} }
if (!gst_element_register (plugin, "gldifferencematte", if (!gst_element_register (plugin, "gldifferencematte",
GST_RANK_NONE, gst_gl_differencematte_get_type())) { GST_RANK_NONE, gst_gl_differencematte_get_type ())) {
return FALSE; return FALSE;
} }
if (!gst_element_register (plugin, "glbumper", if (!gst_element_register (plugin, "glbumper",
GST_RANK_NONE, gst_gl_bumper_get_type())) { GST_RANK_NONE, gst_gl_bumper_get_type ())) {
return FALSE; return FALSE;
} }
if (!gst_element_register (plugin, "gleffects", if (!gst_element_register (plugin, "gleffects",
GST_RANK_NONE, gst_gl_effects_get_type())) { GST_RANK_NONE, gst_gl_effects_get_type ())) {
return FALSE; return FALSE;
} }
if (!gst_element_register (plugin, "glfilterblur", if (!gst_element_register (plugin, "glfilterblur",
GST_RANK_NONE, gst_gl_filterblur_get_type())) { GST_RANK_NONE, gst_gl_filterblur_get_type ())) {
return FALSE; return FALSE;
} }
if (!gst_element_register (plugin, "glfiltersobel", if (!gst_element_register (plugin, "glfiltersobel",
GST_RANK_NONE, gst_gl_filtersobel_get_type())) { GST_RANK_NONE, gst_gl_filtersobel_get_type ())) {
return FALSE; return FALSE;
} }

View file

@ -31,7 +31,8 @@
#define W 320 #define W 320
#define H 240 #define H 240
struct GstGLClutterActor_ { struct GstGLClutterActor_
{
Window win; Window win;
Window root; Window root;
ClutterActor *texture; ClutterActor *texture;
@ -41,44 +42,45 @@ struct GstGLClutterActor_ {
typedef struct GstGLClutterActor_ GstGLClutterActor; typedef struct GstGLClutterActor_ GstGLClutterActor;
static gboolean static gboolean
create_actor (GstGLClutterActor *actor) { create_actor (GstGLClutterActor * actor)
{
ClutterKnot knot[2]; ClutterKnot knot[2];
ClutterTimeline *timeline; ClutterTimeline *timeline;
ClutterEffectTemplate *effect_template; ClutterEffectTemplate *effect_template;
actor->texture = g_object_new (CLUTTER_GLX_TYPE_TEXTURE_PIXMAP, actor->texture = g_object_new (CLUTTER_GLX_TYPE_TEXTURE_PIXMAP,
"window", actor->win, "window", actor->win, "automatic-updates", TRUE, NULL);
"automatic-updates", TRUE, NULL); clutter_container_add_actor (CLUTTER_CONTAINER (actor->stage),
clutter_container_add_actor (CLUTTER_CONTAINER (actor->stage), actor->texture); actor->texture);
clutter_actor_set_scale (actor->texture, 0.2 , 0.2); clutter_actor_set_scale (actor->texture, 0.2, 0.2);
clutter_actor_set_opacity (actor->texture, 0); clutter_actor_set_opacity (actor->texture, 0);
clutter_actor_show (actor->texture); clutter_actor_show (actor->texture);
timeline =
clutter_timeline_new (120 /* frames */ , 50 /* frames per second. */ );
clutter_timeline_set_loop (timeline, TRUE);
clutter_timeline_start (timeline);
timeline = clutter_timeline_new(120 /* frames */, 50 /* frames per second. */);
clutter_timeline_set_loop(timeline, TRUE);
clutter_timeline_start(timeline);
/* Instead of our custom callback, /* Instead of our custom callback,
* we could use a standard callback. For instance, CLUTTER_ALPHA_SINE_INC. * we could use a standard callback. For instance, CLUTTER_ALPHA_SINE_INC.
*/ */
effect_template = effect_template =
clutter_effect_template_new (timeline, CLUTTER_ALPHA_SINE_INC); clutter_effect_template_new (timeline, CLUTTER_ALPHA_SINE_INC);
knot[0].x = -10; knot[0].x = -10;
knot[0].y = -10; knot[0].y = -10;
knot[1].x= 160; knot[1].x = 160;
knot[1].y= 120; knot[1].y = 120;
// Move the actor along the path: // Move the actor along the path:
clutter_effect_path (effect_template, actor->texture, knot, clutter_effect_path (effect_template, actor->texture, knot,
sizeof(knot) / sizeof(ClutterKnot), NULL, NULL); sizeof (knot) / sizeof (ClutterKnot), NULL, NULL);
clutter_effect_scale (effect_template, actor->texture, 1.0, 1.0, NULL, NULL); clutter_effect_scale (effect_template, actor->texture, 1.0, 1.0, NULL, NULL);
clutter_effect_rotate (effect_template, actor->texture, clutter_effect_rotate (effect_template, actor->texture,
CLUTTER_Z_AXIS, 360.0, W/2.0, H/2.0, 0.0, CLUTTER_Z_AXIS, 360.0, W / 2.0, H / 2.0, 0.0,
CLUTTER_ROTATE_CW, NULL, NULL); CLUTTER_ROTATE_CW, NULL, NULL);
clutter_effect_rotate (effect_template, actor->texture, clutter_effect_rotate (effect_template, actor->texture,
CLUTTER_X_AXIS, 360.0, 0.0, W/4.0, 0.0, CLUTTER_X_AXIS, 360.0, 0.0, W / 4.0, 0.0, CLUTTER_ROTATE_CW, NULL, NULL);
CLUTTER_ROTATE_CW, NULL, NULL);
// Also change the actor's opacity while moving it along the path: // Also change the actor's opacity while moving it along the path:
// (You would probably want to use a different ClutterEffectTemplate, // (You would probably want to use a different ClutterEffectTemplate,
@ -88,7 +90,7 @@ create_actor (GstGLClutterActor *actor) {
g_object_unref (effect_template); g_object_unref (effect_template);
g_object_unref (timeline); g_object_unref (timeline);
return FALSE; return FALSE;
} }
static GstBusSyncReply static GstBusSyncReply
@ -98,15 +100,16 @@ create_window (GstBus * bus, GstMessage * message, gpointer data)
// ignore anything but 'prepare-xwindow-id' element messages // ignore anything but 'prepare-xwindow-id' element messages
if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT) if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
return GST_BUS_PASS; return GST_BUS_PASS;
if (!gst_structure_has_name (message->structure, "prepare-xwindow-id")) if (!gst_structure_has_name (message->structure, "prepare-xwindow-id"))
return GST_BUS_PASS; return GST_BUS_PASS;
g_debug ("CREATING WINDOW"); g_debug ("CREATING WINDOW");
gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (GST_MESSAGE_SRC (message)), actor->win); gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (GST_MESSAGE_SRC (message)),
actor->win);
clutter_threads_add_idle ((GSourceFunc) create_actor, actor); clutter_threads_add_idle ((GSourceFunc) create_actor, actor);
gst_message_unref (message); gst_message_unref (message);
return GST_BUS_DROP; return GST_BUS_DROP;
} }
@ -114,8 +117,8 @@ create_window (GstBus * bus, GstMessage * message, gpointer data)
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
GstPipeline *pipeline; GstPipeline *pipeline;
GstBus *bus; GstBus *bus;
ClutterActor *stage; ClutterActor *stage;
GstGLClutterActor *actor; GstGLClutterActor *actor;
Display *disp; Display *disp;
@ -125,10 +128,10 @@ main (int argc, char *argv[])
gst_init (&argc, &argv); gst_init (&argc, &argv);
disp = clutter_x11_get_default_display (); disp = clutter_x11_get_default_display ();
if(!clutter_x11_has_composite_extension ()) { if (!clutter_x11_has_composite_extension ()) {
g_error ("XComposite extension missing"); g_error ("XComposite extension missing");
} }
stage = clutter_stage_get_default (); stage = clutter_stage_get_default ();
// clutter_actor_set_size (CLUTTER_ACTOR (stage), W*3+2, H); // clutter_actor_set_size (CLUTTER_ACTOR (stage), W*3+2, H);
@ -142,8 +145,10 @@ main (int argc, char *argv[])
XMapRaised (disp, actor->win); XMapRaised (disp, actor->win);
XSync (disp, FALSE); XSync (disp, FALSE);
pipeline = GST_PIPELINE (gst_parse_launch ("videotestsrc ! video/x-raw-rgb, width=320, height=240, framerate=(fraction)30/1 ! " pipeline =
"glupload ! gleffects effect=twirl ! glimagesink", NULL)); GST_PIPELINE (gst_parse_launch
("videotestsrc ! video/x-raw-rgb, width=320, height=240, framerate=(fraction)30/1 ! "
"glupload ! gleffects effect=twirl ! glimagesink", NULL));
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
@ -153,10 +158,10 @@ main (int argc, char *argv[])
clutter_actor_show_all (stage); clutter_actor_show_all (stage);
clutter_main(); clutter_main ();
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
g_object_unref (pipeline); g_object_unref (pipeline);
return 0; return 0;
} }

View file

@ -32,7 +32,8 @@
#define W 160 #define W 160
#define H 120 #define H 120
struct GstGLClutterActor_ { struct GstGLClutterActor_
{
Window win; Window win;
Window root; Window root;
ClutterActor *texture; ClutterActor *texture;
@ -42,24 +43,25 @@ struct GstGLClutterActor_ {
typedef struct GstGLClutterActor_ GstGLClutterActor; typedef struct GstGLClutterActor_ GstGLClutterActor;
static gboolean static gboolean
create_actor (GstGLClutterActor *actor) { create_actor (GstGLClutterActor * actor)
{
static gint xpos = 0; static gint xpos = 0;
static gint ypos = 0; static gint ypos = 0;
Display *disp; Display *disp;
actor->texture = g_object_new (CLUTTER_GLX_TYPE_TEXTURE_PIXMAP, actor->texture = g_object_new (CLUTTER_GLX_TYPE_TEXTURE_PIXMAP,
"window", actor->win, "window", actor->win, "automatic-updates", TRUE, NULL);
"automatic-updates", TRUE, NULL); clutter_container_add_actor (CLUTTER_CONTAINER (actor->stage),
clutter_container_add_actor (CLUTTER_CONTAINER (actor->stage), actor->texture); actor->texture);
clutter_actor_set_position (actor->texture, xpos, ypos); clutter_actor_set_position (actor->texture, xpos, ypos);
disp = clutter_x11_get_default_display (); disp = clutter_x11_get_default_display ();
XMoveResizeWindow (disp, actor->win, xpos, ypos, W, H); XMoveResizeWindow (disp, actor->win, xpos, ypos, W, H);
if (xpos > (COLS-1)*W) { if (xpos > (COLS - 1) * W) {
xpos = 0; xpos = 0;
ypos += H+1; ypos += H + 1;
} else } else
xpos += W+1; xpos += W + 1;
clutter_actor_show (actor->texture); clutter_actor_show (actor->texture);
return FALSE; return FALSE;
@ -79,14 +81,14 @@ create_window (GstBus * bus, GstMessage * message, gpointer data)
return GST_BUS_PASS; return GST_BUS_PASS;
if (!mutex) if (!mutex)
mutex = g_mutex_new (); mutex = g_mutex_new ();
g_mutex_lock (mutex); g_mutex_lock (mutex);
if (count < N_ACTORS) { if (count < N_ACTORS) {
g_message ("adding actor %d", count); g_message ("adding actor %d", count);
gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (GST_MESSAGE_SRC (message)), gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (GST_MESSAGE_SRC (message)),
actor[count]->win); actor[count]->win);
clutter_threads_add_idle ((GSourceFunc) create_actor, actor[count]); clutter_threads_add_idle ((GSourceFunc) create_actor, actor[count]);
count++; count++;
} }
@ -99,7 +101,7 @@ create_window (GstBus * bus, GstMessage * message, gpointer data)
#if 0 #if 0
void void
apply_fx (GstElement *element, const gchar *fx) apply_fx (GstElement * element, const gchar * fx)
{ {
GEnumClass *p_class; GEnumClass *p_class;
@ -120,12 +122,13 @@ apply_fx (GstElement *element, const gchar *fx)
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
GstPipeline *pipeline; GstPipeline *pipeline;
GstBus *bus; GstBus *bus;
GstElement *srcbin; GstElement *srcbin;
GstElement *tee; GstElement *tee;
GstElement *queue[N_ACTORS], *upload[N_ACTORS], *effect[N_ACTORS], *sink[N_ACTORS]; GstElement *queue[N_ACTORS], *upload[N_ACTORS], *effect[N_ACTORS],
*sink[N_ACTORS];
ClutterActor *stage; ClutterActor *stage;
GstGLClutterActor *actor[N_ACTORS]; GstGLClutterActor *actor[N_ACTORS];
@ -139,18 +142,17 @@ main (int argc, char *argv[])
gst_init (&argc, &argv); gst_init (&argc, &argv);
disp = clutter_x11_get_default_display (); disp = clutter_x11_get_default_display ();
if(!clutter_x11_has_composite_extension ()) { if (!clutter_x11_has_composite_extension ()) {
g_error ("XComposite extension missing"); g_error ("XComposite extension missing");
} }
stage = clutter_stage_get_default (); stage = clutter_stage_get_default ();
clutter_actor_set_size (CLUTTER_ACTOR (stage), clutter_actor_set_size (CLUTTER_ACTOR (stage),
W*COLS + (COLS-1), W * COLS + (COLS - 1), H * ROWS + (ROWS - 1));
H*ROWS + (ROWS-1));
stage_win = clutter_x11_get_stage_window (CLUTTER_STAGE (stage)); stage_win = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
for (i=0; i<N_ACTORS; i++) { for (i = 0; i < N_ACTORS; i++) {
actor[i] = g_new0 (GstGLClutterActor, 1); actor[i] = g_new0 (GstGLClutterActor, 1);
actor[i]->stage = stage; actor[i]->stage = stage;
actor[i]->win = XCreateSimpleWindow (disp, stage_win, 0, 0, W, H, 0, 0, 0); actor[i]->win = XCreateSimpleWindow (disp, stage_win, 0, 0, W, H, 0, 0, 0);
@ -166,38 +168,41 @@ main (int argc, char *argv[])
"identity", W, H); "identity", W, H);
*/ */
desc = g_strdup_printf ("videotestsrc ! " desc = g_strdup_printf ("videotestsrc ! "
"video/x-raw-rgb, width=%d, height=%d !" "video/x-raw-rgb, width=%d, height=%d !" "identity", W, H);
"identity", W, H);
pipeline = GST_PIPELINE (gst_pipeline_new (NULL)); pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
srcbin = gst_parse_bin_from_description (desc, TRUE, NULL); srcbin = gst_parse_bin_from_description (desc, TRUE, NULL);
if (!srcbin) g_error ("Source bin creation failed"); if (!srcbin)
g_error ("Source bin creation failed");
tee = gst_element_factory_make ("tee", NULL); tee = gst_element_factory_make ("tee", NULL);
gst_bin_add_many (GST_BIN (pipeline), srcbin, tee, NULL); gst_bin_add_many (GST_BIN (pipeline), srcbin, tee, NULL);
for (i=0; i<N_ACTORS; i++) { for (i = 0; i < N_ACTORS; i++) {
queue[i] = gst_element_factory_make ("queue", NULL); queue[i] = gst_element_factory_make ("queue", NULL);
upload[i] = gst_element_factory_make ("glupload", NULL); upload[i] = gst_element_factory_make ("glupload", NULL);
effect[i] = gst_element_factory_make ("gleffects", NULL); effect[i] = gst_element_factory_make ("gleffects", NULL);
sink[i] = gst_element_factory_make ("glimagesink", NULL); sink[i] = gst_element_factory_make ("glimagesink", NULL);
gst_bin_add_many (GST_BIN (pipeline), gst_bin_add_many (GST_BIN (pipeline),
queue[i], upload[i], effect[i], sink[i], NULL); queue[i], upload[i], effect[i], sink[i], NULL);
} }
gst_element_link_many (srcbin, tee, NULL); gst_element_link_many (srcbin, tee, NULL);
for (i=0; i<N_ACTORS; i++) { for (i = 0; i < N_ACTORS; i++) {
ok |= gst_element_link_many (tee, queue[i], upload[i], effect[i], sink[i], NULL); ok |=
gst_element_link_many (tee, queue[i], upload[i], effect[i], sink[i],
NULL);
} }
if (!ok) if (!ok)
g_error ("Failed to link one or more elements"); g_error ("Failed to link one or more elements");
for (i=0; i<N_ACTORS; i++) { for (i = 0; i < N_ACTORS; i++) {
g_message ("setting effect %d on %s", i+1, gst_element_get_name (effect[i])); g_message ("setting effect %d on %s", i + 1,
g_object_set (G_OBJECT (effect[i]), "effect", i+1, NULL); gst_element_get_name (effect[i]));
g_object_set (G_OBJECT (effect[i]), "effect", i + 1, NULL);
} }
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
@ -208,7 +213,7 @@ main (int argc, char *argv[])
clutter_actor_show_all (stage); clutter_actor_show_all (stage);
clutter_main(); clutter_main ();
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
g_object_unref (pipeline); g_object_unref (pipeline);

View file

@ -17,10 +17,11 @@ static gboolean
expose_cb (GtkWidget * widget, GdkEventExpose * event, gpointer data) expose_cb (GtkWidget * widget, GdkEventExpose * event, gpointer data)
{ {
GstXOverlay *overlay = GstXOverlay *overlay =
GST_X_OVERLAY (gst_bin_get_by_interface (GST_BIN (data), GST_X_OVERLAY (gst_bin_get_by_interface (GST_BIN (data),
GST_TYPE_X_OVERLAY)); GST_TYPE_X_OVERLAY));
#ifdef WIN32 #ifdef WIN32
gst_x_overlay_set_xwindow_id (overlay, (gulong)GDK_WINDOW_HWND(widget->window)); gst_x_overlay_set_xwindow_id (overlay,
(gulong) GDK_WINDOW_HWND (widget->window));
#else #else
gst_x_overlay_set_xwindow_id (overlay, GDK_WINDOW_XWINDOW (widget->window)); gst_x_overlay_set_xwindow_id (overlay, GDK_WINDOW_XWINDOW (widget->window));
#endif #endif
@ -29,7 +30,7 @@ expose_cb (GtkWidget * widget, GdkEventExpose * event, gpointer data)
} }
static void static void
destroy_cb (GtkWidget *widget, GdkEvent *event, GstElement *pipeline) destroy_cb (GtkWidget * widget, GdkEvent * event, GstElement * pipeline)
{ {
g_message ("destroy callback"); g_message ("destroy callback");
@ -111,9 +112,10 @@ main (gint argc, gchar * argv[])
GOptionContext *context; GOptionContext *context;
GOptionEntry options[] = { GOptionEntry options[] = {
{ "source-bin", 's', 0, G_OPTION_ARG_STRING_ARRAY, &source_desc_array, {"source-bin", 's', 0, G_OPTION_ARG_STRING_ARRAY, &source_desc_array,
"Use a custom source bin description (gst-launch style)", NULL }, "Use a custom source bin description (gst-launch style)", NULL}
{ NULL } ,
{NULL}
}; };
g_thread_init (NULL); g_thread_init (NULL);
@ -127,20 +129,23 @@ main (gint argc, gchar * argv[])
return -1; return -1;
} }
g_option_context_free (context); g_option_context_free (context);
if (source_desc_array != NULL) { if (source_desc_array != NULL) {
source_desc = g_strjoinv (" ", source_desc_array); source_desc = g_strjoinv (" ", source_desc_array);
g_strfreev (source_desc_array); g_strfreev (source_desc_array);
} }
if (source_desc == NULL) { if (source_desc == NULL) {
source_desc = g_strdup ("videotestsrc ! video/x-raw-rgb, width=352, height=288 ! identity"); source_desc =
g_strdup
("videotestsrc ! video/x-raw-rgb, width=352, height=288 ! identity");
} }
sourcebin = gst_parse_bin_from_description (g_strdup (source_desc), TRUE, &error); sourcebin =
gst_parse_bin_from_description (g_strdup (source_desc), TRUE, &error);
g_free (source_desc); g_free (source_desc);
if (error) { if (error) {
g_print ("Error while parsing source bin description: %s\n", g_print ("Error while parsing source bin description: %s\n",
GST_STR_NULL (error->message)); GST_STR_NULL (error->message));
return -1; return -1;
} }
@ -163,9 +168,9 @@ main (gint argc, gchar * argv[])
} }
g_signal_connect (G_OBJECT (window), "delete-event", g_signal_connect (G_OBJECT (window), "delete-event",
G_CALLBACK (destroy_cb), pipeline); G_CALLBACK (destroy_cb), pipeline);
g_signal_connect (G_OBJECT (window), "destroy-event", g_signal_connect (G_OBJECT (window), "destroy-event",
G_CALLBACK (destroy_cb), pipeline); G_CALLBACK (destroy_cb), pipeline);
screen = gtk_drawing_area_new (); screen = gtk_drawing_area_new ();

View file

@ -23,38 +23,38 @@ struct _SourceData
}; };
typedef struct _SourceData SourceData; typedef struct _SourceData SourceData;
static GstBusSyncReply static GstBusSyncReply
create_window (GstBus *bus, GstMessage *message, GtkWidget *widget) create_window (GstBus * bus, GstMessage * message, GtkWidget * widget)
{ {
// ignore anything but 'prepare-xwindow-id' element messages // ignore anything but 'prepare-xwindow-id' element messages
if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT) if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
return GST_BUS_PASS; return GST_BUS_PASS;
if (!gst_structure_has_name (message->structure, "prepare-xwindow-id")) if (!gst_structure_has_name (message->structure, "prepare-xwindow-id"))
return GST_BUS_PASS; return GST_BUS_PASS;
#ifdef WIN32 #ifdef WIN32
gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (GST_MESSAGE_SRC (message)), gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (GST_MESSAGE_SRC (message)),
(gulong)GDK_WINDOW_HWND(widget->window)); (gulong) GDK_WINDOW_HWND (widget->window));
#else #else
gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (GST_MESSAGE_SRC (message)), gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (GST_MESSAGE_SRC (message)),
GDK_WINDOW_XWINDOW(widget->window)); GDK_WINDOW_XWINDOW (widget->window));
#endif #endif
gst_message_unref (message); gst_message_unref (message);
return GST_BUS_DROP; return GST_BUS_DROP;
} }
static gboolean static gboolean
expose_cb(GtkWidget *widget, GdkEventExpose *event, GstElement *videosink) expose_cb (GtkWidget * widget, GdkEventExpose * event, GstElement * videosink)
{ {
gst_x_overlay_expose (GST_X_OVERLAY (videosink)); gst_x_overlay_expose (GST_X_OVERLAY (videosink));
return FALSE; return FALSE;
} }
static void static void
destroy_cb (GtkWidget *widget, GdkEvent *event, GstElement *pipeline) destroy_cb (GtkWidget * widget, GdkEvent * event, GstElement * pipeline)
{ {
g_message ("destroy callback"); g_message ("destroy callback");
@ -112,9 +112,8 @@ set_location_delayed (gpointer data)
static void static void
on_drag_data_received (GtkWidget * widget, on_drag_data_received (GtkWidget * widget,
GdkDragContext * context, int x, int y, GdkDragContext * context, int x, int y,
GtkSelectionData * seldata, guint inf, guint time, GtkSelectionData * seldata, guint inf, guint time, gpointer data)
gpointer data)
{ {
GdkPixbufFormat *format; GdkPixbufFormat *format;
SourceData *userdata = g_new0 (SourceData, 1); SourceData *userdata = g_new0 (SourceData, 1);
@ -127,7 +126,7 @@ on_drag_data_received (GtkWidget * widget,
format = gdk_pixbuf_get_file_info (filename, NULL, NULL); format = gdk_pixbuf_get_file_info (filename, NULL, NULL);
g_return_if_fail (format); g_return_if_fail (format);
g_print ("received %s image: %s\n", filename, g_print ("received %s image: %s\n", filename,
gdk_pixbuf_format_get_name (format)); gdk_pixbuf_format_get_name (format));
userdata->nick = "location"; userdata->nick = "location";
userdata->value = g_strdup (filename); userdata->value = g_strdup (filename);
userdata->data = data; userdata->data = data;
@ -135,9 +134,9 @@ on_drag_data_received (GtkWidget * widget,
if (delay > 0) { if (delay > 0) {
g_print ("%d\n", delay); g_print ("%d\n", delay);
g_timeout_add_seconds (1, set_location_delayed, userdata); g_timeout_add_seconds (1, set_location_delayed, userdata);
} } else
else g_object_set (G_OBJECT (userdata->data), userdata->nick, userdata->value,
g_object_set (G_OBJECT (userdata->data), userdata->nick, userdata->value, NULL); NULL);
g_free (filename); g_free (filename);
} }
@ -163,11 +162,17 @@ main (gint argc, gchar * argv[])
GOptionContext *context; GOptionContext *context;
GOptionEntry options[] = { GOptionEntry options[] = {
{ "source-bin", 's', 0, G_OPTION_ARG_STRING_ARRAY, &source_desc_array, {"source-bin", 's', 0, G_OPTION_ARG_STRING_ARRAY, &source_desc_array,
"Use a custom source bin description (gst-launch style)", NULL }, "Use a custom source bin description (gst-launch style)", NULL}
{ "method", 'm', 0, G_OPTION_ARG_INT, &method, "1 for gstdifferencematte, 2 for gloverlay", "M" }, ,
{ "delay", 'd', 0, G_OPTION_ARG_INT, &delay, "Wait N seconds before to send the image to gstreamer (useful with differencematte)", "N" }, {"method", 'm', 0, G_OPTION_ARG_INT, &method,
{ NULL } "1 for gstdifferencematte, 2 for gloverlay", "M"}
,
{"delay", 'd', 0, G_OPTION_ARG_INT, &delay,
"Wait N seconds before to send the image to gstreamer (useful with differencematte)",
"N"}
,
{NULL}
}; };
g_thread_init (NULL); g_thread_init (NULL);
@ -181,20 +186,23 @@ main (gint argc, gchar * argv[])
return -1; return -1;
} }
g_option_context_free (context); g_option_context_free (context);
if (source_desc_array != NULL) { if (source_desc_array != NULL) {
source_desc = g_strjoinv (" ", source_desc_array); source_desc = g_strjoinv (" ", source_desc_array);
g_strfreev (source_desc_array); g_strfreev (source_desc_array);
} }
if (source_desc == NULL) { if (source_desc == NULL) {
source_desc = g_strdup ("videotestsrc ! video/x-raw-rgb, width=352, height=288 ! identity"); source_desc =
g_strdup
("videotestsrc ! video/x-raw-rgb, width=352, height=288 ! identity");
} }
sourcebin = gst_parse_bin_from_description (g_strdup (source_desc), TRUE, &error); sourcebin =
gst_parse_bin_from_description (g_strdup (source_desc), TRUE, &error);
g_free (source_desc); g_free (source_desc);
if (error) { if (error) {
g_print ("Error while parsing source bin description: %s\n", g_print ("Error while parsing source bin description: %s\n",
GST_STR_NULL (error->message)); GST_STR_NULL (error->message));
return -1; return -1;
} }
@ -221,9 +229,9 @@ main (gint argc, gchar * argv[])
} }
g_signal_connect (G_OBJECT (window), "delete-event", g_signal_connect (G_OBJECT (window), "delete-event",
G_CALLBACK (destroy_cb), pipeline); G_CALLBACK (destroy_cb), pipeline);
g_signal_connect (G_OBJECT (window), "destroy-event", g_signal_connect (G_OBJECT (window), "destroy-event",
G_CALLBACK (destroy_cb), pipeline); G_CALLBACK (destroy_cb), pipeline);
screen = gtk_drawing_area_new (); screen = gtk_drawing_area_new ();
@ -265,7 +273,7 @@ main (gint argc, gchar * argv[])
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_set_sync_handler (bus, (GstBusSyncHandler) create_window, screen); gst_bus_set_sync_handler (bus, (GstBusSyncHandler) create_window, screen);
gst_object_unref (bus); gst_object_unref (bus);
g_signal_connect(screen, "expose-event", G_CALLBACK(expose_cb), sink); g_signal_connect (screen, "expose-event", G_CALLBACK (expose_cb), sink);
gtk_drag_dest_set (screen, GTK_DEST_DEFAULT_ALL, NULL, 0, GDK_ACTION_COPY); gtk_drag_dest_set (screen, GTK_DEST_DEFAULT_ALL, NULL, 0, GDK_ACTION_COPY);
gtk_drag_dest_add_uri_targets (screen); gtk_drag_dest_add_uri_targets (screen);