mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-18 15:51:11 +00:00
563 lines
16 KiB
C
563 lines
16 KiB
C
/* GStreamer
|
|
* Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "gstfrei0r.h"
|
|
#include "gstfrei0rfilter.h"
|
|
#include "gstfrei0rsrc.h"
|
|
#include "gstfrei0rmixer.h"
|
|
|
|
#include <string.h>
|
|
|
|
GST_DEBUG_CATEGORY (frei0r_debug);
|
|
#define GST_CAT_DEFAULT frei0r_debug
|
|
|
|
GstCaps *
|
|
gst_frei0r_caps_from_color_model (gint color_model)
|
|
{
|
|
switch (color_model) {
|
|
case F0R_COLOR_MODEL_BGRA8888:
|
|
return gst_caps_from_string (GST_VIDEO_CAPS_BGRA);
|
|
case F0R_COLOR_MODEL_RGBA8888:
|
|
return gst_caps_from_string (GST_VIDEO_CAPS_RGBA);
|
|
case F0R_COLOR_MODEL_PACKED32:
|
|
return gst_caps_from_string (GST_VIDEO_CAPS_BGRA " ; "
|
|
GST_VIDEO_CAPS_RGBA " ; "
|
|
GST_VIDEO_CAPS_ABGR " ; "
|
|
GST_VIDEO_CAPS_ARGB " ; "
|
|
GST_VIDEO_CAPS_BGRx " ; "
|
|
GST_VIDEO_CAPS_RGBx " ; "
|
|
GST_VIDEO_CAPS_xBGR " ; "
|
|
GST_VIDEO_CAPS_xRGB " ; " GST_VIDEO_CAPS_YUV ("AYUV"));
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
gst_frei0r_klass_install_properties (GObjectClass * gobject_class,
|
|
GstFrei0rFuncTable * ftable, GstFrei0rProperty * properties,
|
|
gint n_properties)
|
|
{
|
|
gint i, count = 1;
|
|
f0r_instance_t *instance = ftable->construct (640, 480);
|
|
|
|
g_assert (instance);
|
|
|
|
for (i = 0; i < n_properties; i++) {
|
|
f0r_param_info_t *param_info = &properties[i].info;
|
|
gchar *prop_name;
|
|
|
|
ftable->get_param_info (param_info, i);
|
|
|
|
prop_name = g_ascii_strdown (param_info->name, -1);
|
|
g_strcanon (prop_name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-+", '-');
|
|
|
|
properties[i].prop_id = count;
|
|
properties[i].prop_idx = i;
|
|
|
|
ftable->get_param_value (instance, &properties[i].default_value, i);
|
|
if (param_info->type == F0R_PARAM_STRING)
|
|
properties[i].default_value.data.s =
|
|
g_strdup (properties[i].default_value.data.s);
|
|
|
|
switch (param_info->type) {
|
|
case F0R_PARAM_BOOL:
|
|
g_object_class_install_property (gobject_class, count++,
|
|
g_param_spec_boolean (prop_name, param_info->name,
|
|
param_info->explanation, FALSE,
|
|
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
|
|
properties[i].n_prop_ids = 1;
|
|
break;
|
|
case F0R_PARAM_DOUBLE:
|
|
g_object_class_install_property (gobject_class, count++,
|
|
g_param_spec_double (prop_name, param_info->name,
|
|
param_info->explanation, -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
|
|
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
|
|
properties[i].n_prop_ids = 1;
|
|
break;
|
|
case F0R_PARAM_STRING:
|
|
g_object_class_install_property (gobject_class, count++,
|
|
g_param_spec_string (prop_name, param_info->name,
|
|
param_info->explanation, NULL,
|
|
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
|
|
properties[i].n_prop_ids = 1;
|
|
break;
|
|
case F0R_PARAM_COLOR:{
|
|
gchar *prop_name_full;
|
|
gchar *prop_nick_full;
|
|
|
|
prop_name_full = g_strconcat (prop_name, "-r", NULL);
|
|
prop_nick_full = g_strconcat (param_info->name, "-R", NULL);
|
|
g_object_class_install_property (gobject_class, count++,
|
|
g_param_spec_float (prop_name_full, prop_nick_full,
|
|
param_info->explanation, 0.0, 1.0, 0.0,
|
|
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
|
|
g_free (prop_name_full);
|
|
g_free (prop_nick_full);
|
|
|
|
prop_name_full = g_strconcat (prop_name, "-g", NULL);
|
|
prop_nick_full = g_strconcat (param_info->name, "-G", NULL);
|
|
g_object_class_install_property (gobject_class, count++,
|
|
g_param_spec_float (prop_name_full, param_info->name,
|
|
param_info->explanation, 0.0, 1.0, 0.0,
|
|
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
|
|
g_free (prop_name_full);
|
|
g_free (prop_nick_full);
|
|
|
|
prop_name_full = g_strconcat (prop_name, "-b", NULL);
|
|
prop_nick_full = g_strconcat (param_info->name, "-B", NULL);
|
|
g_object_class_install_property (gobject_class, count++,
|
|
g_param_spec_float (prop_name_full, param_info->name,
|
|
param_info->explanation, 0.0, 1.0, 0.0,
|
|
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
|
|
g_free (prop_name_full);
|
|
g_free (prop_nick_full);
|
|
|
|
properties[i].n_prop_ids = 3;
|
|
break;
|
|
}
|
|
case F0R_PARAM_POSITION:{
|
|
gchar *prop_name_full;
|
|
gchar *prop_nick_full;
|
|
|
|
prop_name_full = g_strconcat (prop_name, "-x", NULL);
|
|
prop_nick_full = g_strconcat (param_info->name, "-X", NULL);
|
|
g_object_class_install_property (gobject_class, count++,
|
|
g_param_spec_double (prop_name_full, param_info->name,
|
|
param_info->explanation, 0.0, 1.0, 0.0,
|
|
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
|
|
g_free (prop_name_full);
|
|
g_free (prop_nick_full);
|
|
|
|
prop_name_full = g_strconcat (prop_name, "-Y", NULL);
|
|
prop_nick_full = g_strconcat (param_info->name, "-X", NULL);
|
|
g_object_class_install_property (gobject_class, count++,
|
|
g_param_spec_double (prop_name_full, param_info->name,
|
|
param_info->explanation, 0.0, 1.0, 0.0,
|
|
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
|
|
g_free (prop_name_full);
|
|
g_free (prop_nick_full);
|
|
|
|
properties[i].n_prop_ids = 2;
|
|
break;
|
|
}
|
|
default:
|
|
g_assert_not_reached ();
|
|
break;
|
|
}
|
|
|
|
g_free (prop_name);
|
|
}
|
|
|
|
ftable->destruct (instance);
|
|
}
|
|
|
|
GstFrei0rPropertyValue *
|
|
gst_frei0r_property_cache_init (GstFrei0rProperty * properties,
|
|
gint n_properties)
|
|
{
|
|
gint i;
|
|
GstFrei0rPropertyValue *ret = g_new0 (GstFrei0rPropertyValue, n_properties);
|
|
|
|
for (i = 0; i < n_properties; i++) {
|
|
memcpy (&ret[i].data, &properties[i].default_value,
|
|
sizeof (GstFrei0rPropertyValue));
|
|
|
|
if (properties[i].info.type == F0R_PARAM_STRING)
|
|
ret[i].data.s = g_strdup (ret[i].data.s);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
gst_frei0r_property_cache_free (GstFrei0rProperty * properties,
|
|
GstFrei0rPropertyValue * property_cache, gint n_properties)
|
|
{
|
|
gint i;
|
|
|
|
for (i = 0; i < n_properties; i++) {
|
|
if (properties[i].info.type == F0R_PARAM_STRING)
|
|
g_free (property_cache[i].data.s);
|
|
}
|
|
g_free (property_cache);
|
|
}
|
|
|
|
f0r_instance_t *
|
|
gst_frei0r_instance_construct (GstFrei0rFuncTable * ftable,
|
|
GstFrei0rProperty * properties, gint n_properties,
|
|
GstFrei0rPropertyValue * property_cache, gint width, gint height)
|
|
{
|
|
f0r_instance_t *instance = ftable->construct (width, height);
|
|
gint i;
|
|
|
|
for (i = 0; i < n_properties; i++) {
|
|
if (properties[i].info.type == F0R_PARAM_STRING)
|
|
ftable->set_param_value (instance, property_cache[i].data.s, i);
|
|
else
|
|
ftable->set_param_value (instance, &property_cache[i].data, i);
|
|
}
|
|
|
|
return instance;
|
|
}
|
|
|
|
gboolean
|
|
gst_frei0r_get_property (f0r_instance_t * instance, GstFrei0rFuncTable * ftable,
|
|
GstFrei0rProperty * properties, gint n_properties,
|
|
GstFrei0rPropertyValue * property_cache, guint prop_id, GValue * value)
|
|
{
|
|
gint i;
|
|
GstFrei0rProperty *prop = NULL;
|
|
|
|
for (i = 0; i < n_properties; i++) {
|
|
if (properties[i].prop_id <= prop_id &&
|
|
properties[i].prop_id + properties[i].n_prop_ids > prop_id) {
|
|
prop = &properties[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!prop)
|
|
return FALSE;
|
|
|
|
switch (prop->info.type) {
|
|
case F0R_PARAM_BOOL:{
|
|
gdouble d;
|
|
|
|
if (instance)
|
|
ftable->get_param_value (instance, &d, prop->prop_idx);
|
|
else
|
|
d = property_cache[prop->prop_idx].data.b ? 1.0 : 0.0;
|
|
|
|
g_value_set_boolean (value, (d < 0.5) ? FALSE : TRUE);
|
|
break;
|
|
}
|
|
case F0R_PARAM_DOUBLE:{
|
|
gdouble d;
|
|
|
|
if (instance)
|
|
ftable->get_param_value (instance, &d, prop->prop_idx);
|
|
else
|
|
d = property_cache[prop->prop_idx].data.d;
|
|
|
|
g_value_set_double (value, d);
|
|
break;
|
|
}
|
|
case F0R_PARAM_STRING:{
|
|
const gchar *s;
|
|
|
|
if (instance)
|
|
ftable->get_param_value (instance, &s, prop->prop_idx);
|
|
else
|
|
s = property_cache[prop->prop_idx].data.s;
|
|
g_value_set_string (value, s);
|
|
break;
|
|
}
|
|
case F0R_PARAM_COLOR:{
|
|
f0r_param_color_t color;
|
|
|
|
if (instance)
|
|
ftable->get_param_value (instance, &color, prop->prop_idx);
|
|
else
|
|
color = property_cache[prop->prop_idx].data.color;
|
|
|
|
switch (prop_id - prop->prop_id) {
|
|
case 0:
|
|
g_value_set_float (value, color.r);
|
|
break;
|
|
case 1:
|
|
g_value_set_float (value, color.g);
|
|
break;
|
|
case 2:
|
|
g_value_set_float (value, color.b);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case F0R_PARAM_POSITION:{
|
|
f0r_param_position_t position;
|
|
|
|
if (instance)
|
|
ftable->get_param_value (instance, &position, prop->prop_idx);
|
|
else
|
|
position = property_cache[prop->prop_idx].data.position;
|
|
|
|
switch (prop_id - prop->prop_id) {
|
|
case 0:
|
|
g_value_set_double (value, position.x);
|
|
break;
|
|
case 1:
|
|
g_value_set_double (value, position.y);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
g_assert_not_reached ();
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
gst_frei0r_set_property (f0r_instance_t * instance, GstFrei0rFuncTable * ftable,
|
|
GstFrei0rProperty * properties, gint n_properties,
|
|
GstFrei0rPropertyValue * property_cache, guint prop_id,
|
|
const GValue * value)
|
|
{
|
|
GstFrei0rProperty *prop = NULL;
|
|
gint i;
|
|
|
|
for (i = 0; i < n_properties; i++) {
|
|
if (properties[i].prop_id <= prop_id &&
|
|
properties[i].prop_id + properties[i].n_prop_ids > prop_id) {
|
|
prop = &properties[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!prop)
|
|
return FALSE;
|
|
|
|
switch (prop->info.type) {
|
|
case F0R_PARAM_BOOL:{
|
|
gboolean b = g_value_get_boolean (value);
|
|
gdouble d = b ? 1.0 : 0.0;
|
|
|
|
if (instance)
|
|
ftable->set_param_value (instance, &d, prop->prop_idx);
|
|
property_cache[prop->prop_idx].data.b = b;
|
|
break;
|
|
}
|
|
case F0R_PARAM_DOUBLE:{
|
|
gdouble d = g_value_get_double (value);
|
|
|
|
if (instance)
|
|
ftable->set_param_value (instance, &d, prop->prop_idx);
|
|
property_cache[prop->prop_idx].data.d = d;
|
|
break;
|
|
}
|
|
case F0R_PARAM_STRING:{
|
|
gchar *s = g_value_dup_string (value);
|
|
|
|
/* Copies the string */
|
|
if (instance)
|
|
ftable->set_param_value (instance, s, prop->prop_idx);
|
|
property_cache[prop->prop_idx].data.s = s;
|
|
break;
|
|
}
|
|
case F0R_PARAM_COLOR:{
|
|
gfloat f = g_value_get_float (value);
|
|
f0r_param_color_t *color = &property_cache[prop->prop_idx].data.color;
|
|
|
|
switch (prop_id - prop->prop_id) {
|
|
case 0:
|
|
color->r = f;
|
|
break;
|
|
case 1:
|
|
color->g = f;
|
|
break;
|
|
case 2:
|
|
color->b = f;
|
|
break;
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
|
|
if (instance)
|
|
ftable->set_param_value (instance, color, prop->prop_idx);
|
|
break;
|
|
}
|
|
case F0R_PARAM_POSITION:{
|
|
gdouble d = g_value_get_double (value);
|
|
f0r_param_position_t *position =
|
|
&property_cache[prop->prop_idx].data.position;
|
|
|
|
switch (prop_id - prop->prop_id) {
|
|
case 0:
|
|
position->x = d;
|
|
break;
|
|
case 1:
|
|
position->y = d;
|
|
break;
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
if (instance)
|
|
ftable->set_param_value (instance, position, prop->prop_idx);
|
|
break;
|
|
}
|
|
default:
|
|
g_assert_not_reached ();
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
register_plugin (GstPlugin * plugin, const gchar * filename)
|
|
{
|
|
GModule *module;
|
|
gboolean ret = FALSE;
|
|
GstFrei0rFuncTable ftable = { NULL, };
|
|
f0r_plugin_info_t info = { NULL, };
|
|
|
|
GST_DEBUG ("Registering plugin '%s'", filename);
|
|
|
|
module = g_module_open (filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
|
|
if (!module) {
|
|
GST_WARNING ("Failed to load plugin");
|
|
return FALSE;
|
|
}
|
|
|
|
if (!g_module_symbol (module, "f0r_init", (gpointer *) & ftable.init)) {
|
|
GST_INFO ("No frei0r plugin");
|
|
g_module_close (module);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!g_module_symbol (module, "f0r_deinit", (gpointer *) & ftable.deinit) ||
|
|
!g_module_symbol (module, "f0r_construct",
|
|
(gpointer *) & ftable.construct)
|
|
|| !g_module_symbol (module, "f0r_destruct",
|
|
(gpointer *) & ftable.destruct)
|
|
|| !g_module_symbol (module, "f0r_get_plugin_info",
|
|
(gpointer *) & ftable.get_plugin_info)
|
|
|| !g_module_symbol (module, "f0r_get_param_info",
|
|
(gpointer *) & ftable.get_param_info)
|
|
|| !g_module_symbol (module, "f0r_set_param_value",
|
|
(gpointer *) & ftable.set_param_value)
|
|
|| !g_module_symbol (module, "f0r_get_param_value",
|
|
(gpointer *) & ftable.get_param_value))
|
|
goto invalid_frei0r_plugin;
|
|
|
|
/* One of these must exist */
|
|
g_module_symbol (module, "f0r_update", (gpointer *) & ftable.update);
|
|
g_module_symbol (module, "f0r_update2", (gpointer *) & ftable.update2);
|
|
|
|
if (!ftable.update && !ftable.update2)
|
|
goto invalid_frei0r_plugin;
|
|
|
|
ftable.get_plugin_info (&info);
|
|
|
|
if (info.frei0r_version > 1) {
|
|
GST_WARNING ("Unsupported frei0r version %d", info.frei0r_version);
|
|
g_module_close (module);
|
|
return FALSE;
|
|
}
|
|
|
|
if (info.color_model > F0R_COLOR_MODEL_PACKED32) {
|
|
GST_WARNING ("Unsupported color model %d", info.color_model);
|
|
g_module_close (module);
|
|
return FALSE;
|
|
}
|
|
|
|
switch (info.plugin_type) {
|
|
case F0R_PLUGIN_TYPE_FILTER:
|
|
ret = gst_frei0r_filter_register (plugin, &info, &ftable);
|
|
break;
|
|
case F0R_PLUGIN_TYPE_SOURCE:
|
|
ret = gst_frei0r_src_register (plugin, &info, &ftable);
|
|
break;
|
|
case F0R_PLUGIN_TYPE_MIXER2:
|
|
case F0R_PLUGIN_TYPE_MIXER3:
|
|
ret = gst_frei0r_mixer_register (plugin, &info, &ftable);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
|
|
invalid_frei0r_plugin:
|
|
GST_ERROR ("Invalid frei0r plugin");
|
|
g_module_close (module);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
register_plugins (GstPlugin * plugin, const gchar * path)
|
|
{
|
|
GDir *dir;
|
|
gchar *filename;
|
|
const gchar *entry_name;
|
|
gboolean ret = FALSE;
|
|
|
|
GST_DEBUG ("Scanning director '%s' for frei0r plugins", path);
|
|
|
|
dir = g_dir_open (path, 0, NULL);
|
|
if (!dir)
|
|
return FALSE;
|
|
|
|
while ((entry_name = g_dir_read_name (dir))) {
|
|
filename = g_build_filename (path, entry_name, NULL);
|
|
if ((g_str_has_suffix (filename, G_MODULE_SUFFIX)
|
|
#ifdef GST_EXTRA_MODULE_SUFFIX
|
|
|| g_str_has_suffix (filename, GST_EXTRA_MODULE_SUFFIX)
|
|
#endif
|
|
) && g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
|
|
ret |= register_plugin (plugin, filename);
|
|
} else if (g_file_test (filename, G_FILE_TEST_IS_DIR)) {
|
|
ret |= register_plugins (plugin, filename);
|
|
}
|
|
g_free (filename);
|
|
}
|
|
g_dir_close (dir);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static gboolean
|
|
plugin_init (GstPlugin * plugin)
|
|
{
|
|
const gchar *homedir;
|
|
gchar *path;
|
|
|
|
GST_DEBUG_CATEGORY_INIT (frei0r_debug, "frei0r", 0, "frei0r");
|
|
|
|
gst_plugin_add_dependency_simple (plugin,
|
|
"HOME/.frei0r-1/lib",
|
|
"/usr/lib/frei0r-1:/usr/local/lib/frei0r-1",
|
|
NULL, GST_PLUGIN_DEPENDENCY_FLAG_RECURSE);
|
|
|
|
register_plugins (plugin, "/usr/lib/frei0r-1");
|
|
register_plugins (plugin, "/usr/local/lib/frei0r-1");
|
|
|
|
homedir = g_get_home_dir ();
|
|
path = g_build_filename (homedir, ".frei0r-1", NULL);
|
|
register_plugins (plugin, path);
|
|
g_free (path);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
|
GST_VERSION_MINOR,
|
|
"frei0r",
|
|
"frei0r plugin library",
|
|
plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
|