Add support for I420, YV12 etc. formatted YUV surface for encoding
authorXiang, Haihao <haihao.xiang@intel.com>
Wed, 1 Feb 2012 06:26:51 +0000 (14:26 +0800)
committerXiang, Haihao <haihao.xiang@intel.com>
Wed, 1 Feb 2012 06:38:38 +0000 (14:38 +0800)
MFX only supports NV12 formatted YUV surface, so the driver converts
I420/YV12 formatted surface to NV12 surface internally.

Signed-off-by: Xiang, Haihao <haihao.xiang@intel.com>
src/gen6_mfc.c
src/gen6_vme.c
src/gen7_mfc.c
src/i965_encoder.c
src/i965_encoder.h

index b90596b..abc9a92 100644 (file)
@@ -945,7 +945,7 @@ static VAStatus gen6_mfc_avc_prepare(VADriverContextP ctx,
         }
     }
        
-    obj_surface = SURFACE(encode_state->current_render_target);
+    obj_surface = SURFACE(encoder_context->input_yuv_surface);
     assert(obj_surface && obj_surface->bo);
     mfc_context->uncompressed_picture_source.bo = obj_surface->bo;
     dri_bo_reference(mfc_context->uncompressed_picture_source.bo);
index 5446ff3..695d326 100644 (file)
@@ -314,7 +314,7 @@ static VAStatus gen6_vme_surface_setup(VADriverContextP ctx,
 
     /*Setup surfaces state*/
     /* current picture for encoding */
-    obj_surface = SURFACE(encode_state->current_render_target);
+    obj_surface = SURFACE(encoder_context->input_yuv_surface);
     assert(obj_surface);
     gen6_vme_source_surface_state(ctx, 0, obj_surface, encoder_context);
     gen6_vme_media_source_surface_state(ctx, 4, obj_surface, encoder_context);
@@ -556,7 +556,7 @@ static VAStatus gen7_vme_surface_setup(VADriverContextP ctx,
 
     /*Setup surfaces state*/
     /* current picture for encoding */
-    obj_surface = SURFACE(encode_state->current_render_target);
+    obj_surface = SURFACE(encoder_context->input_yuv_surface);
     assert(obj_surface);
     gen7_vme_source_surface_state(ctx, 1, obj_surface, encoder_context);
     gen7_vme_media_source_surface_state(ctx, 4, obj_surface, encoder_context);
@@ -784,7 +784,7 @@ static int gen6_vme_media_object(VADriverContextP ctx,
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct intel_batchbuffer *batch = encoder_context->base.batch;
-    struct object_surface *obj_surface = SURFACE(encode_state->current_render_target);
+    struct object_surface *obj_surface = SURFACE(encoder_context->input_yuv_surface);
     VAEncPictureParameterBufferH264 *pPicParameter = (VAEncPictureParameterBufferH264 *)encode_state->pic_param_ext->buffer;
     int mb_width = ALIGN(obj_surface->orig_width, 16) / 16;
     int len_in_dowrds = 6 + 2;      /*6 + n: n is number of inline data*/
index ecfe27f..d55ec54 100644 (file)
@@ -1002,7 +1002,7 @@ gen7_mfc_avc_prepare(VADriverContextP ctx,
         }
     }
        
-    obj_surface = SURFACE(encode_state->current_render_target);
+    obj_surface = SURFACE(encoder_context->input_yuv_surface);
     assert(obj_surface && obj_surface->bo);
     mfc_context->uncompressed_picture_source.bo = obj_surface->bo;
     dri_bo_reference(mfc_context->uncompressed_picture_source.bo);
index 7a8390b..0723cbf 100644 (file)
@@ -42,6 +42,83 @@ extern Bool gen6_mfc_context_init(VADriverContextP ctx, struct intel_encoder_con
 extern Bool gen6_vme_context_init(VADriverContextP ctx, struct intel_encoder_context *encoder_context);
 extern Bool gen7_mfc_context_init(VADriverContextP ctx, struct intel_encoder_context *encoder_context);
 
+VAStatus 
+i965_DestroySurfaces(VADriverContextP ctx,
+                     VASurfaceID *surface_list,
+                     int num_surfaces);
+VAStatus 
+i965_CreateSurfaces(VADriverContextP ctx,
+                    int width,
+                    int height,
+                    int format,
+                    int num_surfaces,
+                    VASurfaceID *surfaces);
+
+static void
+intel_encoder_check_yuv_surface(VADriverContextP ctx,
+                                VAProfile profile,
+                                struct encode_state *encode_state,
+                                struct intel_encoder_context *encoder_context)
+{
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+    struct i965_surface src_surface, dst_surface;
+    struct object_surface *obj_surface;
+    VAStatus status;
+    VARectangle rect;
+
+    /* releae the temporary surface */
+    if (encoder_context->is_tmp_id) {
+        i965_DestroySurfaces(ctx, &encoder_context->input_yuv_surface, 1);
+    }
+
+    encoder_context->is_tmp_id = 0;
+    obj_surface = SURFACE(encode_state->current_render_target);
+    assert(obj_surface && obj_surface->bo);
+
+    if (obj_surface->fourcc == VA_FOURCC('N', 'V', '1', '2')) {
+        unsigned int tiling = 0, swizzle = 0;
+
+        dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
+
+        if (tiling == I915_TILING_Y) {
+            encoder_context->input_yuv_surface = encode_state->current_render_target;
+            return;
+        }
+    }
+
+    rect.x = 0;
+    rect.y = 0;
+    rect.width = obj_surface->orig_width;
+    rect.height = obj_surface->orig_height;
+    
+    src_surface.id = encode_state->current_render_target;
+    src_surface.type = I965_SURFACE_TYPE_SURFACE;
+    src_surface.flags = I965_SURFACE_FLAG_FRAME;
+    
+    status = i965_CreateSurfaces(ctx,
+                                 obj_surface->orig_width,
+                                 obj_surface->orig_height,
+                                 VA_RT_FORMAT_YUV420,
+                                 1,
+                                 &encoder_context->input_yuv_surface);
+    assert(status == VA_STATUS_SUCCESS);
+    obj_surface = SURFACE(encoder_context->input_yuv_surface);
+    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N', 'V', '1', '2'), SUBSAMPLE_YUV420);
+    
+    dst_surface.id = encoder_context->input_yuv_surface;
+    dst_surface.type = I965_SURFACE_TYPE_SURFACE;
+    dst_surface.flags = I965_SURFACE_FLAG_FRAME;
+
+    status = i965_image_processing(ctx,
+                                   &src_surface,
+                                   &rect,
+                                   &dst_surface,
+                                   &rect);
+    assert(status == VA_STATUS_SUCCESS);
+
+    encoder_context->is_tmp_id = 1;
+}
+
 static void 
 intel_encoder_end_picture(VADriverContextP ctx, 
                           VAProfile profile, 
@@ -52,6 +129,8 @@ intel_encoder_end_picture(VADriverContextP ctx,
     struct encode_state *encode_state = &codec_state->encode;
     VAStatus vaStatus;
 
+    intel_encoder_check_yuv_surface(ctx, profile, encode_state, encoder_context);
+
     vaStatus = encoder_context->vme_pipeline(ctx, profile, encode_state, encoder_context);
 
     if (vaStatus == VA_STATUS_SUCCESS)
@@ -101,6 +180,8 @@ gen7_enc_hw_context_init(VADriverContextP ctx, VAProfile profile)
     encoder_context->base.destroy = intel_encoder_context_destroy;
     encoder_context->base.run = intel_encoder_end_picture;
     encoder_context->base.batch = intel_batchbuffer_new(intel, I915_EXEC_RENDER);
+    encoder_context->input_yuv_surface = VA_INVALID_SURFACE;
+    encoder_context->is_tmp_id = 0;
 
     gen6_vme_context_init(ctx, encoder_context);
     assert(encoder_context->vme_context);
index b31af98..d4e6165 100644 (file)
@@ -39,6 +39,8 @@
 struct intel_encoder_context
 {
     struct hw_context base;
+    VASurfaceID input_yuv_surface;
+    int is_tmp_id;
     void *vme_context;
     void *mfc_context;
     void (*vme_context_destroy)(void *vme_context);