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:
Víctor Manuel Jáquez Leal 2021-02-24 13:06:51 +01:00 committed by GStreamer Merge Bot
parent 5b117045e0
commit 87fe2e321e
5 changed files with 219 additions and 8 deletions

View file

@ -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)

View file

@ -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,

View file

@ -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;
}

View file

@ -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'],
)

View file

@ -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: