st/vdpau: use matrix filter to blur/sharpen video
authorChristian König <deathsimple@vodafone.de>
Wed, 8 Feb 2012 18:23:33 +0000 (19:23 +0100)
committerChristian König <deathsimple@vodafone.de>
Fri, 10 Feb 2012 11:10:05 +0000 (12:10 +0100)
Signed-off-by: Christian König <deathsimple@vodafone.de>
src/gallium/state_trackers/vdpau/mixer.c
src/gallium/state_trackers/vdpau/query.c
src/gallium/state_trackers/vdpau/vdpau_private.h

index 87ebe978e5f84b05956b238753656131cb3e12b3..5ce40d619ed863597346225db6c720dbf9e1d6ac 100644 (file)
@@ -93,7 +93,10 @@ vlVdpVideoMixerCreate(VdpDevice device,
       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9:
       case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE:
       case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY:
+         break;
+
       case VDP_VIDEO_MIXER_FEATURE_SHARPNESS:
+         vmixer->sharpness.supported = true;
          break;
 
       case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION:
@@ -142,7 +145,6 @@ vlVdpVideoMixerCreate(VdpDevice device,
    }
    vmixer->luma_key_min = 0.f;
    vmixer->luma_key_max = 1.f;
-   vmixer->sharpness = 0.f;
 
    return VDP_STATUS_OK;
 
@@ -253,6 +255,10 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer,
       vl_median_filter_render(vmixer->noise_reduction.filter,
                               dst->sampler_view, dst->surface);
 
+   if (vmixer->sharpness.filter)
+      vl_matrix_filter_render(vmixer->sharpness.filter,
+                              dst->sampler_view, dst->surface);
+
    return VDP_STATUS_OK;
 }
 
@@ -282,6 +288,52 @@ vlVdpVideoMixerUpdateNoiseReductionFilter(vlVdpVideoMixer *vmixer)
    }
 }
 
+static void
+vlVdpVideoMixerUpdateSharpnessFilter(vlVdpVideoMixer *vmixer)
+{
+   assert(vmixer);
+
+   /* if present remove the old filter first */
+   if (vmixer->sharpness.filter) {
+      vl_matrix_filter_cleanup(vmixer->sharpness.filter);
+      FREE(vmixer->sharpness.filter);
+      vmixer->sharpness.filter = NULL;
+   }
+
+   /* and create a new filter as needed */
+   if (vmixer->sharpness.enabled && vmixer->sharpness.value != 0.0f) {
+      float matrix[9];
+      unsigned i;
+
+      if (vmixer->sharpness.value > 0.0f) {
+         matrix[0] = -1.0f; matrix[1] = -1.0f; matrix[2] = -1.0f;
+         matrix[3] = -1.0f; matrix[4] =  8.0f; matrix[5] = -1.0f;
+         matrix[6] = -1.0f; matrix[7] = -1.0f; matrix[8] = -1.0f;
+
+         for (i = 0; i < 9; ++i)
+            matrix[i] *= vmixer->sharpness.value;
+
+         matrix[4] += 1.0f;
+
+      } else {
+         matrix[0] = 1.0f; matrix[1] = 2.0f; matrix[2] = 1.0f;
+         matrix[3] = 2.0f; matrix[4] = 4.0f; matrix[5] = 2.0f;
+         matrix[6] = 1.0f; matrix[7] = 2.0f; matrix[8] = 1.0f;
+
+         for (i = 0; i < 9; ++i)
+               matrix[i] *= fabsf(vmixer->sharpness.value) / 16.0f;
+
+         matrix[4] += 1.0f - fabsf(vmixer->sharpness.value);
+      }
+
+      vmixer->sharpness.filter = MALLOC(sizeof(struct vl_matrix_filter));
+      vl_matrix_filter_init(vmixer->sharpness.filter,
+                            vmixer->device->context->pipe,
+                            vmixer->video_width, vmixer->video_height,
+                            3, 3, matrix);
+   }
+}
+
 /**
  * Retrieve whether features were requested at creation time.
  */
@@ -317,10 +369,13 @@ vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer,
       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9:
       case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE:
       case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY:
