mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
va: vpp: implement GstColorBalance interface
And modify multiple-vpp example to use it with -r parameter. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2033>
This commit is contained in:
parent
5b117045e0
commit
87fe2e321e
5 changed files with 219 additions and 8 deletions
|
@ -26,7 +26,6 @@
|
|||
|
||||
#include <gst/video/video.h>
|
||||
|
||||
#include <va/va_vpp.h>
|
||||
#include <va/va_drmcommon.h>
|
||||
|
||||
#include "gstvacaps.h"
|
||||
|
@ -665,6 +664,30 @@ gst_va_filter_install_properties (GstVaFilter * self, GObjectClass * klass)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_va_filter_has_filter (GstVaFilter * self, VAProcFilterType type)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_return_val_if_fail (GST_IS_VA_FILTER (self), FALSE);
|
||||
|
||||
if (!gst_va_filter_is_open (self))
|
||||
return FALSE;
|
||||
|
||||
if (!gst_va_filter_ensure_filters (self))
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < self->available_filters->len; i++) {
|
||||
const struct VaFilter *filter =
|
||||
&g_array_index (self->available_filters, struct VaFilter, i);
|
||||
|
||||
if (filter->type == type)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const gpointer
|
||||
gst_va_filter_get_filter_caps (GstVaFilter * self, VAProcFilterType type,
|
||||
guint * num_caps)
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#include <gst/video/video.h>
|
||||
|
||||
#include <va/va_vpp.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_VA_FILTER (gst_va_filter_get_type())
|
||||
|
@ -48,6 +50,8 @@ GstVaFilter * gst_va_filter_new (GstVaDisplay * displa
|
|||
gboolean gst_va_filter_open (GstVaFilter * self);
|
||||
gboolean gst_va_filter_close (GstVaFilter * self);
|
||||
gboolean gst_va_filter_is_open (GstVaFilter * self);
|
||||
gboolean gst_va_filter_has_filter (GstVaFilter * self,
|
||||
VAProcFilterType type);
|
||||
gboolean gst_va_filter_install_properties (GstVaFilter * self,
|
||||
GObjectClass * klass);
|
||||
gboolean gst_va_filter_set_orientation (GstVaFilter * self,
|
||||
|
|
|
@ -124,6 +124,8 @@ struct _GstVaVpp
|
|||
GstVideoOrientationMethod direction;
|
||||
GstVideoOrientationMethod prev_direction;
|
||||
GstVideoOrientationMethod tag_direction;
|
||||
|
||||
GList *channels;
|
||||
};
|
||||
|
||||
static GstElementClass *parent_class = NULL;
|
||||
|
@ -162,11 +164,16 @@ static GQuark meta_tag_orientation_quark;
|
|||
#define META_TAG_VIDEO meta_tag_video_quark
|
||||
static GQuark meta_tag_video_quark;
|
||||
|
||||
static void gst_va_vpp_colorbalance_init (gpointer iface, gpointer data);
|
||||
|
||||
static void
|
||||
gst_va_vpp_dispose (GObject * object)
|
||||
{
|
||||
GstVaVpp *self = GST_VA_VPP (object);
|
||||
|
||||
if (self->channels)
|
||||
g_list_free_full (g_steal_pointer (&self->channels), g_object_unref);
|
||||
|
||||
if (self->sinkpad_pool) {
|
||||
gst_buffer_pool_set_active (self->sinkpad_pool, FALSE);
|
||||
gst_clear_object (&self->sinkpad_pool);
|
||||
|
@ -2327,6 +2334,19 @@ gst_va_vpp_class_init (gpointer g_class, gpointer class_data)
|
|||
gst_object_unref (display);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_create_colorbalance_channel (GstVaVpp * self, const gchar * label)
|
||||
{
|
||||
GstColorBalanceChannel *channel;
|
||||
|
||||
channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL);
|
||||
channel->label = g_strdup_printf ("VA-%s", label);
|
||||
channel->min_value = -1000;
|
||||
channel->max_value = 1000;
|
||||
|
||||
self->channels = g_list_append (self->channels, channel);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_va_vpp_init (GTypeInstance * instance, gpointer g_class)
|
||||
{
|
||||
|
@ -2359,17 +2379,23 @@ gst_va_vpp_init (GTypeInstance * instance, gpointer g_class)
|
|||
if (pspec) {
|
||||
self->brightness =
|
||||
g_value_get_float (g_param_spec_get_default_value (pspec));
|
||||
_create_colorbalance_channel (self, "BRIGHTNESS");
|
||||
}
|
||||
pspec = g_object_class_find_property (g_class, "contrast");
|
||||
if (pspec)
|
||||
if (pspec) {
|
||||
self->contrast = g_value_get_float (g_param_spec_get_default_value (pspec));
|
||||
_create_colorbalance_channel (self, "CONTRAST");
|
||||
}
|
||||
pspec = g_object_class_find_property (g_class, "hue");
|
||||
if (pspec)
|
||||
if (pspec) {
|
||||
self->hue = g_value_get_float (g_param_spec_get_default_value (pspec));
|
||||
_create_colorbalance_channel (self, "HUE");
|
||||
}
|
||||
pspec = g_object_class_find_property (g_class, "saturation");
|
||||
if (pspec) {
|
||||
self->saturation =
|
||||
g_value_get_float (g_param_spec_get_default_value (pspec));
|
||||
_create_colorbalance_channel (self, "SATURATION");
|
||||
}
|
||||
|
||||
/* enable QoS */
|
||||
|
@ -2442,6 +2468,16 @@ gst_va_vpp_register (GstPlugin * plugin, GstVaDevice * device, guint rank)
|
|||
type = g_type_register_static (GST_TYPE_BASE_TRANSFORM, type_name, &type_info,
|
||||
0);
|
||||
|
||||
{
|
||||
GstVaFilter *filter = gst_va_filter_new (device->display);
|
||||
if (gst_va_filter_open (filter)
|
||||
&& gst_va_filter_has_filter (filter, VAProcFilterColorBalance)) {
|
||||
const GInterfaceInfo info = { gst_va_vpp_colorbalance_init, NULL, NULL };
|
||||
g_type_add_interface_static (type, GST_TYPE_COLOR_BALANCE, &info);
|
||||
}
|
||||
gst_object_unref (filter);
|
||||
}
|
||||
|
||||
ret = gst_element_register (plugin, feature_name, rank, type);
|
||||
|
||||
g_free (type_name);
|
||||
|
@ -2449,3 +2485,119 @@ gst_va_vpp_register (GstPlugin * plugin, GstVaDevice * device, guint rank)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Color Balance interface */
|
||||
static const GList *
|
||||
gst_va_vpp_colorbalance_list_channels (GstColorBalance * balance)
|
||||
{
|
||||
GstVaVpp *self = GST_VA_VPP (balance);
|
||||
|
||||
return self->channels;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_set_cb_val (GstVaVpp * self, const gchar * name,
|
||||
GstColorBalanceChannel * channel, gint value, gfloat * cb)
|
||||
{
|
||||
GObjectClass *klass = G_OBJECT_CLASS (GST_VA_VPP_GET_CLASS (self));
|
||||
GParamSpec *pspec;
|
||||
GParamSpecFloat *fpspec;
|
||||
gfloat new_value;
|
||||
gboolean changed;
|
||||
|
||||
pspec = g_object_class_find_property (klass, name);
|
||||
if (!pspec)
|
||||
return FALSE;
|
||||
|
||||
fpspec = G_PARAM_SPEC_FLOAT (pspec);
|
||||
new_value = (value - channel->min_value) * (fpspec->maximum - fpspec->minimum)
|
||||
/ (channel->max_value - channel->min_value) + fpspec->minimum;
|
||||
|
||||
GST_OBJECT_LOCK (self);
|
||||
changed = new_value != *cb;
|
||||
*cb = new_value;
|
||||
value = (*cb + fpspec->minimum) * (channel->max_value - channel->min_value)
|
||||
/ (fpspec->maximum - fpspec->minimum) + channel->min_value;
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
|
||||
if (changed) {
|
||||
GST_INFO_OBJECT (self, "%s: %d / %f", channel->label, value, new_value);
|
||||
gst_color_balance_value_changed (GST_COLOR_BALANCE (self), channel, value);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_va_vpp_colorbalance_set_value (GstColorBalance * balance,
|
||||
GstColorBalanceChannel * channel, gint value)
|
||||
{
|
||||
GstVaVpp *self = GST_VA_VPP (balance);
|
||||
|
||||
if (g_str_has_suffix (channel->label, "HUE"))
|
||||
_set_cb_val (self, "hue", channel, value, &self->hue);
|
||||
else if (g_str_has_suffix (channel->label, "BRIGHTNESS"))
|
||||
_set_cb_val (self, "brightness", channel, value, &self->brightness);
|
||||
else if (g_str_has_suffix (channel->label, "CONTRAST"))
|
||||
_set_cb_val (self, "contrast", channel, value, &self->contrast);
|
||||
else if (g_str_has_suffix (channel->label, "SATURATION"))
|
||||
_set_cb_val (self, "saturation", channel, value, &self->saturation);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_get_cb_val (GstVaVpp * self, const gchar * name,
|
||||
GstColorBalanceChannel * channel, gfloat * cb, gint * val)
|
||||
{
|
||||
GObjectClass *klass = G_OBJECT_CLASS (GST_VA_VPP_GET_CLASS (self));
|
||||
GParamSpec *pspec;
|
||||
GParamSpecFloat *fpspec;
|
||||
|
||||
pspec = g_object_class_find_property (klass, name);
|
||||
if (!pspec)
|
||||
return FALSE;
|
||||
|
||||
fpspec = G_PARAM_SPEC_FLOAT (pspec);
|
||||
|
||||
GST_OBJECT_LOCK (self);
|
||||
*val = (*cb + fpspec->minimum) * (channel->max_value - channel->min_value)
|
||||
/ (fpspec->maximum - fpspec->minimum) + channel->min_value;
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gint
|
||||
gst_va_vpp_colorbalance_get_value (GstColorBalance * balance,
|
||||
GstColorBalanceChannel * channel)
|
||||
{
|
||||
GstVaVpp *self = GST_VA_VPP (balance);
|
||||
gint value = 0;
|
||||
|
||||
if (g_str_has_suffix (channel->label, "HUE"))
|
||||
_get_cb_val (self, "hue", channel, &self->hue, &value);
|
||||
else if (g_str_has_suffix (channel->label, "BRIGHTNESS"))
|
||||
_get_cb_val (self, "brightness", channel, &self->brightness, &value);
|
||||
else if (g_str_has_suffix (channel->label, "CONTRAST"))
|
||||
_get_cb_val (self, "contrast", channel, &self->contrast, &value);
|
||||
else if (g_str_has_suffix (channel->label, "SATURATION"))
|
||||
_get_cb_val (self, "saturation", channel, &self->saturation, &value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static GstColorBalanceType
|
||||
gst_va_vpp_colorbalance_get_balance_type (GstColorBalance * balance)
|
||||
{
|
||||
return GST_COLOR_BALANCE_HARDWARE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_va_vpp_colorbalance_init (gpointer iface, gpointer data)
|
||||
{
|
||||
GstColorBalanceInterface *cbiface = iface;
|
||||
|
||||
cbiface->list_channels = gst_va_vpp_colorbalance_list_channels;
|
||||
cbiface->set_value = gst_va_vpp_colorbalance_set_value;
|
||||
cbiface->get_value = gst_va_vpp_colorbalance_get_value;
|
||||
cbiface->get_balance_type = gst_va_vpp_colorbalance_get_balance_type;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,6 @@ executable('multiple-vpp',
|
|||
'multiple-vpp.c',
|
||||
install: false,
|
||||
include_directories : [configinc],
|
||||
dependencies : [gst_dep],
|
||||
dependencies : [gst_dep, gstvideo_dep],
|
||||
c_args : gst_plugins_bad_args + ['-DGST_USE_UNSTABLE_API'],
|
||||
)
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/video/video.h>
|
||||
|
||||
static gint num_buffers = 50;
|
||||
static gboolean camera = FALSE;
|
||||
static gboolean randomcb = FALSE;
|
||||
|
||||
static GOptionEntry entries[] = {
|
||||
{"num-buffers", 'n', 0, G_OPTION_ARG_INT, &num_buffers,
|
||||
"Number of buffers (<= 0 : forever)", "N"},
|
||||
{"camera", 'c', 0, G_OPTION_ARG_NONE, &camera, "Use v4l2src as video source",
|
||||
NULL},
|
||||
{"random-cb", 'r', 0, G_OPTION_ARG_NONE, &randomcb,
|
||||
"Change colorbalance randomly every second", NULL},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
|
@ -18,6 +22,7 @@ struct _app
|
|||
GMainLoop *loop;
|
||||
GstObject *display;
|
||||
GstElement *pipeline;
|
||||
GstElement *vpp;
|
||||
GstElement *caps;
|
||||
GMutex mutex;
|
||||
};
|
||||
|
@ -156,7 +161,7 @@ config_vpp (GstElement * vpp)
|
|||
static gboolean
|
||||
build_pipeline (struct _app *app)
|
||||
{
|
||||
GstElement *vpp, *src;
|
||||
GstElement *src;
|
||||
GstBus *bus;
|
||||
GError *err = NULL;
|
||||
GString *cmd = g_string_new (NULL);
|
||||
|
@ -180,9 +185,9 @@ build_pipeline (struct _app *app)
|
|||
gst_object_unref (src);
|
||||
}
|
||||
|
||||
vpp = gst_bin_get_by_name (GST_BIN (app->pipeline), "vpp");
|
||||
config_vpp (vpp);
|
||||
gst_object_unref (vpp);
|
||||
app->vpp = gst_bin_get_by_name (GST_BIN (app->pipeline), "vpp");
|
||||
if (!randomcb)
|
||||
config_vpp (app->vpp);
|
||||
|
||||
app->caps = gst_bin_get_by_name (GST_BIN (app->pipeline), "caps");
|
||||
|
||||
|
@ -194,6 +199,29 @@ build_pipeline (struct _app *app)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
change_cb_randomly (gpointer data)
|
||||
{
|
||||
struct _app *app = data;
|
||||
GstColorBalance *cb;
|
||||
GList *channels;
|
||||
|
||||
if (!GST_COLOR_BALANCE_GET_INTERFACE (app->vpp))
|
||||
return G_SOURCE_REMOVE;
|
||||
|
||||
cb = GST_COLOR_BALANCE (app->vpp);
|
||||
channels = (GList *) gst_color_balance_list_channels (cb);
|
||||
for (; channels && channels->data; channels = channels->next) {
|
||||
GstColorBalanceChannel *channel = channels->data;
|
||||
gint value =
|
||||
g_random_int_range (channel->min_value, channel->max_value + 1);
|
||||
|
||||
gst_color_balance_set_value (cb, channel, value);
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_arguments (int *argc, char ***argv)
|
||||
{
|
||||
|
@ -231,6 +259,9 @@ main (int argc, char **argv)
|
|||
if (!build_pipeline (&app))
|
||||
goto gst_failed;
|
||||
|
||||
if (randomcb)
|
||||
g_timeout_add_seconds (1, change_cb_randomly, &app);
|
||||
|
||||
gst_element_set_state (app.pipeline, GST_STATE_PLAYING);
|
||||
|
||||
g_main_loop_run (app.loop);
|
||||
|
@ -246,6 +277,7 @@ main (int argc, char **argv)
|
|||
ret = EXIT_SUCCESS;
|
||||
|
||||
gst_clear_object (&app.caps);
|
||||
gst_clear_object (&app.vpp);
|
||||
gst_clear_object (&app.pipeline);
|
||||
|
||||
gst_failed:
|
||||
|
|
Loading…
Reference in a new issue