mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-22 00:06:36 +00:00
[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:
parent
3fbd8bbd24
commit
d015d5862d
42 changed files with 5376 additions and 5424 deletions
|
@ -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
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)));"
|
||||||
"}";
|
"}";
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 ();
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue