mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-25 09:40:37 +00:00
gleffects: Create element for each effect
https://bugzilla.gnome.org/show_bug.cgi?id=746209
This commit is contained in:
parent
afdc3c8ee3
commit
7ec1246730
3 changed files with 188 additions and 54 deletions
|
@ -39,16 +39,17 @@
|
||||||
#include <gst/gl/gstglconfig.h>
|
#include <gst/gl/gstglconfig.h>
|
||||||
#include "gstgleffects.h"
|
#include "gstgleffects.h"
|
||||||
|
|
||||||
#define GST_TYPE_GL_EFFECTS (gst_gl_effects_get_type())
|
|
||||||
#define GST_GL_EFFECTS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_GL_EFFECTS,GstGLEffects))
|
|
||||||
#define GST_IS_GL_EFFECTS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_GL_EFFECTS))
|
|
||||||
#define GST_GL_EFFECTS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) , GST_TYPE_GL_EFFECTS,GstGLEffectsClass))
|
|
||||||
#define GST_IS_GL_EFFECTS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) , GST_TYPE_GL_EFFECTS))
|
|
||||||
#define GST_GL_EFFECTS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) , GST_TYPE_GL_EFFECTS,GstGLEffectsClass))
|
|
||||||
|
|
||||||
#define GST_CAT_DEFAULT gst_gl_effects_debug
|
#define GST_CAT_DEFAULT gst_gl_effects_debug
|
||||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0 = 0x0,
|
||||||
|
PROP_EFFECT = 0x1 << 1,
|
||||||
|
PROP_HSWAP = 0x1 << 2,
|
||||||
|
PROP_INVERT = 0x1 << 3
|
||||||
|
};
|
||||||
|
|
||||||
#define DEBUG_INIT \
|
#define DEBUG_INIT \
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_gl_effects_debug, "gleffects", 0, "gleffects element");
|
GST_DEBUG_CATEGORY_INIT (gst_gl_effects_debug, "gleffects", 0, "gleffects element");
|
||||||
|
|
||||||
|
@ -70,6 +71,8 @@ static void gst_gl_effects_ghash_func_clean (gpointer key, gpointer value,
|
||||||
|
|
||||||
static gboolean gst_gl_effects_filter_texture (GstGLFilter * filter,
|
static gboolean gst_gl_effects_filter_texture (GstGLFilter * filter,
|
||||||
guint in_tex, guint out_tex);
|
guint in_tex, guint out_tex);
|
||||||
|
static gboolean gst_gl_effects_filters_is_property_supported (const
|
||||||
|
GstGLEffectsFilterDescriptor *, gint property);
|
||||||
|
|
||||||
/* 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
|
||||||
|
@ -96,11 +99,9 @@ typedef enum
|
||||||
GST_GL_N_EFFECTS
|
GST_GL_N_EFFECTS
|
||||||
} GstGLEffectsEffect;
|
} GstGLEffectsEffect;
|
||||||
|
|
||||||
#define GST_TYPE_GL_EFFECTS_EFFECT (gst_gl_effects_effect_get_type ())
|
static const GEnumValue *
|
||||||
static GType
|
gst_gl_effects_get_effects (void)
|
||||||
gst_gl_effects_effect_get_type (void)
|
|
||||||
{
|
{
|
||||||
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"},
|
||||||
|
@ -123,10 +124,18 @@ gst_gl_effects_effect_get_type (void)
|
||||||
{GST_GL_EFFECT_LAPLACIAN, "Laplacian Convolution Demo Effect", "laplacian"},
|
{GST_GL_EFFECT_LAPLACIAN, "Laplacian Convolution Demo Effect", "laplacian"},
|
||||||
{0, NULL, NULL}
|
{0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
return effect_types;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GST_TYPE_GL_EFFECTS_EFFECT (gst_gl_effects_effect_get_type ())
|
||||||
|
static GType
|
||||||
|
gst_gl_effects_effect_get_type (void)
|
||||||
|
{
|
||||||
|
static GType gl_effects_effect_type = 0;
|
||||||
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",
|
||||||
|
gst_gl_effects_get_effects ());
|
||||||
}
|
}
|
||||||
return gl_effects_effect_type;
|
return gl_effects_effect_type;
|
||||||
}
|
}
|
||||||
|
@ -307,14 +316,7 @@ gst_gl_effects_reset_gl_resources (GstGLFilter * filter)
|
||||||
static void
|
static void
|
||||||
gst_gl_effects_class_init (GstGLEffectsClass * klass)
|
gst_gl_effects_class_init (GstGLEffectsClass * klass)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class;
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||||
GstElementClass *element_class;
|
|
||||||
|
|
||||||
gobject_class = (GObjectClass *) klass;
|
|
||||||
element_class = GST_ELEMENT_CLASS (klass);
|
|
||||||
|
|
||||||
gobject_class->set_property = gst_gl_effects_set_property;
|
|
||||||
gobject_class->get_property = gst_gl_effects_get_property;
|
|
||||||
|
|
||||||
GST_GL_FILTER_CLASS (klass)->filter_texture = gst_gl_effects_filter_texture;
|
GST_GL_FILTER_CLASS (klass)->filter_texture = gst_gl_effects_filter_texture;
|
||||||
GST_GL_FILTER_CLASS (klass)->display_init_cb =
|
GST_GL_FILTER_CLASS (klass)->display_init_cb =
|
||||||
|
@ -325,26 +327,7 @@ gst_gl_effects_class_init (GstGLEffectsClass * klass)
|
||||||
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 (gobject_class,
|
klass->filter_descriptor = NULL;
|
||||||
PROP_EFFECT,
|
|
||||||
g_param_spec_enum ("effect",
|
|
||||||
"Effect",
|
|
||||||
"Select which effect apply to GL video texture",
|
|
||||||
GST_TYPE_GL_EFFECTS_EFFECT,
|
|
||||||
GST_GL_EFFECT_IDENTITY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
|
||||||
g_object_class_install_property (gobject_class,
|
|
||||||
PROP_HSWAP,
|
|
||||||
g_param_spec_boolean ("hswap",
|
|
||||||
"Horizontal Swap",
|
|
||||||
"Switch video texture left to right, useful with webcams",
|
|
||||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
|
||||||
/* FIXME: make it work on every effect */
|
|
||||||
g_object_class_install_property (gobject_class,
|
|
||||||
PROP_INVERT,
|
|
||||||
g_param_spec_boolean ("invert",
|
|
||||||
"Invert the colours for sobel and laplacian effect",
|
|
||||||
"Invert colors to get dark edges on bright background when using sobel effect",
|
|
||||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
|
||||||
|
|
||||||
gst_element_class_set_metadata (element_class,
|
gst_element_class_set_metadata (element_class,
|
||||||
"Gstreamer OpenGL Effects", "Filter/Effect/Video",
|
"Gstreamer OpenGL Effects", "Filter/Effect/Video",
|
||||||
|
@ -355,6 +338,46 @@ gst_gl_effects_class_init (GstGLEffectsClass * klass)
|
||||||
GST_GL_API_OPENGL | GST_GL_API_GLES2 | GST_GL_API_OPENGL3;
|
GST_GL_API_OPENGL | GST_GL_API_GLES2 | GST_GL_API_OPENGL3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_effects_filter_class_init (GstGLEffectsClass * klass,
|
||||||
|
const GstGLEffectsFilterDescriptor * filter_descriptor)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
klass->filter_descriptor = filter_descriptor;
|
||||||
|
|
||||||
|
gobject_class->set_property = gst_gl_effects_set_property;
|
||||||
|
gobject_class->get_property = gst_gl_effects_get_property;
|
||||||
|
|
||||||
|
/* if filterDescriptor is null it's a generic gleffects */
|
||||||
|
if (!filter_descriptor) {
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_EFFECT,
|
||||||
|
g_param_spec_enum ("effect",
|
||||||
|
"Effect",
|
||||||
|
"Select which effect apply to GL video texture",
|
||||||
|
GST_TYPE_GL_EFFECTS_EFFECT,
|
||||||
|
GST_GL_EFFECT_IDENTITY,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_HSWAP,
|
||||||
|
g_param_spec_boolean ("hswap",
|
||||||
|
"Horizontal Swap",
|
||||||
|
"Switch video texture left to right, useful with webcams",
|
||||||
|
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
/* FIXME: make it work on every effect */
|
||||||
|
if (gst_gl_effects_filters_is_property_supported (filter_descriptor,
|
||||||
|
PROP_INVERT)) {
|
||||||
|
g_object_class_install_property (gobject_class, PROP_INVERT,
|
||||||
|
g_param_spec_boolean ("invert", "Invert the colors for sobel effect",
|
||||||
|
"Invert colors to get dark edges on bright background when using sobel effect",
|
||||||
|
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_horizontal_swap (GstGLContext * context, gpointer data)
|
set_horizontal_swap (GstGLContext * context, gpointer data)
|
||||||
{
|
{
|
||||||
|
@ -376,9 +399,16 @@ set_horizontal_swap (GstGLContext * context, gpointer data)
|
||||||
static void
|
static void
|
||||||
gst_gl_effects_init (GstGLEffects * effects)
|
gst_gl_effects_init (GstGLEffects * effects)
|
||||||
{
|
{
|
||||||
effects->effect = gst_gl_effects_identity;
|
|
||||||
effects->horizontal_swap = FALSE;
|
effects->horizontal_swap = FALSE;
|
||||||
effects->invert = FALSE;
|
effects->invert = FALSE;
|
||||||
|
effects->effect = gst_gl_effects_identity;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_effects_filter_init (GstGLEffects * effects)
|
||||||
|
{
|
||||||
|
gst_gl_effects_set_effect (effects,
|
||||||
|
GST_GL_EFFECTS_GET_CLASS (effects)->filter_descriptor->effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -533,3 +563,109 @@ gst_gl_effects_get_fragment_shader (GstGLEffects * effects,
|
||||||
|
|
||||||
return shader;
|
return shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const GstGLEffectsFilterDescriptor *
|
||||||
|
gst_gl_effects_filters_supported_properties (void)
|
||||||
|
{
|
||||||
|
/* Horizontal swap property is supported by all filters */
|
||||||
|
static const GstGLEffectsFilterDescriptor effects[] = {
|
||||||
|
{GST_GL_EFFECT_SOBEL, PROP_INVERT, NULL},
|
||||||
|
{GST_GL_EFFECT_LAPLACIAN, PROP_INVERT, NULL},
|
||||||
|
{0, 0, NULL}
|
||||||
|
};
|
||||||
|
return effects;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline gboolean
|
||||||
|
gst_gl_effects_filters_is_property_supported (const GstGLEffectsFilterDescriptor
|
||||||
|
* descriptor, gint property)
|
||||||
|
{
|
||||||
|
/* generic filter (NULL descriptor) supports all properties */
|
||||||
|
return !descriptor || (descriptor->supported_properties & property);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const GstGLEffectsFilterDescriptor *
|
||||||
|
gst_gl_effects_filters_descriptors (void)
|
||||||
|
{
|
||||||
|
static GstGLEffectsFilterDescriptor *descriptors = NULL;
|
||||||
|
if (!descriptors) {
|
||||||
|
const GEnumValue *effect = gst_gl_effects_get_effects ();
|
||||||
|
guint n_filters = 0;
|
||||||
|
for (const GEnumValue * e = effect; NULL != e->value_nick; ++e, ++n_filters) {
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptors = g_new0 (GstGLEffectsFilterDescriptor, n_filters + 1);
|
||||||
|
for (guint i = 0; i < n_filters; ++i, ++effect) {
|
||||||
|
descriptors[i].effect = effect->value;
|
||||||
|
descriptors[i].filter_name = effect->value_nick;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const GstGLEffectsFilterDescriptor * defined =
|
||||||
|
gst_gl_effects_filters_supported_properties ();
|
||||||
|
0 != defined->supported_properties; ++defined) {
|
||||||
|
|
||||||
|
guint i = 0;
|
||||||
|
for (; i < n_filters; ++i) {
|
||||||
|
if (descriptors[i].effect == defined->effect) {
|
||||||
|
descriptors[i].supported_properties = defined->supported_properties;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i >= n_filters) {
|
||||||
|
GST_WARNING ("Could not match gstgleffects-%s descriptor",
|
||||||
|
defined->filter_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return descriptors;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_gl_effects_register_filters (GstPlugin * plugin, GstRank rank)
|
||||||
|
{
|
||||||
|
static volatile gsize registered = 0;
|
||||||
|
|
||||||
|
if (g_once_init_enter (®istered)) {
|
||||||
|
GTypeInfo info = {
|
||||||
|
sizeof (GstGLEffectsClass),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
(GClassInitFunc) gst_gl_effects_filter_class_init,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
sizeof (GstGLEffects),
|
||||||
|
0,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
GType generic_type =
|
||||||
|
g_type_register_static (GST_TYPE_GL_EFFECTS, "GstGLEffectsGeneric",
|
||||||
|
&info, 0);
|
||||||
|
|
||||||
|
if (gst_element_register (plugin, "gleffects", rank, generic_type)) {
|
||||||
|
for (const GstGLEffectsFilterDescriptor * filters =
|
||||||
|
gst_gl_effects_filters_descriptors (); NULL != filters->filter_name;
|
||||||
|
++filters) {
|
||||||
|
gchar *name = g_strdup_printf ("gleffects_%s", filters->filter_name);
|
||||||
|
GTypeInfo info = {
|
||||||
|
sizeof (GstGLEffectsClass),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
(GClassInitFunc) gst_gl_effects_filter_class_init,
|
||||||
|
NULL,
|
||||||
|
filters,
|
||||||
|
sizeof (GstGLEffects),
|
||||||
|
0,
|
||||||
|
(GInstanceInitFunc) gst_gl_effects_filter_init
|
||||||
|
};
|
||||||
|
GType type =
|
||||||
|
g_type_register_static (GST_TYPE_GL_EFFECTS, name, &info, 0);
|
||||||
|
if (!gst_element_register (plugin, name, rank, type)) {
|
||||||
|
GST_WARNING ("Could not register %s", name);
|
||||||
|
}
|
||||||
|
g_free (name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_once_init_leave (®istered, generic_type);
|
||||||
|
}
|
||||||
|
return registered;
|
||||||
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
|
||||||
#define GST_TYPE_GL_EFFECTS (gst_gl_effects_get_type())
|
#define GST_TYPE_GL_EFFECTS (gst_gl_effects_get_type())
|
||||||
#define GST_GL_EFFECTS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_GL_EFFECTS,GstGLEffects))
|
#define GST_GL_EFFECTS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_GL_EFFECTS,GstGLEffects))
|
||||||
#define GST_IS_GL_EFFECTS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_GL_EFFECTS))
|
#define GST_IS_GL_EFFECTS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_GL_EFFECTS))
|
||||||
|
@ -43,6 +42,12 @@ G_BEGIN_DECLS
|
||||||
typedef struct _GstGLEffects GstGLEffects;
|
typedef struct _GstGLEffects GstGLEffects;
|
||||||
typedef struct _GstGLEffectsClass GstGLEffectsClass;
|
typedef struct _GstGLEffectsClass GstGLEffectsClass;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
gint effect;
|
||||||
|
guint supported_properties;
|
||||||
|
const gchar *filter_name;
|
||||||
|
} GstGLEffectsFilterDescriptor;
|
||||||
|
|
||||||
typedef void (* GstGLEffectProcessFunc) (GstGLEffects *effects);
|
typedef void (* GstGLEffectProcessFunc) (GstGLEffects *effects);
|
||||||
|
|
||||||
#define NEEDED_TEXTURES 5
|
#define NEEDED_TEXTURES 5
|
||||||
|
@ -78,18 +83,11 @@ struct _GstGLEffects
|
||||||
struct _GstGLEffectsClass
|
struct _GstGLEffectsClass
|
||||||
{
|
{
|
||||||
GstGLFilterClass filter_class;
|
GstGLFilterClass filter_class;
|
||||||
|
const GstGLEffectsFilterDescriptor *filter_descriptor;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
PROP_0,
|
|
||||||
PROP_EFFECT,
|
|
||||||
PROP_HSWAP,
|
|
||||||
PROP_INVERT
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
GType gst_gl_effects_get_type (void);
|
GType gst_gl_effects_get_type (void);
|
||||||
|
gboolean gst_gl_effects_register_filters (GstPlugin *, GstRank);
|
||||||
GstGLShader* gst_gl_effects_get_fragment_shader (GstGLEffects *effects,
|
GstGLShader* gst_gl_effects_get_fragment_shader (GstGLEffects *effects,
|
||||||
const gchar * shader_name, const gchar * shader_source_gles2, const gchar * shader_source_opengl);
|
const gchar * shader_name, const gchar * shader_source_gles2, const gchar * shader_source_opengl);
|
||||||
|
|
||||||
|
|
|
@ -161,10 +161,10 @@ plugin_init (GstPlugin * plugin)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (!gst_element_register (plugin, "gleffects",
|
|
||||||
GST_RANK_NONE, gst_gl_effects_get_type ())) {
|
if (!gst_gl_effects_register_filters (plugin, GST_RANK_NONE)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
};
|
||||||
|
|
||||||
if (!gst_element_register (plugin, "glcolorscale",
|
if (!gst_element_register (plugin, "glcolorscale",
|
||||||
GST_RANK_NONE, GST_TYPE_GL_COLORSCALE)) {
|
GST_RANK_NONE, GST_TYPE_GL_COLORSCALE)) {
|
||||||
|
|
Loading…
Reference in a new issue