-      case VDP_VIDEO_MIXER_FEATURE_SHARPNESS:
          feature_supports[i] = false;
          break;
 
+      case VDP_VIDEO_MIXER_FEATURE_SHARPNESS:
+         feature_supports[i] = vmixer->sharpness.supported;
+         break;
+
       case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION:
          feature_supports[i] = vmixer->noise_reduction.supported;
          break;
@@ -368,7 +423,11 @@ vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer,
       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9:
       case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE:
       case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY:
+         break;
+
       case VDP_VIDEO_MIXER_FEATURE_SHARPNESS:
+         vmixer->sharpness.enabled = feature_enables[i];
+         vlVdpVideoMixerUpdateSharpnessFilter(vmixer);
          break;
 
       case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION:
@@ -419,12 +478,14 @@ vlVdpVideoMixerGetFeatureEnables(VdpVideoMixer mixer,
       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9:
       case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE:
       case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY:
+         break;
+
       case VDP_VIDEO_MIXER_FEATURE_SHARPNESS:
+         feature_enables[i] = vmixer->sharpness.enabled;
          break;
 
       case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION:
-         vmixer->noise_reduction.enabled = feature_enables[i];
-         vlVdpVideoMixerUpdateNoiseReductionFilter(vmixer);
+         feature_enables[i] = vmixer->noise_reduction.enabled;
          break;
 
       default:
@@ -500,12 +561,17 @@ vlVdpVideoMixerSetAttributeValues(VdpVideoMixer mixer,
             return VDP_STATUS_INVALID_VALUE;
          vmixer->luma_key_max = val;
          break;
+
       case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL:
+
          val = *(float*)attribute_values[i];
          if (val < -1.f || val > 1.f)
             return VDP_STATUS_INVALID_VALUE;
-         vmixer->sharpness = val;
+
+         vmixer->sharpness.value = val;
+         vlVdpVideoMixerUpdateSharpnessFilter(vmixer);
          break;
+
       case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE:
          if (*(uint8_t*)attribute_values[i] > 1)
             return VDP_STATUS_INVALID_VALUE;
@@ -602,7 +668,7 @@ vlVdpVideoMixerGetAttributeValues(VdpVideoMixer mixer,
          *(float*)attribute_values[i] = vmixer->luma_key_max;
          break;
       case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL:
-         *(float*)attribute_values[i] = vmixer->sharpness;
+         *(float*)attribute_values[i] = vmixer->sharpness.value;
          break;
       case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE:
          *(uint8_t*)attribute_values[i] = vmixer->skip_chroma_deint;
index 4110a877400689156ced974dc0fb9d48c4f30650..8bb2078e0a50fa76a4917654c0f32d3359bd86ae 100644 (file)
@@ -308,6 +308,7 @@ vlVdpVideoMixerQueryFeatureSupport(VdpDevice device, VdpVideoMixerFeature featur
       return VDP_STATUS_INVALID_POINTER;
 
    switch (feature) {
+   case VDP_VIDEO_MIXER_FEATURE_SHARPNESS:
    case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION:
       *is_supported = VDP_TRUE;
       break;
index 82e6a8e84d21fd088cb7c39d63f86793a3ae00c9..f47c0bf1a31ad36fbc11e4ea811de7edf7a691de 100644 (file)
@@ -39,6 +39,7 @@
 #include "util/u_debug.h"
 #include "util/u_rect.h"
 #include "vl/vl_compositor.h"
+#include "vl/vl_matrix_filter.h"
 #include "vl/vl_median_filter.h"
 
 #include "vl_winsys.h"
@@ -314,10 +315,16 @@ typedef struct
       struct vl_median_filter *filter;
    } noise_reduction;
 
+   struct {
+      bool supported, enabled;
+      float value;
+      struct vl_matrix_filter *filter;
+   } sharpness;
+
    unsigned video_width, video_height;
    enum pipe_video_chroma_format chroma_format;
    unsigned max_layers, skip_chroma_deint, custom_csc;
-   float luma_key_min, luma_key_max, sharpness;
+   float luma_key_min, luma_key_max;
    float csc[16];
 } vlVdpVideoMixer;