mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
playsink: Proxy colorbalance interface
This commit is contained in:
parent
377bd8255c
commit
4289c0c899
1 changed files with 335 additions and 16 deletions
|
@ -216,6 +216,11 @@ struct _GstPlaySink
|
|||
gint xoverlay_x, xoverlay_y, xoverlay_width, xoverlay_height;
|
||||
gboolean xoverlay_handle_events_set;
|
||||
gboolean xoverlay_handle_events;
|
||||
|
||||
/* colorbalance proxy interface */
|
||||
GstColorBalance *colorbalance_element;
|
||||
GList *colorbalance_channels; /* CONTRAST, BRIGHTNESS, HUE, SATURATION */
|
||||
gint colorbalance_values[4];
|
||||
};
|
||||
|
||||
struct _GstPlaySinkClass
|
||||
|
@ -344,6 +349,9 @@ static void gst_play_sink_xoverlay_init (gpointer g_iface,
|
|||
gpointer g_iface_data);
|
||||
static void gst_play_sink_navigation_init (gpointer g_iface,
|
||||
gpointer g_iface_data);
|
||||
static void gst_play_sink_colorbalance_init (gpointer g_iface,
|
||||
gpointer g_iface_data);
|
||||
|
||||
static void
|
||||
_do_init (GType type)
|
||||
{
|
||||
|
@ -362,11 +370,16 @@ _do_init (GType type)
|
|||
gst_play_sink_navigation_init,
|
||||
NULL, NULL
|
||||
};
|
||||
static const GInterfaceInfo col_info = {
|
||||
gst_play_sink_colorbalance_init,
|
||||
NULL, NULL
|
||||
};
|
||||
|
||||
g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE, &impl_info);
|
||||
g_type_add_interface_static (type, GST_TYPE_STREAM_VOLUME, &svol_info);
|
||||
g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &xov_info);
|
||||
g_type_add_interface_static (type, GST_TYPE_NAVIGATION, &nav_info);
|
||||
g_type_add_interface_static (type, GST_TYPE_COLOR_BALANCE, &col_info);
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GstPlaySink, gst_play_sink, GST_TYPE_BIN,
|
||||
|
@ -553,6 +566,8 @@ gst_play_sink_class_init (GstPlaySinkClass * klass)
|
|||
static void
|
||||
gst_play_sink_init (GstPlaySink * playsink)
|
||||
{
|
||||
GstColorBalanceChannel *channel;
|
||||
|
||||
/* init groups */
|
||||
playsink->video_sink = NULL;
|
||||
playsink->audio_sink = NULL;
|
||||
|
@ -570,6 +585,46 @@ gst_play_sink_init (GstPlaySink * playsink)
|
|||
|
||||
g_static_rec_mutex_init (&playsink->lock);
|
||||
GST_OBJECT_FLAG_SET (playsink, GST_ELEMENT_IS_SINK);
|
||||
|
||||
channel =
|
||||
GST_COLOR_BALANCE_CHANNEL (g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL,
|
||||
NULL));
|
||||
channel->label = g_strdup ("CONTRAST");
|
||||
channel->min_value = -1000;
|
||||
channel->max_value = 1000;
|
||||
playsink->colorbalance_channels =
|
||||
g_list_append (playsink->colorbalance_channels, channel);
|
||||
playsink->colorbalance_values[0] = 0;
|
||||
|
||||
channel =
|
||||
GST_COLOR_BALANCE_CHANNEL (g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL,
|
||||
NULL));
|
||||
channel->label = g_strdup ("BRIGHTNESS");
|
||||
channel->min_value = -1000;
|
||||
channel->max_value = 1000;
|
||||
playsink->colorbalance_channels =
|
||||
g_list_append (playsink->colorbalance_channels, channel);
|
||||
playsink->colorbalance_values[1] = 0;
|
||||
|
||||
channel =
|
||||
GST_COLOR_BALANCE_CHANNEL (g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL,
|
||||
NULL));
|
||||
channel->label = g_strdup ("HUE");
|
||||
channel->min_value = -1000;
|
||||
channel->max_value = 1000;
|
||||
playsink->colorbalance_channels =
|
||||
g_list_append (playsink->colorbalance_channels, channel);
|
||||
playsink->colorbalance_values[2] = 0;
|
||||
|
||||
channel =
|
||||
GST_COLOR_BALANCE_CHANNEL (g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL,
|
||||
NULL));
|
||||
channel->label = g_strdup ("SATURATION");
|
||||
channel->min_value = -1000;
|
||||
channel->max_value = 1000;
|
||||
playsink->colorbalance_channels =
|
||||
g_list_append (playsink->colorbalance_channels, channel);
|
||||
playsink->colorbalance_values[3] = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -661,6 +716,11 @@ gst_play_sink_dispose (GObject * object)
|
|||
|
||||
playsink->stream_synchronizer = NULL;
|
||||
|
||||
g_list_foreach (playsink->colorbalance_channels, (GFunc) gst_object_unref,
|
||||
NULL);
|
||||
g_list_free (playsink->colorbalance_channels);
|
||||
playsink->colorbalance_channels = NULL;
|
||||
|
||||
G_OBJECT_CLASS (gst_play_sink_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
@ -1314,32 +1374,117 @@ static void
|
|||
iterate_color_balance_elements (gpointer data, gpointer user_data)
|
||||
{
|
||||
gboolean valid = is_valid_color_balance_element (data);
|
||||
gboolean *valid_out = user_data;
|
||||
GstColorBalance **cb_out = user_data;
|
||||
|
||||
*valid_out = *valid_out && valid;
|
||||
if (valid) {
|
||||
if (*cb_out
|
||||
&& gst_color_balance_get_balance_type (*cb_out) ==
|
||||
GST_COLOR_BALANCE_SOFTWARE) {
|
||||
gst_object_unref (*cb_out);
|
||||
*cb_out = GST_COLOR_BALANCE (gst_object_ref (data));
|
||||
} else if (!*cb_out) {
|
||||
*cb_out = GST_COLOR_BALANCE (gst_object_ref (data));
|
||||
}
|
||||
}
|
||||
|
||||
gst_object_unref (data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
has_color_balance_element (GstElement * element)
|
||||
static GstColorBalance *
|
||||
find_color_balance_element (GstElement * element)
|
||||
{
|
||||
GstIterator *it;
|
||||
gboolean valid = FALSE;
|
||||
GstColorBalance *cb = NULL;
|
||||
|
||||
if (GST_IS_COLOR_BALANCE (element))
|
||||
return is_valid_color_balance_element (element);
|
||||
if (GST_IS_COLOR_BALANCE (element)
|
||||
&& is_valid_color_balance_element (element))
|
||||
return GST_COLOR_BALANCE (gst_object_ref (element));
|
||||
else if (!GST_IS_BIN (element))
|
||||
return FALSE;
|
||||
|
||||
it = gst_bin_iterate_all_by_interface (GST_BIN (element),
|
||||
GST_TYPE_COLOR_BALANCE);
|
||||
while (gst_iterator_foreach (it, iterate_color_balance_elements,
|
||||
&valid) == GST_ITERATOR_RESYNC)
|
||||
&cb) == GST_ITERATOR_RESYNC)
|
||||
gst_iterator_resync (it);
|
||||
gst_iterator_free (it);
|
||||
|
||||
return valid;
|
||||
return cb;
|
||||
}
|
||||
|
||||
static void
|
||||
colorbalance_value_changed_cb (GstColorBalance * balance,
|
||||
GstColorBalanceChannel * channel, gint value, GstPlaySink * playsink)
|
||||
{
|
||||
GList *l;
|
||||
gint i;
|
||||
|
||||
for (i = 0, l = playsink->colorbalance_channels; l; l = l->next, i++) {
|
||||
GstColorBalanceChannel *proxy = l->data;
|
||||
|
||||
if (g_strrstr (channel->label, proxy->label)) {
|
||||
gdouble new_val;
|
||||
|
||||
/* Convert to [0, 1] range */
|
||||
new_val =
|
||||
((gdouble) value -
|
||||
(gdouble) channel->min_value) / ((gdouble) channel->max_value -
|
||||
(gdouble) channel->min_value);
|
||||
/* Convert to proxy range */
|
||||
new_val =
|
||||
proxy->min_value + new_val * ((gdouble) proxy->max_value -
|
||||
(gdouble) proxy->min_value);
|
||||
playsink->colorbalance_values[i] = (gint) (0.5 + new_val);
|
||||
|
||||
gst_color_balance_value_changed (GST_COLOR_BALANCE (playsink), proxy,
|
||||
playsink->colorbalance_values[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_colorbalance (GstPlaySink * playsink)
|
||||
{
|
||||
GstColorBalance *balance = NULL;
|
||||
GList *l;
|
||||
gint i;
|
||||
|
||||
GST_OBJECT_LOCK (playsink);
|
||||
if (playsink->colorbalance_element) {
|
||||
balance =
|
||||
GST_COLOR_BALANCE (gst_object_ref (playsink->colorbalance_element));
|
||||
}
|
||||
GST_OBJECT_UNLOCK (playsink);
|
||||
if (!balance)
|
||||
return;
|
||||
|
||||
g_signal_handlers_disconnect_by_func (balance,
|
||||
G_CALLBACK (colorbalance_value_changed_cb), playsink);
|
||||
|
||||
for (i = 0, l = playsink->colorbalance_channels; l; l = l->next, i++) {
|
||||
GstColorBalanceChannel *proxy = l->data;
|
||||
GstColorBalanceChannel *channel = NULL;
|
||||
const GList *channels, *k;
|
||||
|
||||
channels = gst_color_balance_list_channels (balance);
|
||||
for (k = channels; k; k = k->next) {
|
||||
GstColorBalanceChannel *tmp = k->data;
|
||||
|
||||
if (g_strrstr (tmp->label, proxy->label)) {
|
||||
channel = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_assert (channel);
|
||||
|
||||
gst_color_balance_set_value (balance, channel,
|
||||
playsink->colorbalance_values[i]);
|
||||
}
|
||||
|
||||
g_signal_connect (balance, "value-changed",
|
||||
G_CALLBACK (colorbalance_value_changed_cb), playsink);
|
||||
}
|
||||
|
||||
/* make the element (bin) that contains the elements needed to perform
|
||||
|
@ -1475,17 +1620,34 @@ gen_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async)
|
|||
head = prev = chain->queue;
|
||||
}
|
||||
|
||||
GST_OBJECT_LOCK (playsink);
|
||||
if (playsink->colorbalance_element) {
|
||||
g_signal_handlers_disconnect_by_func (playsink->colorbalance_element,
|
||||
G_CALLBACK (colorbalance_value_changed_cb), playsink);
|
||||
gst_object_unref (playsink->colorbalance_element);
|
||||
}
|
||||
playsink->colorbalance_element = find_color_balance_element (chain->sink);
|
||||
GST_OBJECT_UNLOCK (playsink);
|
||||
|
||||
if (!(playsink->flags & GST_PLAY_FLAG_NATIVE_VIDEO)
|
||||
|| (!has_color_balance_element (chain->sink)
|
||||
|| (!playsink->colorbalance_element
|
||||
&& (playsink->flags & GST_PLAY_FLAG_SOFT_COLORBALANCE))) {
|
||||
gboolean use_converters = !(playsink->flags & GST_PLAY_FLAG_NATIVE_VIDEO);
|
||||
gboolean use_balance = !has_color_balance_element (chain->sink)
|
||||
gboolean use_balance = !playsink->colorbalance_element
|
||||
&& (playsink->flags & GST_PLAY_FLAG_SOFT_COLORBALANCE);
|
||||
|
||||
GST_DEBUG_OBJECT (playsink, "creating videoconverter");
|
||||
chain->conv =
|
||||
g_object_new (GST_TYPE_PLAY_SINK_VIDEO_CONVERT, "name", "vconv",
|
||||
"use-converters", use_converters, "use-balance", use_balance, NULL);
|
||||
|
||||
GST_OBJECT_LOCK (playsink);
|
||||
if (use_balance && GST_PLAY_SINK_VIDEO_CONVERT (chain->conv)->balance)
|
||||
playsink->colorbalance_element =
|
||||
GST_COLOR_BALANCE (gst_object_ref (GST_PLAY_SINK_VIDEO_CONVERT
|
||||
(chain->conv)->balance));
|
||||
GST_OBJECT_UNLOCK (playsink);
|
||||
|
||||
gst_bin_add (bin, chain->conv);
|
||||
if (prev) {
|
||||
if (!gst_element_link_pads_full (prev, "src", chain->conv, "sink",
|
||||
|
@ -1497,6 +1659,8 @@ gen_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async)
|
|||
prev = chain->conv;
|
||||
}
|
||||
|
||||
update_colorbalance (playsink);
|
||||
|
||||
if (prev) {
|
||||
GST_DEBUG_OBJECT (playsink, "linking to sink");
|
||||
if (!gst_element_link_pads_full (prev, "src", chain->sink, NULL,
|
||||
|
@ -1632,10 +1796,30 @@ setup_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async)
|
|||
if (elem)
|
||||
g_object_set (elem, "force-aspect-ratio", TRUE, NULL);
|
||||
|
||||
if (chain->conv)
|
||||
g_object_set (chain->conv, "use-balance",
|
||||
!has_color_balance_element (chain->sink)
|
||||
&& (playsink->flags & GST_PLAY_FLAG_SOFT_COLORBALANCE), NULL);
|
||||
GST_OBJECT_LOCK (playsink);
|
||||
if (playsink->colorbalance_element) {
|
||||
g_signal_handlers_disconnect_by_func (playsink->colorbalance_element,
|
||||
G_CALLBACK (colorbalance_value_changed_cb), playsink);
|
||||
gst_object_unref (playsink->colorbalance_element);
|
||||
}
|
||||
playsink->colorbalance_element = find_color_balance_element (chain->sink);
|
||||
GST_OBJECT_UNLOCK (playsink);
|
||||
|
||||
if (chain->conv) {
|
||||
gboolean use_balance = !playsink->colorbalance_element
|
||||
&& (playsink->flags & GST_PLAY_FLAG_SOFT_COLORBALANCE);
|
||||
|
||||
g_object_set (chain->conv, "use-balance", use_balance, NULL);
|
||||
|
||||
GST_OBJECT_LOCK (playsink);
|
||||
if (use_balance && GST_PLAY_SINK_VIDEO_CONVERT (chain->conv)->balance)
|
||||
playsink->colorbalance_element =
|
||||
GST_COLOR_BALANCE (gst_object_ref (GST_PLAY_SINK_VIDEO_CONVERT
|
||||
(chain->conv)->balance));
|
||||
GST_OBJECT_UNLOCK (playsink);
|
||||
}
|
||||
|
||||
update_colorbalance (playsink);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -2363,6 +2547,13 @@ gst_play_sink_reconfigure (GstPlaySink * playsink)
|
|||
if (playsink->xoverlay_element)
|
||||
gst_object_unref (playsink->xoverlay_element);
|
||||
playsink->xoverlay_element = NULL;
|
||||
|
||||
if (playsink->colorbalance_element) {
|
||||
g_signal_handlers_disconnect_by_func (playsink->colorbalance_element,
|
||||
G_CALLBACK (colorbalance_value_changed_cb), playsink);
|
||||
gst_object_unref (playsink->colorbalance_element);
|
||||
}
|
||||
playsink->colorbalance_element = NULL;
|
||||
GST_OBJECT_UNLOCK (playsink);
|
||||
|
||||
if (((flags & GST_PLAY_FLAG_VIDEO)
|
||||
|
@ -3727,6 +3918,13 @@ gst_play_sink_change_state (GstElement * element, GstStateChange transition)
|
|||
if (playsink->xoverlay_element)
|
||||
gst_object_unref (playsink->xoverlay_element);
|
||||
playsink->xoverlay_element = NULL;
|
||||
|
||||
if (playsink->colorbalance_element) {
|
||||
g_signal_handlers_disconnect_by_func (playsink->colorbalance_element,
|
||||
G_CALLBACK (colorbalance_value_changed_cb), playsink);
|
||||
gst_object_unref (playsink->colorbalance_element);
|
||||
}
|
||||
playsink->colorbalance_element = NULL;
|
||||
GST_OBJECT_UNLOCK (playsink);
|
||||
|
||||
ret = GST_STATE_CHANGE_SUCCESS;
|
||||
|
@ -4072,7 +4270,7 @@ gst_play_sink_implements_interface_supported (GstImplementsInterface * iface,
|
|||
GType type)
|
||||
{
|
||||
if (type == GST_TYPE_X_OVERLAY || type == GST_TYPE_STREAM_VOLUME ||
|
||||
type == GST_TYPE_NAVIGATION)
|
||||
type == GST_TYPE_NAVIGATION || type == GST_TYPE_COLOR_BALANCE)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
|
@ -4122,6 +4320,127 @@ gst_play_sink_navigation_init (gpointer g_iface, gpointer g_iface_data)
|
|||
iface->send_event = gst_play_sink_navigation_send_event;
|
||||
}
|
||||
|
||||
static const GList *
|
||||
gst_play_sink_colorbalance_list_channels (GstColorBalance * balance)
|
||||
{
|
||||
GstPlaySink *playsink = GST_PLAY_SINK (balance);
|
||||
|
||||
return playsink->colorbalance_channels;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_play_sink_colorbalance_set_value (GstColorBalance * balance,
|
||||
GstColorBalanceChannel * proxy, gint value)
|
||||
{
|
||||
GstPlaySink *playsink = GST_PLAY_SINK (balance);
|
||||
GList *l;
|
||||
gint i;
|
||||
GstColorBalance *balance_element = NULL;
|
||||
|
||||
GST_OBJECT_LOCK (playsink);
|
||||
if (playsink->colorbalance_element)
|
||||
balance_element =
|
||||
GST_COLOR_BALANCE (gst_object_ref (playsink->colorbalance_element));
|
||||
GST_OBJECT_UNLOCK (playsink);
|
||||
|
||||
for (i = 0, l = playsink->colorbalance_channels; l; l = l->next, i++) {
|
||||
GstColorBalanceChannel *proxy_tmp = l->data;
|
||||
gdouble new_val;
|
||||
|
||||
if (proxy_tmp != proxy)
|
||||
continue;
|
||||
|
||||
playsink->colorbalance_values[i] = value;
|
||||
|
||||
if (balance_element) {
|
||||
GstColorBalanceChannel *channel = NULL;
|
||||
const GList *channels, *k;
|
||||
|
||||
channels = gst_color_balance_list_channels (balance_element);
|
||||
for (k = channels; k; k = k->next) {
|
||||
GstColorBalanceChannel *tmp = l->data;
|
||||
|
||||
if (g_strrstr (tmp->label, proxy->label)) {
|
||||
channel = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_assert (channel);
|
||||
|
||||
/* Convert to [0, 1] range */
|
||||
new_val =
|
||||
((gdouble) value -
|
||||
(gdouble) proxy->min_value) / ((gdouble) proxy->max_value -
|
||||
(gdouble) proxy->min_value);
|
||||
/* Convert to channel range */
|
||||
new_val =
|
||||
channel->min_value + new_val * ((gdouble) channel->max_value -
|
||||
(gdouble) channel->min_value);
|
||||
|
||||
gst_color_balance_set_value (balance_element, channel,
|
||||
(gint) (new_val + 0.5));
|
||||
|
||||
gst_object_unref (balance_element);
|
||||
}
|
||||
|
||||
gst_color_balance_value_changed (balance, proxy, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gint
|
||||
gst_play_sink_colorbalance_get_value (GstColorBalance * balance,
|
||||
GstColorBalanceChannel * proxy)
|
||||
{
|
||||
GstPlaySink *playsink = GST_PLAY_SINK (balance);
|
||||
GList *l;
|
||||
gint i;
|
||||
|
||||
for (i = 0, l = playsink->colorbalance_channels; l; l = l->next, i++) {
|
||||
GstColorBalanceChannel *proxy_tmp = l->data;
|
||||
|
||||
if (proxy_tmp != proxy)
|
||||
continue;
|
||||
|
||||
return playsink->colorbalance_values[i];
|
||||
}
|
||||
|
||||
g_return_val_if_reached (0);
|
||||
}
|
||||
|
||||
static GstColorBalanceType
|
||||
gst_play_sink_colorbalance_get_balance_type (GstColorBalance * balance)
|
||||
{
|
||||
GstPlaySink *playsink = GST_PLAY_SINK (balance);
|
||||
GstColorBalance *balance_element = NULL;
|
||||
GstColorBalanceType t = GST_COLOR_BALANCE_SOFTWARE;
|
||||
|
||||
GST_OBJECT_LOCK (playsink);
|
||||
if (playsink->colorbalance_element)
|
||||
balance_element =
|
||||
GST_COLOR_BALANCE (gst_object_ref (playsink->colorbalance_element));
|
||||
GST_OBJECT_UNLOCK (playsink);
|
||||
|
||||
if (balance_element) {
|
||||
t = gst_color_balance_get_balance_type (balance_element);
|
||||
gst_object_unref (balance_element);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_play_sink_colorbalance_init (gpointer g_iface, gpointer g_iface_data)
|
||||
{
|
||||
GstColorBalanceClass *iface = (GstColorBalanceClass *) g_iface;
|
||||
|
||||
iface->list_channels = gst_play_sink_colorbalance_list_channels;
|
||||
iface->set_value = gst_play_sink_colorbalance_set_value;
|
||||
iface->get_value = gst_play_sink_colorbalance_get_value;
|
||||
iface->get_balance_type = gst_play_sink_colorbalance_get_balance_type;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_play_sink_plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue