st/va: add BOB deinterlacing v2
authorChristian König <christian.koenig@amd.com>
Tue, 8 Dec 2015 12:18:43 +0000 (13:18 +0100)
committerChristian König <christian.koenig@amd.com>
Tue, 12 Jan 2016 12:28:35 +0000 (13:28 +0100)
Tested with MPV.

v2: correctly handle compositor deinterlacing as well.

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
src/gallium/state_trackers/va/postproc.c
src/gallium/state_trackers/va/surface.c

index 51c54a20ee801fa181fa81971d26f51f7d633f73..0cec0c88124eb6b7476359831ee3f1cf43297636 100644 (file)
@@ -52,7 +52,8 @@ vlVaPostProcCompositor(vlVaDriver *drv, vlVaContext *context,
                        const VARectangle *src_region,
                        const VARectangle *dst_region,
                        struct pipe_video_buffer *src,
-                       struct pipe_video_buffer *dst)
+                       struct pipe_video_buffer *dst,
+                       enum vl_compositor_deinterlace deinterlace)
 {
    struct pipe_surface **surfaces;
    struct u_rect src_rect;
@@ -74,7 +75,7 @@ vlVaPostProcCompositor(vlVaDriver *drv, vlVaContext *context,
 
    vl_compositor_clear_layers(&drv->cstate);
    vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, src,
-                                 &src_rect, NULL, VL_COMPOSITOR_WEAVE);
+                                 &src_rect, NULL, deinterlace);
    vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dst_rect);
    vl_compositor_render(&drv->cstate, &drv->compositor, surfaces[0], NULL, false);
 
@@ -107,7 +108,8 @@ static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
                                  const VARectangle *src_region,
                                  const VARectangle *dst_region,
                                  struct pipe_video_buffer *src,
-                                 struct pipe_video_buffer *dst)
+                                 struct pipe_video_buffer *dst,
+                                 enum vl_compositor_deinterlace deinterlace)
 {
    struct pipe_surface **src_surfaces;
    struct pipe_surface **dst_surfaces;
@@ -125,16 +127,31 @@ static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
       return VA_STATUS_ERROR_INVALID_SURFACE;
 
    for (i = 0; i < VL_MAX_SURFACES; ++i) {
+      struct pipe_surface *from = src_surfaces[i];
       struct pipe_blit_info blit;
 
-      if (!src_surfaces[i] || !dst_surfaces[i])
+      if (src->interlaced) {
+         /* Not 100% accurate, but close enough */
+         switch (deinterlace) {
+         case VL_COMPOSITOR_BOB_TOP:
+            from = src_surfaces[i & ~1];
+            break;
+         case VL_COMPOSITOR_BOB_BOTTOM:
+            from = src_surfaces[(i & ~1) + 1];
+            break;
+         default:
+            break;
+         }
+      }
+
+      if (!from || !dst_surfaces[i])
          continue;
 
       memset(&blit, 0, sizeof(blit));
-      blit.src.resource = src_surfaces[i]->texture;
-      blit.src.format = src_surfaces[i]->format;
+      blit.src.resource = from->texture;
+      blit.src.format = from->format;
       blit.src.level = 0;
-      blit.src.box.z = src_surfaces[i]->u.tex.first_layer;
+      blit.src.box.z = from->u.tex.first_layer;
       blit.src.box.depth = 1;
       vlVaGetBox(src, i, &blit.src.box, src_region);
 
@@ -160,10 +177,12 @@ static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
 VAStatus
 vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
 {
+   enum vl_compositor_deinterlace deinterlace = VL_COMPOSITOR_WEAVE;
    VARectangle def_src_region, def_dst_region;
    const VARectangle *src_region, *dst_region;
    VAProcPipelineParameterBuffer *param;
    vlVaSurface *src_surface;
+   unsigned i;
 
    if (!drv || !context)
       return VA_STATUS_ERROR_INVALID_CONTEXT;
@@ -180,13 +199,50 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
    if (!src_surface || !src_surface->buffer)
       return VA_STATUS_ERROR_INVALID_SURFACE;
 
+   for (i = 0; i < param->num_filters; i++) {
+      vlVaBuffer *buf = handle_table_get(drv->htab, param->filters[i]);
+      VAProcFilterParameterBufferBase *filter;
+
+      if (!buf || buf->type != VAProcFilterParameterBufferType)
+         return VA_STATUS_ERROR_INVALID_BUFFER;
+
+      filter = buf->data;
+      switch (filter->type) {
+      case VAProcFilterDeinterlacing: {
+         VAProcFilterParameterBufferDeinterlacing *deint = buf->data;
+         switch (deint->algorithm) {
+         case VAProcDeinterlacingBob:
+            if (deint->flags & VA_DEINTERLACING_BOTTOM_FIELD)
+               deinterlace = VL_COMPOSITOR_BOB_BOTTOM;
+            else
+               deinterlace = VL_COMPOSITOR_BOB_TOP;
+            break;
+
+         case VAProcDeinterlacingWeave:
+            deinterlace = VL_COMPOSITOR_WEAVE;
+            break;
+
+         default:
+            return VA_STATUS_ERROR_UNIMPLEMENTED;
+         }
+
+         break;
+      }
+
+      default:
+         return VA_STATUS_ERROR_UNIMPLEMENTED;
+      }
+   }
+
    src_region = vlVaRegionDefault(param->surface_region, src_surface->buffer, &def_src_region);
    dst_region = vlVaRegionDefault(param->output_region, context->target, &def_dst_region);
 
    if (context->target->buffer_format != PIPE_FORMAT_NV12)
       return vlVaPostProcCompositor(drv, context, src_region, dst_region,
-                                    src_surface->buffer, context->target);
+                                    src_surface->buffer, context->target,
+                                    deinterlace);
    else
       return vlVaPostProcBlit(drv, context, src_region, dst_region,
-                              src_surface->buffer, context->target);
+                              src_surface->buffer, context->target,
+                              deinterlace);
 }
index cead10b6bd81f0947108ef30967ed42ef8210c49..f23a88901f54cc951e13ccb1a2d6e1f3114ace60 100644 (file)
@@ -663,7 +663,7 @@ vlVaQueryVideoProcFilters(VADriverContextP ctx, VAContextID context,
    if (!num_filters || !filters)
       return VA_STATUS_ERROR_INVALID_PARAMETER;
 
-   filters[num++] = VAProcFilterNone;
+   filters[num++] = VAProcFilterDeinterlacing;
 
    *num_filters = num;
 
@@ -688,8 +688,20 @@ vlVaQueryVideoProcFilterCaps(VADriverContextP ctx, VAContextID context,
    switch (type) {
    case VAProcFilterNone:
       break;
+   case VAProcFilterDeinterlacing: {
+      VAProcFilterCapDeinterlacing *deint = filter_caps;
+
+      if (*num_filter_caps < 2) {
+         *num_filter_caps = 2;
+         return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
+      }
+
+      deint[i++].type = VAProcDeinterlacingBob;
+      deint[i++].type = VAProcDeinterlacingWeave;
+      break;
+   }
+
    case VAProcFilterNoiseReduction:
-   case VAProcFilterDeinterlacing:
    case VAProcFilterSharpening:
    case VAProcFilterColorBalance:
    case VAProcFilterSkinToneEnhancement: