#include "vl/vl_defines.h"
#include "vl/vl_video_buffer.h"
+#include "vl/vl_deint_filter.h"
#include "va_private.h"
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)
{
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;
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;
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;
}
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);
}
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;
}
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;