Reintegrate Motion Adaptive Deinterlacing (MADI) and Motion Compensated Deinterlacing (MCDI) support. This is totally reworked so that to allow for bob-deinterlacing if no previous frame was supplied, improve global robustness, and ensure that the right surface storage are used.
Signed-off-by: Gwenole Beauchesne <[email protected]> --- src/gen75_vpp_vebox.c | 101 ++++++++++++++++++++++++++++++++++++++++++------- src/gen75_vpp_vebox.h | 4 +- 2 files changed, 91 insertions(+), 14 deletions(-) diff --git a/src/gen75_vpp_vebox.c b/src/gen75_vpp_vebox.c index b060ae2..7e37d9c 100644 --- a/src/gen75_vpp_vebox.c +++ b/src/gen75_vpp_vebox.c @@ -836,6 +836,25 @@ void hsw_veb_dndi_iecp_command(VADriverContextP ctx, struct intel_vebox_context ADVANCE_VEB_BATCH(batch); } +static void +frame_store_reset(VEBFrameStore *fs) +{ + fs->obj_surface = NULL; + fs->surface_id = VA_INVALID_ID; + fs->is_internal_surface = 0; + fs->is_scratch_surface = 0; +} + +static void +frame_store_clear(VEBFrameStore *fs, VADriverContextP ctx) +{ + if (fs->obj_surface && fs->is_scratch_surface) { + VASurfaceID surface_id = fs->obj_surface->base.id; + i965_DestroySurfaces(ctx, &surface_id, 1); + } + frame_store_reset(fs); +} + static VAStatus gen75_vebox_ensure_surfaces_storage(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) @@ -935,6 +954,7 @@ gen75_vebox_ensure_surfaces_storage(VADriverContextP ctx, proc_ctx->frame_store[i].obj_surface = obj_surface; proc_ctx->frame_store[i].is_internal_surface = 1; + proc_ctx->frame_store[i].is_scratch_surface = 1; } /* Allocate DNDI state table */ @@ -980,6 +1000,7 @@ static VAStatus gen75_vebox_ensure_surfaces(VADriverContextP ctx, struct intel_vebox_context *proc_ctx) { + struct i965_driver_data * const i965 = i965_driver_data(ctx); struct object_surface *obj_surface; VEBFrameStore *ifs, *ofs; bool is_new_frame = 0; @@ -990,15 +1011,47 @@ gen75_vebox_ensure_surfaces(VADriverContextP ctx, is_new_frame = proc_ctx->frame_store[FRAME_IN_CURRENT].surface_id != obj_surface->base.id; + if (is_new_frame) { + ifs = &proc_ctx->frame_store[FRAME_IN_PREVIOUS]; + ofs = &proc_ctx->frame_store[proc_ctx->is_dn_enabled ? + FRAME_OUT_CURRENT_DN : FRAME_IN_CURRENT]; + do { + const VAProcPipelineParameterBuffer * const pipe = + proc_ctx->pipeline_param; + + if (pipe->num_forward_references < 1) + break; + if (pipe->forward_references[0] == VA_INVALID_ID) + break; + + obj_surface = SURFACE(pipe->forward_references[0]); + if (!obj_surface || obj_surface->base.id == ifs->surface_id) + break; + + frame_store_clear(ifs, ctx); + if (obj_surface->base.id == ofs->surface_id) { + *ifs = *ofs; + frame_store_reset(ofs); + } + else { + ifs->obj_surface = obj_surface; + ifs->surface_id = obj_surface->base.id; + ifs->is_internal_surface = 0; + ifs->is_scratch_surface = 0; + } + } while (0); + } /* Update the input surface */ obj_surface = proc_ctx->surface_input_vebox_object ? proc_ctx->surface_input_vebox_object : proc_ctx->surface_input_object; ifs = &proc_ctx->frame_store[FRAME_IN_CURRENT]; + frame_store_clear(ifs, ctx); ifs->obj_surface = obj_surface; ifs->surface_id = proc_ctx->surface_input_object->base.id; ifs->is_internal_surface = proc_ctx->surface_input_vebox_object != NULL; + ifs->is_scratch_surface = 0; /* Update the Spatial Temporal Motion Measure (STMM) surfaces */ if (is_new_frame) { @@ -1011,7 +1064,7 @@ gen75_vebox_ensure_surfaces(VADriverContextP ctx, /* Reset the output surfaces to defaults. i.e. clean from user surfaces */ for (i = FRAME_OUT_CURRENT_DN; i <= FRAME_OUT_PREVIOUS; i++) { ofs = &proc_ctx->frame_store[i]; - if (!ofs->is_internal_surface) + if (!ofs->is_scratch_surface) ofs->obj_surface = NULL; ofs->surface_id = proc_ctx->surface_input_object->base.id; } @@ -1023,12 +1076,19 @@ gen75_vebox_ensure_surfaces(VADriverContextP ctx, proc_ctx->current_output_type = 2; if (proc_ctx->filters_mask == VPP_DNDI_DN) proc_ctx->current_output = FRAME_OUT_CURRENT_DN; + else if (proc_ctx->is_di_adv_enabled && !proc_ctx->is_first_frame) { + proc_ctx->current_output_type = 0; + proc_ctx->current_output = proc_ctx->is_second_field ? + FRAME_OUT_CURRENT : FRAME_OUT_PREVIOUS; + } else proc_ctx->current_output = FRAME_OUT_CURRENT; ofs = &proc_ctx->frame_store[proc_ctx->current_output]; + frame_store_clear(ofs, ctx); ofs->obj_surface = obj_surface; ofs->surface_id = proc_ctx->surface_input_object->base.id; ofs->is_internal_surface = proc_ctx->surface_output_vebox_object != NULL; + ofs->is_scratch_surface = 0; return VA_STATUS_SUCCESS; } @@ -1261,6 +1321,7 @@ gen75_vebox_init_filter_params(VADriverContextP ctx, proc_ctx->is_iecp_enabled = (proc_ctx->filters_mask & VPP_IECP_MASK) != 0; proc_ctx->is_dn_enabled = (proc_ctx->filters_mask & VPP_DNDI_DN) != 0; proc_ctx->is_di_enabled = (proc_ctx->filters_mask & VPP_DNDI_DI) != 0; + proc_ctx->is_di_adv_enabled = 0; proc_ctx->is_first_frame = 0; proc_ctx->is_second_field = 0; @@ -1295,6 +1356,30 @@ gen75_vebox_init_filter_params(VADriverContextP ctx, case VAProcDeinterlacingBob: proc_ctx->is_first_frame = 1; break; + case VAProcDeinterlacingMotionAdaptive: + case VAProcDeinterlacingMotionCompensated: + if (proc_ctx->frame_store[FRAME_IN_CURRENT].surface_id == VA_INVALID_ID) + proc_ctx->is_first_frame = 1; + else if (proc_ctx->is_second_field) { + /* At this stage, we have already deinterlaced the + first field successfully. So, the first frame flag + is trigerred if the previous field was deinterlaced + without reference frame */ + if (proc_ctx->frame_store[FRAME_IN_PREVIOUS].surface_id == VA_INVALID_ID) + proc_ctx->is_first_frame = 1; + } + else { + const VAProcPipelineParameterBuffer * const pipe = + proc_ctx->pipeline_param; + + if (pipe->num_forward_references < 1 || + pipe->forward_references[0] == VA_INVALID_ID) { + WARN_ONCE("A forward temporal reference is needed for Motion adaptive/compensated deinterlacing !!!\n"); + return VA_STATUS_ERROR_INVALID_PARAMETER; + } + } + proc_ctx->is_di_adv_enabled = 1; + break; default: WARN_ONCE("unsupported deinterlacing algorithm (%d)\n", deint_params->algorithm); @@ -1371,18 +1456,8 @@ void gen75_vebox_context_destroy(VADriverContextP ctx, proc_ctx->surface_output_scaled_object = NULL; } - for (i = 0; i < ARRAY_ELEMS(proc_ctx->frame_store); i++) { - struct object_surface * const obj_surface = - proc_ctx->frame_store[i].obj_surface; - - if (proc_ctx->frame_store[i].is_internal_surface && obj_surface) { - VASurfaceID surface_id = obj_surface->base.id; - i965_DestroySurfaces(ctx, &surface_id, 1); - } - proc_ctx->frame_store[i].obj_surface = NULL; - proc_ctx->frame_store[i].surface_id = VA_INVALID_ID; - proc_ctx->frame_store[i].is_internal_surface = 0; - } + for (i = 0; i < ARRAY_ELEMS(proc_ctx->frame_store); i++) + frame_store_clear(&proc_ctx->frame_store[i], ctx); /* dndi state table */ dri_bo_unreference(proc_ctx->dndi_state_table.bo); diff --git a/src/gen75_vpp_vebox.h b/src/gen75_vpp_vebox.h index 35c657d..d857b87 100644 --- a/src/gen75_vpp_vebox.h +++ b/src/gen75_vpp_vebox.h @@ -91,7 +91,8 @@ enum SURFACE_FORMAT{ typedef struct veb_frame_store { struct object_surface *obj_surface; VASurfaceID surface_id; /* always relative to the input surface */ - unsigned int is_internal_surface; + unsigned int is_internal_surface : 1; + unsigned int is_scratch_surface : 1; } VEBFrameStore; typedef struct veb_buffer { @@ -147,6 +148,7 @@ struct intel_vebox_context unsigned int is_iecp_enabled : 1; unsigned int is_dn_enabled : 1; unsigned int is_di_enabled : 1; + unsigned int is_di_adv_enabled : 1; unsigned int is_first_frame : 1; unsigned int is_second_field : 1; }; -- 1.7.9.5 _______________________________________________ Libva mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libva
