[Mesa-dev] [PATCH 9/9] st/va: add motion adaptive deinterlacing

Christian König deathsimple at vodafone.de
Wed Dec 16 12:14:41 PST 2015


From: Christian König <christian.koenig at amd.com>

Signed-off-by: Christian König <christian.koenig at amd.com>
---
 src/gallium/state_trackers/va/context.c    |  5 +++
 src/gallium/state_trackers/va/postproc.c   | 63 ++++++++++++++++++++++++++++--
 src/gallium/state_trackers/va/surface.c    | 22 +++++++++--
 src/gallium/state_trackers/va/va_private.h |  2 +
 4 files changed, 85 insertions(+), 7 deletions(-)

diff --git a/src/gallium/state_trackers/va/context.c b/src/gallium/state_trackers/va/context.c
index 37a0117..b25c381 100644
--- a/src/gallium/state_trackers/va/context.c
+++ b/src/gallium/state_trackers/va/context.c
@@ -31,6 +31,7 @@
 #include "util/u_memory.h"
 #include "util/u_handle_table.h"
 #include "util/u_video.h"
+#include "vl/vl_deint_filter.h"
 #include "vl/vl_winsys.h"
 
 #include "va_private.h"
@@ -296,6 +297,10 @@ vlVaDestroyContext(VADriverContextP ctx, VAContextID context_id)
       }
       context->decoder->destroy(context->decoder);
    }
+   if (context->deint) {
+      vl_deint_filter_cleanup(context->deint);
+      FREE(context->deint);
+   }
    FREE(context);
    handle_table_remove(drv->htab, context_id);
    pipe_mutex_unlock(drv->mutex);
diff --git a/src/gallium/state_trackers/va/postproc.c b/src/gallium/state_trackers/va/postproc.c
index 0cec0c8..b88d701 100644
--- a/src/gallium/state_trackers/va/postproc.c
+++ b/src/gallium/state_trackers/va/postproc.c
@@ -29,6 +29,7 @@
 
 #include "vl/vl_defines.h"
 #include "vl/vl_video_buffer.h"
+#include "vl/vl_deint_filter.h"
 
 #include "va_private.h"
 
@@ -174,6 +175,51 @@ static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
    return VA_STATUS_SUCCESS;
 }
 
+static struct pipe_video_buffer *
+vlVaApplyDeint(vlVaDriver *drv, vlVaContext *context,
+               VAProcPipelineParameterBuffer *param,
+               struct pipe_video_buffer *current,
+               unsigned field)
+{
+   vlVaSurface *prevprev, *prev, *next;
+
+   if (param->num_forward_references < 1 ||
+       param->num_backward_references < 2)
+      return current;
+
+   prevprev = handle_table_get(drv->htab, param->backward_references[1]);
+   prev = handle_table_get(drv->htab, param->backward_references[0]);
+   next = handle_table_get(drv->htab, param->forward_references[0]);
+
+   if (!prevprev || !prev || !next)
+      return current;
+
+   if (context->deint && (context->deint->video_width != current->width ||
+       context->deint->video_height != current->height)) {
+      vl_deint_filter_cleanup(context->deint);
+      FREE(context->deint);
+      context->deint = NULL;
+   }
+
+   if (!context->deint) {
+      context->deint = MALLOC(sizeof(struct vl_deint_filter));
+      if (!vl_deint_filter_init(context->deint, drv->pipe, current->width,
+                                current->height, false, false)) {
+         FREE(context->deint);
+         context->deint = NULL;
+         return current;
+      }
+   }
+
+   if (!vl_deint_filter_check_buffers(context->deint, prevprev->buffer,
+                                      prev->buffer, current, next->buffer))
+      return current;
+
+   vl_deint_filter_render(context->deint, prevprev->buffer, prev->buffer,
+                          current, next->buffer, field);
+   return context->deint->video_buffer;
+}
+
 VAStatus
 vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
 {
@@ -181,6 +227,7 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
    VARectangle def_src_region, def_dst_region;
    const VARectangle *src_region, *dst_region;
    VAProcPipelineParameterBuffer *param;
+   struct pipe_video_buffer *src;
    vlVaSurface *src_surface;
    unsigned i;
 
@@ -199,6 +246,8 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
    if (!src_surface || !src_surface->buffer)
       return VA_STATUS_ERROR_INVALID_SURFACE;
 
+   src = src_surface->buffer;
+
    for (i = 0; i < param->num_filters; i++) {
       vlVaBuffer *buf = handle_table_get(drv->htab, param->filters[i]);
       VAProcFilterParameterBufferBase *filter;
@@ -222,6 +271,14 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
             deinterlace = VL_COMPOSITOR_WEAVE;
             break;
 
+         case VAProcDeinterlacingMotionAdaptive:
+            if (deint->flags & VA_DEINTERLACING_BOTTOM_FIELD)
+               src = vlVaApplyDeint(drv, context, param, src, 1);
+            else
+               src = vlVaApplyDeint(drv, context, param, src, 0);
+            deinterlace = VL_COMPOSITOR_WEAVE;
+            break;
+
          default:
             return VA_STATUS_ERROR_UNIMPLEMENTED;
          }
@@ -239,10 +296,8 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
 
    if (context->target->buffer_format != PIPE_FORMAT_NV12)
       return vlVaPostProcCompositor(drv, context, src_region, dst_region,
-                                    src_surface->buffer, context->target,
-                                    deinterlace);
+                                    src, context->target, deinterlace);
    else
       return vlVaPostProcBlit(drv, context, src_region, dst_region,
-                              src_surface->buffer, context->target,
-                              deinterlace);
+                              src, context->target, deinterlace);
 }
