summaryrefslogtreecommitdiffstats
path: root/src/gallium/state_trackers/va/postproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers/va/postproc.c')
-rw-r--r--src/gallium/state_trackers/va/postproc.c60
1 files changed, 56 insertions, 4 deletions
diff --git a/src/gallium/state_trackers/va/postproc.c b/src/gallium/state_trackers/va/postproc.c
index 0cec0c88124..f541f7c8aeb 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,11 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
deinterlace = VL_COMPOSITOR_WEAVE;
break;
+ case VAProcDeinterlacingMotionAdaptive:
+ src = vlVaApplyDeint(drv, context, param, src,
+ deint->flags & VA_DEINTERLACING_BOTTOM_FIELD);
+ break;
+
default:
return VA_STATUS_ERROR_UNIMPLEMENTED;
}
@@ -239,10 +293,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);
}