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
@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
#include <gst/video/video.h>
|
#include <gst/video/video.h>
|
||||||
|
|
||||||
#include <va/va_vpp.h>
|
|
||||||
#include <va/va_drmcommon.h>
|
#include <va/va_drmcommon.h>
|
||||||
|
|
||||||
#include "gstvacaps.h"
|
#include "gstvacaps.h"
|
||||||
@ -665,6 +664,30 @@ gst_va_filter_install_properties (GstVaFilter * self, GObjectClass * klass)
|
|||||||
return TRUE;
|
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
|
const gpointer
|
||||||
gst_va_filter_get_filter_caps (GstVaFilter * self, VAProcFilterType type,
|
gst_va_filter_get_filter_caps (GstVaFilter * self, VAProcFilterType type,
|
||||||
guint * num_caps)
|
guint * num_caps)
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
#include <gst/video/video.h>
|
#include <gst/video/video.h>
|
||||||
|
|
||||||
|
#include <va/va_vpp.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define GST_TYPE_VA_FILTER (gst_va_filter_get_type())
|
#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_open (GstVaFilter * self);
|
||||||
gboolean gst_va_filter_close (GstVaFilter * self);
|
gboolean gst_va_filter_close (GstVaFilter * self);
|
||||||
gboolean gst_va_filter_is_open (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,
|
gboolean gst_va_filter_install_properties (GstVaFilter * self,
|
||||||
GObjectClass * klass);
|
GObjectClass * klass);
|
||||||
gboolean gst_va_filter_set_orientation (GstVaFilter * self,
|
gboolean gst_va_filter_set_orientation (GstVaFilter * self,
|
||||||
|
@ -124,6 +124,8 @@ struct _GstVaVpp
|
|||||||
GstVideoOrientationMethod direction;
|
GstVideoOrientationMethod direction;
|
||||||
GstVideoOrientationMethod prev_direction;
|
GstVideoOrientationMethod prev_direction;
|
||||||
GstVideoOrientationMethod tag_direction;
|
GstVideoOrientationMethod tag_direction;
|
||||||
|
|
||||||
|
GList *channels;
|
||||||
};
|
};
|
||||||
|
|
||||||
static GstElementClass *parent_class = NULL;
|
static GstElementClass *parent_class = NULL;
|
||||||
@ -162,11 +164,16 @@ static GQuark meta_tag_orientation_quark;
|
|||||||
#define META_TAG_VIDEO meta_tag_video_quark
|
#define META_TAG_VIDEO meta_tag_video_quark
|
||||||
static GQuark meta_tag_video_quark;
|
static GQuark meta_tag_video_quark;
|
||||||
|
|
||||||
|
static void gst_va_vpp_colorbalance_init (gpointer iface, gpointer data);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_va_vpp_dispose (GObject * object)
|
gst_va_vpp_dispose (GObject * object)
|
||||||
{
|
{
|
||||||
GstVaVpp *self = GST_VA_VPP (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) {
|
if (self->sinkpad_pool) {
|
||||||
gst_buffer_pool_set_active (self->sinkpad_pool, FALSE);
|
gst_buffer_pool_set_active (self->sinkpad_pool, FALSE);
|
||||||
gst_clear_object (&self->sinkpad_pool);
|
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);
|
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
|
static void
|
||||||
gst_va_vpp_init (GTypeInstance * instance, gpointer g_class)
|
gst_va_vpp_init (GTypeInstance * instance, gpointer g_class)
|
||||||
{
|
{
|
||||||
@ -2359,17 +2379,23 @@ gst_va_vpp_init (GTypeInstance * instance, gpointer g_class)
|
|||||||
if (pspec) {
|
if (pspec) {
|
||||||
self->brightness =
|
self->brightness =
|
||||||
g_value_get_float (g_param_spec_get_default_value (pspec));
|
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");
|
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));
|
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");
|
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));
|
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");
|
pspec = g_object_class_find_property (g_class, "saturation");
|
||||||
if (pspec) {
|
if (pspec) {
|
||||||
self->saturation =
|
self->saturation =
|
||||||
g_value_get_float (g_param_spec_get_default_value (pspec));
|
g_value_get_float (g_param_spec_get_default_value (pspec));
|
||||||
|
_create_colorbalance_channel (self, "SATURATION");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* enable QoS */
|
/* 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,
|
type = g_type_register_static (GST_TYPE_BASE_TRANSFORM, type_name, &type_info,
|
||||||
0);
|
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);
|
ret = gst_element_register (plugin, feature_name, rank, type);
|
||||||
|
|
||||||
g_free (type_name);
|
g_free (type_name);
|
||||||
@ -2449,3 +2485,119 @@ gst_va_vpp_register (GstPlugin * plugin, GstVaDevice * device, guint rank)
|
|||||||
|
|
||||||
return ret;
|
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',
|
'multiple-vpp.c',
|
||||||
install: false,
|
install: false,
|
||||||
include_directories : [configinc],
|
include_directories : [configinc],
|
||||||
dependencies : [gst_dep],
|
dependencies : [gst_dep, gstvideo_dep],
|
||||||
c_args : gst_plugins_bad_args + ['-DGST_USE_UNSTABLE_API'],
|
c_args : gst_plugins_bad_args + ['-DGST_USE_UNSTABLE_API'],
|
||||||
)
|
)
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
#include <gst/video/video.h>
|
||||||
|
|
||||||
static gint num_buffers = 50;
|
static gint num_buffers = 50;
|
||||||
static gboolean camera = FALSE;
|
static gboolean camera = FALSE;
|
||||||
|
static gboolean randomcb = FALSE;
|
||||||
|
|
||||||
static GOptionEntry entries[] = {
|
static GOptionEntry entries[] = {
|
||||||
{"num-buffers", 'n', 0, G_OPTION_ARG_INT, &num_buffers,
|
{"num-buffers", 'n', 0, G_OPTION_ARG_INT, &num_buffers,
|
||||||
"Number of buffers (<= 0 : forever)", "N"},
|
"Number of buffers (<= 0 : forever)", "N"},
|
||||||
{"camera", 'c', 0, G_OPTION_ARG_NONE, &camera, "Use v4l2src as video source",
|
{"camera", 'c', 0, G_OPTION_ARG_NONE, &camera, "Use v4l2src as video source",
|
||||||
NULL},
|
NULL},
|
||||||
|
{"random-cb", 'r', 0, G_OPTION_ARG_NONE, &randomcb,
|
||||||
|
"Change colorbalance randomly every second", NULL},
|
||||||
{NULL},
|
{NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -18,6 +22,7 @@ struct _app
|
|||||||
GMainLoop *loop;
|
GMainLoop *loop;
|
||||||
GstObject *display;
|
GstObject *display;
|
||||||
GstElement *pipeline;
|
GstElement *pipeline;
|
||||||
|
GstElement *vpp;
|
||||||
GstElement *caps;
|
GstElement *caps;
|
||||||
GMutex mutex;
|
GMutex mutex;
|
||||||
};
|
};
|
||||||
@ -156,7 +161,7 @@ config_vpp (GstElement * vpp)
|
|||||||
static gboolean
|
static gboolean
|
||||||
build_pipeline (struct _app *app)
|
build_pipeline (struct _app *app)
|
||||||
{
|
{
|
||||||
GstElement *vpp, *src;
|
GstElement *src;
|
||||||
GstBus *bus;
|
GstBus *bus;
|
||||||
GError *err = NULL;
|
GError *err = NULL;
|
||||||
GString *cmd = g_string_new (NULL);
|
GString *cmd = g_string_new (NULL);
|
||||||
@ -180,9 +185,9 @@ build_pipeline (struct _app *app)
|
|||||||
gst_object_unref (src);
|
gst_object_unref (src);
|
||||||
}
|
}
|
||||||
|
|
||||||
vpp = gst_bin_get_by_name (GST_BIN (app->pipeline), "vpp");
|
app->vpp = gst_bin_get_by_name (GST_BIN (app->pipeline), "vpp");
|
||||||
config_vpp (vpp);
|
if (!randomcb)
|
||||||
gst_object_unref (vpp);
|
config_vpp (app->vpp);
|
||||||
|
|
||||||
app->caps = gst_bin_get_by_name (GST_BIN (app->pipeline), "caps");
|
app->caps = gst_bin_get_by_name (GST_BIN (app->pipeline), "caps");
|
||||||
|
|
||||||
@ -194,6 +199,29 @@ build_pipeline (struct _app *app)
|
|||||||
return TRUE;
|
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
|
static gboolean
|
||||||
parse_arguments (int *argc, char ***argv)
|
parse_arguments (int *argc, char ***argv)
|
||||||
{
|
{
|
||||||
@ -231,6 +259,9 @@ main (int argc, char **argv)
|
|||||||
if (!build_pipeline (&app))
|
if (!build_pipeline (&app))
|
||||||
goto gst_failed;
|
goto gst_failed;
|
||||||
|
|
||||||
|
if (randomcb)
|
||||||
|
g_timeout_add_seconds (1, change_cb_randomly, &app);
|
||||||
|
|
||||||
gst_element_set_state (app.pipeline, GST_STATE_PLAYING);
|
gst_element_set_state (app.pipeline, GST_STATE_PLAYING);
|
||||||
|
|
||||||
g_main_loop_run (app.loop);
|
g_main_loop_run (app.loop);
|
||||||
@ -246,6 +277,7 @@ main (int argc, char **argv)
|
|||||||
ret = EXIT_SUCCESS;
|
ret = EXIT_SUCCESS;
|
||||||
|
|
||||||
gst_clear_object (&app.caps);
|
gst_clear_object (&app.caps);
|
||||||
|
gst_clear_object (&app.vpp);
|
||||||
gst_clear_object (&app.pipeline);
|
gst_clear_object (&app.pipeline);
|
||||||
|
|
||||||
gst_failed:
|
gst_failed:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user