vaapisink: add support for GstColorBalance interface.
authorChangzhi Wei <changzhix.wei@intel.com>
Thu, 23 Jan 2014 15:44:09 +0000 (15:44 +0000)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Thu, 31 Jul 2014 16:49:55 +0000 (18:49 +0200)
https://bugzilla.gnome.org/show_bug.cgi?id=722390

[fixed channel names, simplified range factor, fixed memory leak]
Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
gst/vaapi/gstvaapisink.c
gst/vaapi/gstvaapisink.h

index f6ce385..2462737 100644 (file)
 /* Supported interfaces */
 #if GST_CHECK_VERSION(1,0,0)
 # include <gst/video/videooverlay.h>
+# include <gst/video/colorbalance.h>
 #else
 # include <gst/interfaces/xoverlay.h>
+# include <gst/interfaces/colorbalance.h>
 
 # define GST_TYPE_VIDEO_OVERLAY         GST_TYPE_X_OVERLAY
 # define GST_VIDEO_OVERLAY              GST_X_OVERLAY
@@ -52,6 +54,8 @@
     gst_x_overlay_prepare_xwindow_id(sink)
 # define gst_video_overlay_got_window_handle(sink, window_handle) \
     gst_x_overlay_got_window_handle(sink, window_handle)
+
+# define GstColorBalanceInterface       GstColorBalanceClass
 #endif
 
 #include "gstvaapisink.h"
@@ -94,18 +98,23 @@ GST_STATIC_PAD_TEMPLATE ("sink",
 static gboolean
 gst_vaapisink_has_interface (GstVaapiPluginBase * plugin, GType type)
 {
-  return type == GST_TYPE_VIDEO_OVERLAY;
+  return type == GST_TYPE_VIDEO_OVERLAY || type == GST_TYPE_COLOR_BALANCE;
 }
 
 static void
 gst_vaapisink_video_overlay_iface_init (GstVideoOverlayInterface * iface);
 
+static void
+gst_vaapisink_color_balance_iface_init (GstColorBalanceInterface * iface);
+
 G_DEFINE_TYPE_WITH_CODE (GstVaapiSink,
     gst_vaapisink,
     GST_TYPE_VIDEO_SINK,
     GST_VAAPI_PLUGIN_BASE_INIT_INTERFACES
     G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_OVERLAY,
-        gst_vaapisink_video_overlay_iface_init));
+        gst_vaapisink_video_overlay_iface_init);
+    G_IMPLEMENT_INTERFACE (GST_TYPE_COLOR_BALANCE,
+        gst_vaapisink_color_balance_iface_init));
 
 enum
 {
@@ -502,6 +511,10 @@ gst_vaapisink_video_overlay_iface_init (GstVideoOverlayInterface * iface)
   iface->handle_events = gst_vaapisink_video_overlay_set_event_handling;
 }
 
