From: Christian König Date: Tue, 8 Dec 2015 12:18:43 +0000 (+0100) Subject: st/va: add BOB deinterlacing v2 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e945235aed86f473f27362bae902fbe67d5f0f20;p=mesa.git st/va: add BOB deinterlacing v2 Tested with MPV. v2: correctly handle compositor deinterlacing as well. Signed-off-by: Christian König Reviewed-by: Emil Velikov --- diff --git a/src/gallium/state_trackers/va/postproc.c b/src/gallium/state_trackers/va/postproc.c index 51c54a20ee8..0cec0c88124 100644 --- a/src/gallium/state_trackers/va/postproc.c +++ b/src/gallium/state_trackers/va/postproc.c @@ -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); } diff --git a/src/gallium/state_trackers/va/surface.c b/src/gallium/state_trackers/va/surface.c index cead10b6bd8..f23a88901f5 100644 --- a/src/gallium/state_trackers/va/surface.c +++ b/src/gallium/state_trackers/va/surface.c @@ -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: