VAAPI colormatrix and fullrange support

Torsten Jager <[email protected]> Sat, 26 Apr 2014 15:11:47 +0200
Newsgroups gmane.comp.video.xine.devel
Message-ID <[email protected]>
Hello Zaverel (and any VAAPI user, too).

Having neither libva nor suitable hardware, I cannot test this.
That's why I did not push right away.

Can you have a look at it for me?

Torsten

------------------------------------------------------------------------------
Start Your Social Network Today - Download eXo Platform
Build your Enterprise Intranet with eXo Platform Software
Java Based Open Source Intranet - Social, Extensible, Cloud Ready
Get Started Now And Turn Your Intranet Into A Collaboration Platform
http://p.sf.net/sfu/ExoPlatform

_______________________________________________
xine-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/xine-devel
vaapi_cm_1.diff (text/x-patch, 8.2 KB)
VAAPI: color matrix and fullrange support attempt #1.
Also, guard against requesting/setting unsupported properties.
And fix video eq handling like in vo_xv.

This is based on my earlier vo_xv extension and some unused part
of vo_vaapi itself.

The ffmpeg vaapi wrapper seems to ignore va_context.colorspace.
If that information is at all present, it will be in AVContext
and vo_frame.flags as usual, so there might be a chance for this to
work.
--- xine-lib-1.2/src/video_out/video_out_vaapi.c	2014-04-19 14:47:30.000000000 +0200
+++ xine-lib-1.2/src/video_out/video_out_vaapi.c	2014-04-25 01:21:00.000000000 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2012 Edgar Hucek <gimli|@dark-green.com>
- * Copyright (C) 2012-2013 xine developers
+ * Copyright (C) 2012-2014 xine developers
  *
  * This file is part of xine, a free video player.
  *
@@ -268,8 +268,15 @@ struct vaapi_driver_s {
   unsigned int        scaling_level;
   va_property_t       props[VO_NUM_PROPERTIES];
   unsigned int        swap_uv_planes;
+
+  /* color matrix and fullrange emulation */
+  int                 cm_state, color_matrix, update_csc, vaapi_cm_flags;
 };
 
+/* import common color matrix stuff */
+#define CM_DRIVER_T vaapi_driver_t
+#include "color_matrix.c"
+
 ff_vaapi_surface_t  *va_render_surfaces   = NULL;
 VASurfaceID         *va_surface_ids       = NULL;
 VASurfaceID         *va_soft_surface_ids  = NULL;
@@ -1600,36 +1607,85 @@ error:
   return VA_STATUS_ERROR_UNKNOWN;
 }
 
-static inline int vaapi_get_colorspace_flags(vo_driver_t *this_gen)
-{
-  vaapi_driver_t      *this = (vaapi_driver_t *) this_gen;
-  ff_vaapi_context_t  *va_context = this->va_context;
+static void vaapi_update_csc (vaapi_driver_t *that, vaapi_frame_t *frame) {
+  int color_matrix;
 
-  if(!va_context)
-    return 0;
+  color_matrix = cm_from_frame (&frame->vo_frame);
 
-  int colorspace = 0;
-#if USE_VAAPI_COLORSPACE
-  switch (va_context->va_colorspace) {
-    case 0:
-      colorspace = ((va_context->sw_width >= 1280 || va_context->sw_height > 576) ?
-               VA_SRC_BT709 : VA_SRC_BT601);
-      break;
-    case 1:
-      colorspace = VA_SRC_BT601;
-      break;
-    case 2:
-      colorspace = VA_SRC_BT709;
-      break;
-    case 3:
-      colorspace = VA_SRC_SMPTE_240;
-      break;
-    default:
-      colorspace = VA_SRC_BT601;
-      break;
-  }
+  if (that->update_csc || that->color_matrix != color_matrix) {
+    int brightness = that->props[VO_PROP_BRIGHTNESS].value;
+    int contrast   = that->props[VO_PROP_CONTRAST].value;
+    int saturation = that->props[VO_PROP_SATURATION].value;
+    int hue        = that->props[VO_PROP_HUE].value;
+    VADisplayAttribute attr;
+
+#if defined(VA_SRC_BT601)
+    switch (color_matrix >> 1) {
+#if defined(VA_SRC_BT709)
+      case 1:  that->vaapi_cm_flags = VA_SRC_BT709;     break;
+#elif defined(VA_SRC_SMPTE_240)
+      case 1:  that->vaapi_cm_flags = VA_SRC_SMPTE_240; break;
+#endif
+#if defined(VA_SRC_SMPTE_240)
+      case 7:  that->vaapi_cm_flags = VA_SRC_SMPTE_240; break;
+#elif defined(VA_SRC_BT709)
+      case 7:  that->vaapi_cm_flags = VA_SRC_BT709;     break;
 #endif
-    return colorspace;
+      default: that->vaapi_cm_flags = VA_SRC_BT601;
+    }
+#endif
+
+    if (color_matrix & 1) {
+      int a, b;
+      /* fullrange mode. XXX assuming TV set style bcs controls 0% - 200% */
+      saturation -= that->props[VO_PROP_SATURATION].min;
+      saturation  = (saturation * (112 * 255) + (127 * 219 / 2)) / (127 * 219);
+      saturation += that->props[VO_PROP_SATURATION].min;
+      if (saturation > that->props[VO_PROP_SATURATION].max)
+        saturation = that->props[VO_PROP_SATURATION].max;
+
+      contrast -= that->props[VO_PROP_CONTRAST].min;
+      contrast  = (contrast * 219 + 127) / 255;
+      a         = contrast * (that->props[VO_PROP_BRIGHTNESS].max - that->props[VO_PROP_BRIGHTNESS].min);
+      contrast += that->props[VO_PROP_CONTRAST].min;
+      b         = 256 * (that->props[VO_PROP_CONTRAST].max - that->props[VO_PROP_CONTRAST].min);
+
+      brightness += (16 * a + b / 2) / b;
+      if (brightness > that->props[VO_PROP_BRIGHTNESS].max)
+        brightness = that->props[VO_PROP_BRIGHTNESS].max;
+    }
+
+    if (that->props[VO_PROP_BRIGHTNESS].atom) {
+      attr.type  = that->props[VO_PROP_BRIGHTNESS].type;
+      attr.value = brightness;
+      vaSetDisplayAttributes (that->va_context->va_display, &attr, 1);
+    }
+
+    if (that->props[VO_PROP_CONTRAST].atom) {
+      attr.type  = that->props[VO_PROP_CONTRAST].type;
+      attr.value = contrast;
+      vaSetDisplayAttributes (that->va_context->va_display, &attr, 1);
+    }
+
+    if (that->props[VO_PROP_SATURATION].atom) {
+      attr.type  = that->props[VO_PROP_SATURATION].type;
+      attr.value = saturation;
+      vaSetDisplayAttributes (that->va_context->va_display, &attr, 1);
+    }
+
+    if (that->props[VO_PROP_HUE].atom) {
+      attr.type  = that->props[VO_PROP_HUE].type;
+      attr.value = hue;
+      vaSetDisplayAttributes (that->va_context->va_display, &attr, 1);
+    }
+
+    that->color_matrix = color_matrix;
+    that->update_csc = 0;
+
+    xprintf (that->xine, XINE_VERBOSITY_LOG,"video_out_vaapi: %s b %d c %d s %d h %d [%s]\n",
+      color_matrix & 1 ? "modified" : "",
+      brightness, contrast, saturation, hue, cm_names[color_matrix]);
+  }
 }
 
 static void vaapi_property_callback (void *property_gen, xine_cfg_entry_t *entry) {
@@ -2615,6 +2671,9 @@ static int vaapi_redraw_needed (vo_drive
     ret = 1;
   }
 
+  if (this->update_csc)
+    ret = 1;
+
   return ret;
 }
 
@@ -3229,7 +3288,8 @@ static VAStatus vaapi_hardware_render_fr
   for(i = 0; i <= !!((deint > 1) && interlaced_frame); i++) {
     unsigned int flags = (deint && (interlaced_frame) ? (((!!(top_field_first)) ^ i) == 0 ? VA_BOTTOM_FIELD : VA_TOP_FIELD) : VA_FRAME_PICTURE);
 
-    //flags |= vaapi_get_colorspace_flags(this_gen);
+    vaapi_update_csc (this, frame);
+    flags |= this->vaapi_cm_flags;
 
     flags |= VA_CLEAR_DRAWABLE;
     flags |= this->scaling_level;
@@ -3524,6 +3584,8 @@ static void vaapi_display_frame (vo_driv
 static int vaapi_get_property (vo_driver_t *this_gen, int property) {
   vaapi_driver_t *this = (vaapi_driver_t *) this_gen;
 
+  if ((property < 0) || (property >= VO_NUM_PROPERTIES)) return 0;
+
   switch (property) {
     case VO_PROP_WINDOW_WIDTH:
       this->props[property].value = this->sc.gui_width;
@@ -3563,6 +3625,20 @@ static int vaapi_set_property (vo_driver
 
   lprintf("vaapi_set_property property=%d, value=%d\n", property, value );
 
+  if ((property < 0) || (property >= VO_NUM_PROPERTIES)) return 0;
+
+  if ((property == VO_PROP_BRIGHTNESS)
+    || (property == VO_PROP_CONTRAST)
+    || (property == VO_PROP_SATURATION)
+    || (property == VO_PROP_HUE)) {
+    /* defer these to vaapi_update_csc () */
+    if((value < this->props[property].min) || (value > this->props[property].max))
+      value = (this->props[property].min + this->props[property].max) >> 1;
+    this->props[property].value = value;
+    this->update_csc = 1;
+    return value;
+  }
+
   if(this->props[property].atom) {
     VADisplayAttribute attr;
 
@@ -3723,6 +3799,8 @@ static void vaapi_dispose_locked (vo_dri
   pthread_mutex_unlock(&this->vaapi_lock);
   pthread_mutex_destroy(&this->vaapi_lock);
 
+  cm_close (this);
+
   free (this);
 }
 
@@ -3981,6 +4059,9 @@ static vo_driver_t *vaapi_open_plugin (v
     this->props[i].this  = this;
   }
 
+  cm_init (this);
+  this->update_csc = 1;
+
   this->sc.user_ratio                        =
     this->props[VO_PROP_ASPECT_RATIO].value  = XINE_VO_ASPECT_AUTO;
   this->props[VO_PROP_ZOOM_X].value          = 100;
@@ -3999,6 +4080,12 @@ static vo_driver_t *vaapi_open_plugin (v
 
   pthread_mutex_unlock(&this->vaapi_lock);
 
+#if (defined VA_SRC_BT601) && ((defined VA_SRC_BT709) || (defined VA_SRC_SMPTE_240))
+  this->capabilities |= VO_CAP_COLOR_MATRIX;
+#endif
+  if ((this->capabilities & (VO_CAP_BRIGHTNESS | VO_CAP_CONTRAST)) == (VO_CAP_BRIGHTNESS | VO_CAP_CONTRAST))
+    this->capabilities |= VO_CAP_FULLRANGE;
+
   xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_open: Deinterlace : %d\n", this->deinterlace);
   xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_open: Render surfaces : %d\n", RENDER_SURFACES);
   xprintf(this->xine, XINE_VERBOSITY_LOG, LOG_MODULE " vaapi_open: Opengl render : %d\n", this->opengl_render);