+/* ------------------------------------------------------------------------ */
+/* --- GstColorBalance interface                                        --- */
+/* ------------------------------------------------------------------------ */
+
 enum
 {
   CB_HUE = 1,
@@ -514,15 +527,30 @@ typedef struct
 {
   guint cb_id;
   const gchar *prop_name;
+  const gchar *channel_name;
 } ColorBalanceMap;
 
 static const ColorBalanceMap cb_map[4] = {
-  {CB_HUE, GST_VAAPI_DISPLAY_PROP_HUE},
-  {CB_SATURATION, GST_VAAPI_DISPLAY_PROP_SATURATION},
-  {CB_BRIGHTNESS, GST_VAAPI_DISPLAY_PROP_BRIGHTNESS},
-  {CB_CONTRAST, GST_VAAPI_DISPLAY_PROP_CONTRAST}
+  {CB_HUE, GST_VAAPI_DISPLAY_PROP_HUE, "VA_HUE"},
+  {CB_SATURATION, GST_VAAPI_DISPLAY_PROP_SATURATION, "VA_SATURATION"},
+  {CB_BRIGHTNESS, GST_VAAPI_DISPLAY_PROP_BRIGHTNESS, "VA_BRIGHTNESS"},
+  {CB_CONTRAST, GST_VAAPI_DISPLAY_PROP_CONTRAST, "VA_CONTRAST"}
 };
 
+static guint
+cb_get_id_from_channel_name (GstVaapiSink * sink, const gchar * name)
+{
+  guint i;
+
+  for (i = 0; i < G_N_ELEMENTS (sink->cb_values); i++) {
+    if (g_ascii_strcasecmp (cb_map[i].channel_name, name) == 0)
+      return cb_map[i].cb_id;
+  }
+
+  GST_WARNING ("got an unknown channel %s", name);
+  return 0;
+}
+
 static inline GValue *
 cb_get_gvalue (GstVaapiSink * sink, guint id)
 {
@@ -606,6 +634,115 @@ cb_sync_values_to_display (GstVaapiSink * sink, GstVaapiDisplay * display)
   return failures == 0;
 }
 
+#define CB_CHANNEL_FACTOR (1000.0)
+
+static void
+cb_channels_init (GstVaapiSink * sink)
+{
+  GstVaapiDisplay *const display = GST_VAAPI_PLUGIN_BASE_DISPLAY (sink);
+  GstColorBalanceChannel *channel;
+  GParamSpecFloat *pspec;
+  guint i;
+
+  for (i = 0; i < G_N_ELEMENTS (sink->cb_values); i++) {
+    if (!gst_vaapi_display_has_property (display, cb_map[i].prop_name))
+      continue;
+
+    pspec = G_PARAM_SPEC_FLOAT (g_properties[PROP_HUE + i]);
+    if (!pspec)
+      continue;
+
+    channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL);
+    channel->label = g_strdup (cb_map[i].channel_name);
+    channel->min_value = pspec->minimum * CB_CHANNEL_FACTOR;
+    channel->max_value = pspec->maximum * CB_CHANNEL_FACTOR;
+
+    sink->cb_channels = g_list_prepend (sink->cb_channels, channel);
+  }
+
+  if (sink->cb_channels)
+    sink->cb_channels = g_list_reverse (sink->cb_channels);
+}
+
+static void
+cb_channels_finalize (GstVaapiSink * sink)
+{
+  if (sink->cb_channels) {
+    g_list_free_full (sink->cb_channels, g_object_unref);
+    sink->cb_channels = NULL;
+  }
+}
+
+static const GList *
+gst_vaapisink_color_balance_list_channels (GstColorBalance * cb)
+{
+  GstVaapiSink *const sink = GST_VAAPISINK (cb);
+
+  if (!gst_vaapisink_ensure_display (sink))
+    return NULL;
+
+  if (!sink->cb_channels)
+    cb_channels_init (sink);
+  return sink->cb_channels;
+}
+
+static void
+gst_vaapisink_color_balance_set_value (GstColorBalance * cb,
+    GstColorBalanceChannel * channel, gint value)
+{
+  GstVaapiSink *const sink = GST_VAAPISINK (cb);
+  guint cb_id;
+
+  g_return_if_fail (channel->label != NULL);
+
+  if (!gst_vaapisink_ensure_display (sink))
+    return;
+
+  cb_id = cb_get_id_from_channel_name (sink, channel->label);
+  if (!cb_id)
+    return;
+
+  cb_set_value (sink, cb_id, value / CB_CHANNEL_FACTOR);
+}
+
+static gint
+gst_vaapisink_color_balance_get_value (GstColorBalance * cb,
+    GstColorBalanceChannel * channel)
+{
+  GstVaapiSink *const sink = GST_VAAPISINK (cb);
+  guint cb_id;
+
+  g_return_val_if_fail (channel->label != NULL, 0);
+
+  if (!gst_vaapisink_ensure_display (sink))
+    return 0;
+
+  cb_id = cb_get_id_from_channel_name (sink, channel->label);
+  if (!cb_id)
+    return 0;
+
+  return cb_get_value (sink, cb_id) * CB_CHANNEL_FACTOR;
+}
+
+static GstColorBalanceType
+gst_vaapisink_color_balance_get_type (GstColorBalance * cb)
+{
+  return GST_COLOR_BALANCE_HARDWARE;
+}
+
+static void
+gst_vaapisink_color_balance_iface_init (GstColorBalanceInterface * iface)
+{
+  iface->list_channels = gst_vaapisink_color_balance_list_channels;
+  iface->set_value = gst_vaapisink_color_balance_set_value;
+  iface->get_value = gst_vaapisink_color_balance_get_value;
+#if GST_CHECK_VERSION(1,0,0)
+  iface->get_balance_type = gst_vaapisink_color_balance_get_type;
+#else
+  iface->balance_type = gst_vaapisink_color_balance_get_type (NULL);
+#endif
+}
+
 /* ------------------------------------------------------------------------ */
 /* --- Common implementation                                            --- */
 /* ------------------------------------------------------------------------ */
@@ -1210,6 +1347,7 @@ gst_vaapisink_destroy (GstVaapiSink * sink)
 {
   gst_vaapisink_set_event_handling (sink, FALSE);
 
+  cb_channels_finalize (sink);
   gst_buffer_replace (&sink->video_buffer, NULL);
   gst_caps_replace (&sink->caps, NULL);
 }
index 125de2e..958d6cc 100644 (file)
@@ -102,6 +102,7 @@ struct _GstVaapiSink
   /* Color balance values */
   guint cb_changed;
   GValue cb_values[4];
+  GList *cb_channels;
 
   guint handle_events : 1;
   guint foreign_window : 1;