st/vdpau: add support for DEINTERLACE_TEMPORAL
authorGrigori Goronzy <greg@chown.ath.cx>
Thu, 13 Feb 2014 20:32:30 +0000 (21:32 +0100)
committerChristian König <christian.koenig@amd.com>
Fri, 14 Feb 2014 08:05:20 +0000 (09:05 +0100)
Reviewed-by: Christian König <christian.koenig@amd.com>
src/gallium/state_trackers/vdpau/mixer.c
src/gallium/state_trackers/vdpau/query.c
src/gallium/state_trackers/vdpau/vdpau_private.h

index 00958280bd2256d4fe72ba303d80026591e9f460..996fd8e1602ac828d2ff0979c1d8464d85960fcf 100644 (file)
@@ -80,7 +80,6 @@ vlVdpVideoMixerCreate(VdpDevice device,
    for (i = 0; i < feature_count; ++i) {
       switch (features[i]) {
       /* they are valid, but we doesn't support them */
-      case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL:
       case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL:
       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1:
       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2:
@@ -95,6 +94,10 @@ vlVdpVideoMixerCreate(VdpDevice device,
       case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY:
          break;
 
+      case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL:
+         vmixer->deint.supported = true;
+         break;
+
       case VDP_VIDEO_MIXER_FEATURE_SHARPNESS:
          vmixer->sharpness.supported = true;
          break;
@@ -181,6 +184,11 @@ vlVdpVideoMixerDestroy(VdpVideoMixer mixer)
 
    vl_compositor_cleanup_state(&vmixer->cstate);
 
+   if (vmixer->deint.filter) {
+      vl_deint_filter_cleanup(vmixer->deint.filter);
+      FREE(vmixer->deint.filter);
+   }
+
    if (vmixer->noise_reduction.filter) {
       vl_median_filter_cleanup(vmixer->noise_reduction.filter);
       FREE(vmixer->noise_reduction.filter);
@@ -219,6 +227,7 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer,
    enum vl_compositor_deinterlace deinterlace;
    struct u_rect rect, clip, *prect;
    unsigned i, layer = 0;
+   struct pipe_video_buffer *video_buffer;
 
    vlVdpVideoMixer *vmixer;
    vlVdpSurface *surf;
@@ -233,6 +242,7 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer,
    compositor = &vmixer->device->compositor;
 
    surf = vlGetDataHTAB(video_surface_current);
+   video_buffer = surf->video_buffer;
    if (!surf)
       return VDP_STATUS_INVALID_HANDLE;
 
@@ -283,6 +293,24 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer,
       pipe_mutex_unlock(vmixer->device->mutex);
       return VDP_STATUS_INVALID_VIDEO_MIXER_PICTURE_STRUCTURE;
    };
+
+   if (deinterlace != VL_COMPOSITOR_WEAVE && vmixer->deint.enabled &&
+       video_surface_past_count > 1 && video_surface_future_count > 0) {
+      vlVdpSurface *prevprev = vlGetDataHTAB(video_surface_past[1]);
+      vlVdpSurface *prev = vlGetDataHTAB(video_surface_past[0]);
+      vlVdpSurface *next = vlGetDataHTAB(video_surface_future[0]);
+      if (prevprev && prev && next &&
+          vl_deint_filter_check_buffers(vmixer->deint.filter,
+          prevprev->video_buffer, prev->video_buffer, surf->video_buffer, next->video_buffer)) {
+         vl_deint_filter_render(vmixer->deint.filter, prevprev->video_buffer,
+                                prev->video_buffer, surf->video_buffer,
+                                next->video_buffer,
+                                deinterlace == VL_COMPOSITOR_BOB_BOTTOM);
+         deinterlace = VL_COMPOSITOR_WEAVE;
+         video_buffer = vmixer->deint.filter->video_buffer;
+      }
+   }
+
    prect = RectToPipe(video_source_rect, &rect);
    if (!prect) {
       rect.x0 = 0;
@@ -291,7 +319,7 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer,
       rect.y1 = surf->templat.height;
       prect = &rect;
    }
-   vl_compositor_set_buffer_layer(&vmixer->cstate, compositor, layer, surf->video_buffer, prect, NULL, deinterlace);
+   vl_compositor_set_buffer_layer(&vmixer->cstate, compositor, layer, video_buffer, prect, NULL, deinterlace);
    vl_compositor_set_layer_dst_area(&vmixer->cstate, layer++, RectToPipe(destination_video_rect, &rect));
 
    for (i = 0; i < layer_count; ++i) {
@@ -332,6 +360,31 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer,
    return VDP_STATUS_OK;
 }
 
+static void
+vlVdpVideoMixerUpdateDeinterlaceFilter(vlVdpVideoMixer *vmixer)
+{
+   struct pipe_context *pipe = vmixer->device->context;
+   assert(vmixer);
+
+   /* remove existing filter */
+   if (vmixer->deint.filter) {
+      vl_deint_filter_cleanup(vmixer->deint.filter);
+      FREE(vmixer->deint.filter);
+      vmixer->deint.filter = NULL;
+   }
+
+   /* create a new filter if requested */
+   if (vmixer->deint.enabled && vmixer->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) {
+      vmixer->deint.filter = MALLOC(sizeof(struct vl_deint_filter));
+      vmixer->deint.enabled = vl_deint_filter_init(vmixer->deint.filter, pipe,
+            vmixer->video_width, vmixer->video_height,
+            vmixer->skip_chroma_deint, vmixer->deint.spatial);
+      if (!vmixer->deint.enabled) {
+         FREE(vmixer->deint.filter);
+      }
+   }
+}
+
 /**
  * Update the noise reduction setting
  */
@@ -424,7 +477,6 @@ vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer,
    for (i = 0; i < feature_count; ++i) {
       switch (features[i]) {
       /* they are valid, but we doesn't support them */
-      case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL:
       case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL:
       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1:
       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2:
@@ -440,6 +492,10 @@ vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer,
          feature_supports[i] = false;
          break;
 
+      case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL:
+         feature_supports[i] = vmixer->deint.supported;
+         break;
+
       case VDP_VIDEO_MIXER_FEATURE_SHARPNESS:
          feature_supports[i] = vmixer->sharpness.supported;
          break;
@@ -479,7 +535,6 @@ vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer,
    for (i = 0; i < feature_count; ++i) {
       switch (features[i]) {
       /* they are valid, but we doesn't support them */
-      case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL:
       case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL:
       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1:
       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2:
@@ -494,6 +549,11 @@ vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer,
       case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY:
          break;
 
+      case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL:
+         vmixer->deint.enabled = feature_enables[i];
+         vlVdpVideoMixerUpdateDeinterlaceFilter(vmixer);
+         break;
+
       case VDP_VIDEO_MIXER_FEATURE_SHARPNESS:
          vmixer->sharpness.enabled = feature_enables[i];
          vlVdpVideoMixerUpdateSharpnessFilter(vmixer);
@@ -648,6 +708,7 @@ vlVdpVideoMixerSetAttributeValues(VdpVideoMixer mixer,
          if (*(uint8_t*)attribute_values[i] > 1)
             return VDP_STATUS_INVALID_VALUE;
          vmixer->skip_chroma_deint = *(uint8_t*)attribute_values[i];
+         vlVdpVideoMixerUpdateDeinterlaceFilter(vmixer);
          break;
       default:
          pipe_mutex_unlock(vmixer->device->mutex);
index e312aa31948d439036d292d4a5b33cf263906d8e..d41e6d950a744d6c7115e06df07f651659b2517f 100644 (file)
@@ -469,6 +469,7 @@ vlVdpVideoMixerQueryFeatureSupport(VdpDevice device, VdpVideoMixerFeature featur
    switch (feature) {
    case VDP_VIDEO_MIXER_FEATURE_SHARPNESS:
    case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION:
+   case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL:
       *is_supported = VDP_TRUE;
       break;
    default:
index 2f4d651a906ae48109bea97767134284b531a962..078f0f9270cfe087f1b301bdab523690ee6ba473 100644 (file)
 #include "util/u_rect.h"
 #include "os/os_thread.h"
 
+#include "vl/vl_video_buffer.h"
 #include "vl/vl_compositor.h"
 #include "vl/vl_csc.h"
+#include "vl/vl_deint_filter.h"
 #include "vl/vl_matrix_filter.h"
 #include "vl/vl_median_filter.h"
 #include "vl/vl_winsys.h"
@@ -358,6 +360,11 @@ typedef struct
    vlVdpDevice *device;
    struct vl_compositor_state cstate;
 
+   struct {
+         bool supported, enabled, spatial;
+         struct vl_deint_filter *filter;
+   } deint;
+
    struct {
       bool supported, enabled;
       unsigned level;