[Libva] [PATCH intel-driver 10/13] vebox: add support for advanced deinterlacing.
Gwenole Beauchesne
gb.devel at gmail.com
Wed Aug 27 04:50:35 PDT 2014
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 <gwenole.beauchesne at intel.com>
---
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
More information about the Libva
mailing list