diff --git a/src/gallium/state_trackers/va/surface.c b/src/gallium/state_trackers/va/surface.c
index f23a889..84a9494 100644
--- a/src/gallium/state_trackers/va/surface.c
+++ b/src/gallium/state_trackers/va/surface.c
@@ -691,13 +691,14 @@ vlVaQueryVideoProcFilterCaps(VADriverContextP ctx, VAContextID context,
    case VAProcFilterDeinterlacing: {
       VAProcFilterCapDeinterlacing *deint = filter_caps;
 
-      if (*num_filter_caps < 2) {
-         *num_filter_caps = 2;
+      if (*num_filter_caps < 3) {
+         *num_filter_caps = 3;
          return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
       }
 
       deint[i++].type = VAProcDeinterlacingBob;
       deint[i++].type = VAProcDeinterlacingWeave;
+      deint[i++].type = VAProcDeinterlacingMotionAdaptive;
       break;
    }
 
@@ -750,9 +751,24 @@ vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID context,
 
    for (i = 0; i < num_filters; i++) {
       vlVaBuffer *buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, filters[i]);
+      VAProcFilterParameterBufferBase *filter;
 
-      if (!buf || buf->type >= VABufferTypeMax)
+      if (!buf || buf->type != VAProcFilterParameterBufferType)
          return VA_STATUS_ERROR_INVALID_BUFFER;
+
+      filter = buf->data;
+      switch (filter->type) {
+      case VAProcFilterDeinterlacing: {
+         VAProcFilterParameterBufferDeinterlacing *deint = buf->data;
+         if (deint->algorithm == VAProcDeinterlacingMotionAdaptive) {
+            pipeline_cap->num_forward_references = 1;
+            pipeline_cap->num_backward_references = 2;
+         }
+         break;
+      }
+      default:
+         return VA_STATUS_ERROR_UNIMPLEMENTED;
+      }
    }
 
    return VA_STATUS_SUCCESS;
diff --git a/src/gallium/state_trackers/va/va_private.h b/src/gallium/state_trackers/va/va_private.h
index 204db16..ef3c4aa 100644
--- a/src/gallium/state_trackers/va/va_private.h
+++ b/src/gallium/state_trackers/va/va_private.h
@@ -236,6 +236,8 @@ typedef struct {
       VAPictureParameterBufferMPEG4 pps;
       uint8_t start_code[32];
    } mpeg4;
+
+   struct vl_deint_filter *deint;
 } vlVaContext;
 
 typedef struct {
-- 
2.5.0



More information about the mesa-dev mailing list