diff --git a/gst-libs/gst/gl/gstgldisplay.c b/gst-libs/gst/gl/gstgldisplay.c index c3d433cfe1..6cf63235d0 100644 --- a/gst-libs/gst/gl/gstgldisplay.c +++ b/gst-libs/gst/gl/gstgldisplay.c @@ -1,6 +1,7 @@ /* * GStreamer * Copyright (C) 2008 Julien Isorce + * Copyright (C) 2008 Filippo Argiolas * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public diff --git a/gst-libs/gst/gl/gstgldisplay.h b/gst-libs/gst/gl/gstgldisplay.h index 1ff3dbb480..d4aa82d031 100644 --- a/gst-libs/gst/gl/gstgldisplay.h +++ b/gst-libs/gst/gl/gstgldisplay.h @@ -1,6 +1,7 @@ /* * GStreamer * Copyright (C) 2008 Julien Isorce + * Copyright (C) 2008 Filippo Argiolas * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public diff --git a/gst-libs/gst/gl/gstglfilter.c b/gst-libs/gst/gl/gstglfilter.c index 1d753af873..fa61126baf 100644 --- a/gst-libs/gst/gl/gstglfilter.c +++ b/gst-libs/gst/gl/gstglfilter.c @@ -1,6 +1,7 @@ /* * GStreamer * Copyright (C) 2008 Julien Isorce + * Copyright (C) 2008 Filippo Argiolas * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -29,45 +30,48 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); static GstStaticPadTemplate gst_gl_filter_src_pad_template = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_GL_VIDEO_CAPS) + GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_GL_VIDEO_CAPS) ); static GstStaticPadTemplate gst_gl_filter_sink_pad_template = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_GL_VIDEO_CAPS) + GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + 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_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, - const GValue * value, GParamSpec * pspec); + const GValue * value, GParamSpec * pspec); 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, - GstPadDirection direction, GstCaps* caps); + GstPadDirection direction, GstCaps* caps); static void gst_gl_filter_reset (GstGLFilter * filter); static gboolean gst_gl_filter_start (GstBaseTransform * bt); static gboolean gst_gl_filter_stop (GstBaseTransform * bt); 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, - GstBuffer * inbuf, GstBuffer * outbuf); + GstBuffer * inbuf, GstBuffer * outbuf); 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, - GstCaps * outcaps); + GstCaps * outcaps); static gboolean gst_gl_filter_do_transform (GstGLFilter * filter, - GstGLBuffer * inbuf, GstGLBuffer * outbuf); + GstGLBuffer * inbuf, GstGLBuffer * outbuf); +/* GstGLDisplayThreadFunc */ +static void gst_gl_filter_start_gl (GstGLDisplay *display, gpointer data); +static void gst_gl_filter_stop_gl (GstGLDisplay *display, gpointer data); static void @@ -76,244 +80,271 @@ gst_gl_filter_base_init (gpointer klass) GstElementClass *element_class = GST_ELEMENT_CLASS (klass); 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_static_pad_template_get (&gst_gl_filter_sink_pad_template)); + gst_static_pad_template_get (&gst_gl_filter_sink_pad_template)); } static void gst_gl_filter_class_init (GstGLFilterClass * klass) { - GObjectClass *gobject_class; + GObjectClass *gobject_class; - gobject_class = (GObjectClass *) klass; - gobject_class->set_property = gst_gl_filter_set_property; - gobject_class->get_property = gst_gl_filter_get_property; + gobject_class = (GObjectClass *) klass; + gobject_class->set_property = gst_gl_filter_set_property; + gobject_class->get_property = gst_gl_filter_get_property; - GST_BASE_TRANSFORM_CLASS (klass)->transform_caps = - gst_gl_filter_transform_caps; - 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)->stop = gst_gl_filter_stop; - 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)->prepare_output_buffer = - gst_gl_filter_prepare_output_buffer; + GST_BASE_TRANSFORM_CLASS (klass)->transform_caps = + gst_gl_filter_transform_caps; + 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)->stop = gst_gl_filter_stop; + 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)->prepare_output_buffer = + gst_gl_filter_prepare_output_buffer; - klass->set_caps = NULL; - klass->filter = NULL; - klass->onInitFBO = NULL; - klass->onReset = NULL; + klass->set_caps = NULL; + klass->filter = NULL; + klass->display_init_cb = NULL; + klass->display_reset_cb = NULL; + klass->onInitFBO = NULL; + klass->onReset = NULL; } static void gst_gl_filter_init (GstGLFilter * filter, GstGLFilterClass * klass) { - //gst_element_create_all_pads (GST_ELEMENT (filter)); + //gst_element_create_all_pads (GST_ELEMENT (filter)); - filter->sinkpad = gst_element_get_static_pad (GST_ELEMENT (filter), "sink"); - filter->srcpad = gst_element_get_static_pad (GST_ELEMENT (filter), "src"); + filter->sinkpad = gst_element_get_static_pad (GST_ELEMENT (filter), "sink"); + filter->srcpad = gst_element_get_static_pad (GST_ELEMENT (filter), "src"); - gst_gl_filter_reset (filter); + gst_gl_filter_reset (filter); } static void 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) - { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + switch (prop_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } static void 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) - { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + switch (prop_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } static void 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_class->onReset) - filter_class->onReset (filter); + if (filter_class->onReset) + filter_class->onReset (filter); - if (filter->display) - { - //blocking call, delete the FBO - gst_gl_display_del_fbo (filter->display, filter->fbo, - filter->depthbuffer); - g_object_unref (filter->display); - filter->display = NULL; + if (filter->display) + { + if (filter_class->display_reset_cb != NULL) { + gst_gl_display_thread_add (filter->display, gst_gl_filter_stop_gl, filter); } - filter->width = 0; - filter->height = 0; - filter->fbo = 0; - filter->depthbuffer = 0; + //blocking call, delete the FBO + gst_gl_display_del_fbo (filter->display, filter->fbo, + filter->depthbuffer); + g_object_unref (filter->display); + filter->display = NULL; + } + filter->width = 0; + filter->height = 0; + filter->fbo = 0; + filter->depthbuffer = 0; } static gboolean gst_gl_filter_start (GstBaseTransform* bt) { - return TRUE; + return TRUE; } static gboolean gst_gl_filter_stop (GstBaseTransform* bt) { - GstGLFilter *filter = GST_GL_FILTER (bt); + GstGLFilter *filter = GST_GL_FILTER (bt); - gst_gl_filter_reset (filter); + gst_gl_filter_reset (filter); - return TRUE; + return TRUE; +} + +static void +gst_gl_filter_start_gl (GstGLDisplay *display, gpointer data) +{ + GstGLFilter *filter = GST_GL_FILTER (data); + GstGLFilterClass *filter_class = GST_GL_FILTER_GET_CLASS (filter); + + filter_class->display_init_cb (filter); +} + +static void +gst_gl_filter_stop_gl (GstGLDisplay *display, gpointer data) +{ + GstGLFilter *filter = GST_GL_FILTER (data); + GstGLFilterClass *filter_class = GST_GL_FILTER_GET_CLASS (filter); + + filter_class->display_reset_cb (filter); } static GstCaps* gst_gl_filter_transform_caps (GstBaseTransform* bt, - GstPadDirection direction, GstCaps* caps) + GstPadDirection direction, GstCaps* caps) { - //GstGLFilter* filter = GST_GL_FILTER (bt); - GstStructure* structure = gst_caps_get_structure (caps, 0); - GstCaps* ret = gst_caps_copy (caps); - const GValue* par = NULL; + //GstGLFilter* filter = GST_GL_FILTER (bt); + GstStructure* structure = gst_caps_get_structure (caps, 0); + GstCaps* ret = gst_caps_copy (caps); + 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, + "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); + + gst_caps_merge_structure (ret, gst_structure_copy (structure)); + + if ((par = gst_structure_get_value (structure, "pixel-aspect-ratio"))) + { gst_structure_set (structure, - "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); + "pixel-aspect-ratio", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + gst_caps_merge_structure (ret, structure); + } + else + gst_structure_free (structure); - gst_caps_merge_structure (ret, gst_structure_copy (structure)); + GST_DEBUG_OBJECT (bt, "returning caps: %" GST_PTR_FORMAT, ret); - if ((par = gst_structure_get_value (structure, "pixel-aspect-ratio"))) - { - gst_structure_set (structure, - "pixel-aspect-ratio", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); - gst_caps_merge_structure (ret, structure); - } - else - gst_structure_free (structure); - - GST_DEBUG_OBJECT (bt, "returning caps: %" GST_PTR_FORMAT, ret); - - return ret; + return ret; } static gboolean gst_gl_filter_get_unit_size (GstBaseTransform* trans, GstCaps* caps, - guint* size) + guint* size) { - gboolean ret = FALSE; - gint width = 0; - gint height = 0; + gboolean ret = FALSE; + gint width = 0; + gint height = 0; - ret = gst_gl_buffer_parse_caps (caps, &width, &height); - if (ret) - *size = gst_gl_buffer_get_size (width, height); + ret = gst_gl_buffer_parse_caps (caps, &width, &height); + if (ret) + *size = gst_gl_buffer_get_size (width, height); - return TRUE; + return TRUE; } static GstFlowReturn 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; - GstGLBuffer* gl_inbuf = GST_GL_BUFFER (inbuf); - GstGLBuffer* gl_outbuf = NULL; + GstGLFilter* filter = NULL; + GstGLBuffer* gl_inbuf = GST_GL_BUFFER (inbuf); + GstGLBuffer* gl_outbuf = NULL; - filter = GST_GL_FILTER (trans); + filter = GST_GL_FILTER (trans); - if (filter->display == NULL) - { - GstGLFilterClass* filter_class = GST_GL_FILTER_GET_CLASS (filter); + if (filter->display == NULL) + { + 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 - gst_gl_display_gen_fbo (filter->display, filter->width, filter->height, - &filter->fbo, &filter->depthbuffer); + //blocking call, generate a FBO + gst_gl_display_gen_fbo (filter->display, filter->width, filter->height, + &filter->fbo, &filter->depthbuffer); - if (filter_class->onInitFBO) - filter_class->onInitFBO (filter); + if (filter_class->display_init_cb != NULL) { + gst_gl_display_thread_add (filter->display, gst_gl_filter_start_gl, filter); } - gl_outbuf = gst_gl_buffer_new (filter->display, - filter->width, filter->height); + if (filter_class->onInitFBO) + filter_class->onInitFBO (filter); + } - *buf = GST_BUFFER (gl_outbuf); - gst_buffer_set_caps (*buf, caps); + gl_outbuf = gst_gl_buffer_new (filter->display, + filter->width, filter->height); - if (gl_outbuf->texture) - return GST_FLOW_OK; - else - return GST_FLOW_UNEXPECTED; + *buf = GST_BUFFER (gl_outbuf); + gst_buffer_set_caps (*buf, caps); + + if (gl_outbuf->texture) + return GST_FLOW_OK; + else + return GST_FLOW_UNEXPECTED; } static gboolean gst_gl_filter_set_caps (GstBaseTransform* bt, GstCaps* incaps, - GstCaps* outcaps) + GstCaps* outcaps) { - GstGLFilter* filter = GST_GL_FILTER (bt); - gboolean ret = FALSE; - GstGLFilterClass* filter_class = GST_GL_FILTER_GET_CLASS (filter); + GstGLFilter* filter = GST_GL_FILTER (bt); + gboolean ret = FALSE; + 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) - filter_class->set_caps (filter, incaps, outcaps); + if (filter_class->set_caps) + filter_class->set_caps (filter, incaps, outcaps); - if (!ret) - { - GST_DEBUG ("bad caps"); - return FALSE; - } + if (!ret) + { + GST_DEBUG ("bad caps"); + return FALSE; + } - GST_ERROR ("set_caps %d %d", filter->width, filter->height); + GST_ERROR ("set_caps %d %d", filter->width, filter->height); - return ret; + return ret; } static GstFlowReturn gst_gl_filter_transform (GstBaseTransform* bt, GstBuffer* inbuf, - GstBuffer* outbuf) + GstBuffer* outbuf) { - GstGLFilter* filter; - GstGLBuffer* gl_inbuf = GST_GL_BUFFER (inbuf); - GstGLBuffer* gl_outbuf = GST_GL_BUFFER (outbuf); + GstGLFilter* filter; + GstGLBuffer* gl_inbuf = GST_GL_BUFFER (inbuf); + GstGLBuffer* gl_outbuf = GST_GL_BUFFER (outbuf); - filter = GST_GL_FILTER (bt); + filter = GST_GL_FILTER (bt); - gst_gl_filter_do_transform (filter, gl_inbuf, gl_outbuf); + gst_gl_filter_do_transform (filter, gl_inbuf, gl_outbuf); - return GST_FLOW_OK; + return GST_FLOW_OK; } static gboolean 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); - return TRUE; + return TRUE; } /* convenience functions to simplify filter development */ @@ -323,11 +354,11 @@ gst_gl_filter_render_to_target (GstGLFilter *filter, GLuint input, GLuint target, GLCB func, gpointer data) { - gst_gl_display_use_fbo (filter->display, filter->width, filter->height, - filter->fbo, filter->depthbuffer, target, - func, - filter->width, filter->height, input, - 0, filter->width, 0, filter->height, - GST_GL_DISPLAY_PROJECTION_ORTHO2D, - data); + gst_gl_display_use_fbo (filter->display, filter->width, filter->height, + filter->fbo, filter->depthbuffer, target, + func, + filter->width, filter->height, input, + 0, filter->width, 0, filter->height, + GST_GL_DISPLAY_PROJECTION_ORTHO2D, + data); } diff --git a/gst-libs/gst/gl/gstglfilter.h b/gst-libs/gst/gl/gstglfilter.h index 1c0286ee59..f4b85b0bbe 100644 --- a/gst-libs/gst/gl/gstglfilter.h +++ b/gst-libs/gst/gl/gstglfilter.h @@ -1,6 +1,7 @@ /* * GStreamer * Copyright (C) 2008 Julien Isorce + * Copyright (C) 2008 Filippo Argiolas * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -40,34 +41,42 @@ typedef struct _GstGLFilterClass GstGLFilterClass; typedef gboolean (*GstGLFilterSetCaps) (GstGLFilter* filter, - GstCaps* incaps, GstCaps* outcaps); + GstCaps* incaps, GstCaps* outcaps); typedef gboolean (*GstGLFilterProcessFunc) (GstGLFilter *filter, - GstGLBuffer *inbuf, GstGLBuffer *outbuf); + GstGLBuffer *inbuf, GstGLBuffer *outbuf); typedef void (*GstGLFilterOnInitFBO) (GstGLFilter *filter); typedef void (*GstGLFilterOnReset) (GstGLFilter *filter); +typedef void (*GstGLFilterGLStartFunc) (GstGLFilter *filter); +typedef void (*GstGLFilterGLStopFunc) (GstGLFilter *filter); + struct _GstGLFilter { - GstBaseTransform base_transform; + GstBaseTransform base_transform; - GstPad *srcpad; - GstPad *sinkpad; + GstPad *srcpad; + GstPad *sinkpad; - GstGLDisplay *display; + GstGLDisplay *display; - gint width; - gint height; - GLuint fbo; - GLuint depthbuffer; + gint width; + gint height; + GLuint fbo; + GLuint depthbuffer; }; struct _GstGLFilterClass { - GstBaseTransformClass base_transform_class; - GstGLFilterSetCaps set_caps; - GstGLFilterProcessFunc filter; - GstGLFilterOnInitFBO onInitFBO; - GstGLFilterOnReset onReset; + GstBaseTransformClass base_transform_class; + GstGLFilterSetCaps set_caps; + GstGLFilterProcessFunc filter; + GstGLFilterOnInitFBO onInitFBO; + + GstGLFilterOnReset onReset; + + /* useful to init and cleanup custom gl resources */ + GstGLFilterGLStartFunc display_init_cb; /* run arbitrary gl code at start */ + GstGLFilterGLStopFunc display_reset_cb; /* run arbitrary gl code at stop */ }; GType gst_gl_filter_get_type(void);