diff options
author | Gwenole Beauchesne <gwenole.beauchesne@intel.com> | 2014-08-12 15:28:40 +0200 |
---|---|---|
committer | Gwenole Beauchesne <gwenole.beauchesne@intel.com> | 2014-10-28 11:37:37 +0100 |
commit | c400340d2ea597b6a9febbf95c9851c7171e1015 (patch) | |
tree | 18833369e719f9f04bf3d4b590a85cb60b53c655 /src | |
parent | c1aaeb7b27566afd1946df021efca44cad15b658 (diff) | |
download | libva-intel-driver-c400340d2ea597b6a9febbf95c9851c7171e1015.tar.gz |
vebox: add support for advanced deinterlacing.
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, which
is the most important fix.
https://bugs.freedesktop.org/show_bug.cgi?id=79698
https://bugs.freedesktop.org/show_bug.cgi?id=79528
Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/gen75_vpp_vebox.c | 101 | ||||
-rw-r--r-- | 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 9fdba4ac..a6d78dd7 100644 --- a/src/gen75_vpp_vebox.c +++ b/src/gen75_vpp_vebox.c @@ -835,6 +835,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) @@ -934,6 +953,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 */ @@ -979,6 +999,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; @@ -989,15 +1010,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) { @@ -1010,7 +1063,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; } @@ -1022,12 +1075,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; } @@ -1260,6 +1320,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; @@ -1294,6 +1355,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); @@ -1370,18 +1455,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 35c657de..d857b87e 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; }; |