[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