[Libva] [PATCH 1/2] HEVC ENC: 10bit support

Zhao Yakui yakui.zhao at intel.com
Thu Sep 1 01:05:30 UTC 2016


On 08/31/2016 05:13 PM, Pengfei Qu wrote:
> this patch enable HEVC 10bit encoding on KBL+.
>
> v1:
> add internal NV12 format surface in vme context structure.
> add VADriverContextP member in vem context structure.
> P010->NV12 is done in YUV check before encoding.
>
> v2:
> add P010->NV12 for ref/reconstructed frame and enc frame.
>
> v3: call i965_SyncSurface to work around the GPU hang when 10bit->8bit(P010->NV12)

I have the following concerns.
    a. The 10bit encoding is mainly for gen9. But it seems that a lot of 
other files are also modified. Is it required?
    b. the implementation and the 10-bit Profile can be split into two 
patches.
    c. The workaround issue had better be split into one single patch.

    d. It is not a good idea to do the conversion of P010->NV12  in the 
common functions of intel_encoder_check_yuv_surface and 
intel_encoder_check_hevc_parameter.

> ---
>   src/gen6_mfc_common.c  |  20 ++++++++
>   src/gen6_vme.c         |  17 +++++++
>   src/gen6_vme.h         |   8 +++
>   src/gen7_vme.c         |   2 +
>   src/gen8_vme.c         |  12 ++++-
>   src/gen9_mfc_hevc.c    |  37 +++++++++-----
>   src/gen9_vme.c         |  26 ++++++++--
>   src/i965_device_info.c |   1 +
>   src/i965_drv_video.c   |  20 ++++++--
>   src/i965_drv_video.h   |   1 +
>   src/i965_encoder.c     | 130 +++++++++++++++++++++++++++++++++++++++++++++----
>   11 files changed, 245 insertions(+), 29 deletions(-)
>
> diff --git a/src/gen6_mfc_common.c b/src/gen6_mfc_common.c
> index 9f041d8..9bbc69b 100644
> --- a/src/gen6_mfc_common.c
> +++ b/src/gen6_mfc_common.c
> @@ -2089,12 +2089,19 @@ intel_hevc_vme_reference_state(VADriverContextP ctx,
>       struct object_surface *obj_surface = NULL;
>       struct i965_driver_data *i965 = i965_driver_data(ctx);
>       VASurfaceID ref_surface_id;
> +    VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
>       VAEncPictureParameterBufferHEVC *pic_param = (VAEncPictureParameterBufferHEVC *)encode_state->pic_param_ext->buffer;
>       VAEncSliceParameterBufferHEVC *slice_param = (VAEncSliceParameterBufferHEVC *)encode_state->slice_params_ext[0]->buffer;
>       int max_num_references;
>       VAPictureHEVC *curr_pic;
>       VAPictureHEVC *ref_list;
>       int ref_idx;
> +    int frame_index,i;
> +    unsigned int is_hevc10 = 0;
> +
> +    if((pSequenceParameter->seq_fields.bits.bit_depth_luma_minus8>  0)
> +        || (pSequenceParameter->seq_fields.bits.bit_depth_chroma_minus8>  0))
> +        is_hevc10 = 1;
>
>       if (list_index == 0) {
>           max_num_references = pic_param->num_ref_idx_l0_default_active_minus1 + 1;
> @@ -2141,6 +2148,19 @@ intel_hevc_vme_reference_state(VADriverContextP ctx,
>           obj_surface->bo) {
>           assert(ref_idx>= 0);
>           vme_context->used_reference_objects[list_index] = obj_surface;
> +
> +        if(is_hevc10){
> +
> +            frame_index = -1;
> +            for (i = 0; i<  16; i++) {
> +                if (obj_surface == encode_state->reference_objects[i]) {
> +                    frame_index = i;
> +                    break;
> +                }
> +            }
> +
> +            obj_surface = vme_context->reference_objects_internal[frame_index];
> +        }
>           vme_source_surface_state(ctx, surface_index, obj_surface, encoder_context);
>           vme_context->ref_index_in_mb[list_index] = (ref_idx<<  24 |
>                   ref_idx<<  16 |
> diff --git a/src/gen6_vme.c b/src/gen6_vme.c
> index 45cc30e..1f4f001 100644
> --- a/src/gen6_vme.c
> +++ b/src/gen6_vme.c
> @@ -611,6 +611,7 @@ static void
>   gen6_vme_context_destroy(void *context)
>   {
>       struct gen6_vme_context *vme_context = context;
> +    int i = 0;
>
>       i965_gpe_context_destroy(&vme_context->gpe_context);
>
> @@ -626,6 +627,20 @@ gen6_vme_context_destroy(void *context)
>       free(vme_context->qp_per_mb);
>       vme_context->qp_per_mb = NULL;
>
> +    if (vme_context->input_yuv_object_internal) {
> +        i965_DestroySurfaces(vme_context->driver_context,&vme_context->input_yuv_surface_internal, 1);
> +        vme_context->input_yuv_surface_internal = VA_INVALID_SURFACE;
> +        vme_context->input_yuv_object_internal = NULL;
> +    }
> +
> +    for(i = 0 ; i<  16 ; i++) {
> +        if (vme_context->reference_objects_internal[i]) {
> +            i965_DestroySurfaces(vme_context->driver_context,&vme_context->reference_surface_internal[i], 1);
> +            vme_context->reference_surface_internal[i] = VA_INVALID_SURFACE;
> +            vme_context->reference_objects_internal[i] = NULL;
> +        }
> +    }
> +
>       free(vme_context);
>   }
>
> @@ -672,5 +687,7 @@ Bool gen6_vme_context_init(VADriverContextP ctx, struct intel_encoder_context *e
>       encoder_context->vme_context = vme_context;
>       encoder_context->vme_context_destroy = gen6_vme_context_destroy;
>
> +    vme_context->driver_context = ctx;
> +
>       return True;
>   }
> diff --git a/src/gen6_vme.h b/src/gen6_vme.h
> index e8f4742..8aeced0 100644
> --- a/src/gen6_vme.h
> +++ b/src/gen6_vme.h
> @@ -107,6 +107,14 @@ struct gen6_vme_context
>       bool roi_enabled;
>       char *qp_per_mb;
>       int saved_width_mbs, saved_height_mbs;
> +
> +    //Encoding HEVC10:internal surface keep for P010->NV12 , this is only for hevc10 to save the P010->NV12
> +    struct object_surface *input_yuv_object_internal;
> +    struct object_surface *reference_objects_internal[16];
> +    VASurfaceID input_yuv_surface_internal;
> +    VASurfaceID reference_surface_internal[16];
> +    VADriverContextP driver_context;
> +
>   };
>
>   #define MPEG2_PIC_WIDTH_HEIGHT	30
> diff --git a/src/gen7_vme.c b/src/gen7_vme.c
> index 897d169..7f8dc5e 100644
> --- a/src/gen7_vme.c
> +++ b/src/gen7_vme.c
> @@ -1167,5 +1167,7 @@ Bool gen7_vme_context_init(VADriverContextP ctx, struct intel_encoder_context *e
>       encoder_context->vme_context_destroy = gen7_vme_context_destroy;
>       vme_context->vme_state_message = malloc(VME_MSG_LENGTH * sizeof(int));
>
> +    vme_context->driver_context = ctx;
> +
>       return True;
>   }
> diff --git a/src/gen8_vme.c b/src/gen8_vme.c
> index 2a93d1e..f6b3318 100644
> --- a/src/gen8_vme.c
> +++ b/src/gen8_vme.c
> @@ -1335,7 +1335,7 @@ Bool gen8_vme_context_init(VADriverContextP ctx, struct intel_encoder_context *e
>   {
>       struct gen6_vme_context *vme_context = NULL;
>       struct i965_kernel *vme_kernel_list = NULL;
> -    int i965_kernel_num;
> +    int i965_kernel_num,i;
>
>       switch (encoder_context->codec) {
>       case CODEC_H264:
> @@ -1404,6 +1404,16 @@ Bool gen8_vme_context_init(VADriverContextP ctx, struct intel_encoder_context *e
>           encoder_context->vme_context_destroy = gen8_vme_context_destroy;
>
>           vme_context->vme_state_message = malloc(VME_MSG_LENGTH * sizeof(int));
> +
> +        vme_context->driver_context = ctx;
> +
> +        // HEVC 10bit
> +        vme_context->input_yuv_surface_internal = VA_INVALID_SURFACE;
> +        vme_context->input_yuv_object_internal = NULL;
> +        for(i = 0 ; i<  16 ; i++) {
> +            vme_context->reference_surface_internal[i] = VA_INVALID_SURFACE;
> +            vme_context->reference_objects_internal[i] = NULL;
> +        }
>       }
>
>       return True;
> diff --git a/src/gen9_mfc_hevc.c b/src/gen9_mfc_hevc.c
> index b3ee327..6021a7e 100644
> --- a/src/gen9_mfc_hevc.c
> +++ b/src/gen9_mfc_hevc.c
> @@ -193,12 +193,21 @@ gen9_hcpe_surface_state(VADriverContextP ctx, struct encode_state *encode_state,
>       struct intel_batchbuffer *batch = encoder_context->base.batch;
>       struct object_surface *obj_surface = encode_state->reconstructed_object;
>       struct gen9_hcpe_context *mfc_context = encoder_context->mfc_context;
> +    VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
> +    unsigned int surface_format = SURFACE_FORMAT_PLANAR_420_8;
>
>       /* to do */
>       unsigned int y_cb_offset;
>
>       assert(obj_surface);
>
> +    if((pSequenceParameter->seq_fields.bits.bit_depth_luma_minus8>  0)
> +        || (pSequenceParameter->seq_fields.bits.bit_depth_chroma_minus8>  0))
> +    {
> +        assert(obj_surface->fourcc == VA_FOURCC_P010);
> +        surface_format = SURFACE_FORMAT_P010;
> +    }
> +
>       y_cb_offset = obj_surface->y_cb_offset;
>
>       BEGIN_BCS_BATCH(batch, 3);
> @@ -207,7 +216,7 @@ gen9_hcpe_surface_state(VADriverContextP ctx, struct encode_state *encode_state,
>                     (1<<  28) |                   /* surface id */
>                     (mfc_context->surface_state.w_pitch - 1));    /* pitch - 1 */
>       OUT_BCS_BATCH(batch,
> -                  (SURFACE_FORMAT_PLANAR_420_8<<  28) |
> +                  surface_format<<  28 |
>                     y_cb_offset);
>       ADVANCE_BCS_BATCH(batch);
>
> @@ -217,7 +226,7 @@ gen9_hcpe_surface_state(VADriverContextP ctx, struct encode_state *encode_state,
>                     (0<<  28) |                   /* surface id */
>                     (mfc_context->surface_state.w_pitch - 1));    /* pitch - 1 */
>       OUT_BCS_BATCH(batch,
> -                  (SURFACE_FORMAT_PLANAR_420_8<<  28) |
> +                  surface_format<<  28 |
>                     y_cb_offset);
>       ADVANCE_BCS_BATCH(batch);
>   }
> @@ -588,8 +597,8 @@ gen9_hcpe_hevc_pic_state(VADriverContextP ctx, struct encode_state *encode_state
>                     seq_param->seq_fields.bits.sample_adaptive_offset_enabled_flag<<  3 | /* 0 for encoder */
>                     0);
>       OUT_BCS_BATCH(batch,
> -                  0<<  27 |                 /* 8 bit only for encoder */
> -                  0<<  24 |                 /* 8 bit only for encoder */
> +                  seq_param->seq_fields.bits.bit_depth_luma_minus8<<  27 |                 /* 10 bit for KBL+*/
> +                  seq_param->seq_fields.bits.bit_depth_chroma_minus8<<  24 |                 /* 10 bit for KBL+ */
>                     pcm_sample_bit_depth_luma_minus1<<  20 |
>                     pcm_sample_bit_depth_chroma_minus1<<  16 |
>                     seq_param->max_transform_hierarchy_depth_inter<<  13 |    /*  for encoder */
> @@ -913,6 +922,11 @@ static void gen9_hcpe_init(VADriverContextP ctx,
>       int height_in_mb = ALIGN(pSequenceParameter->pic_height_in_luma_samples, 16) / 16;
>
>       int num_cu_record = 64;
> +    int size_shift = 3;
> +
> +    if((pSequenceParameter->seq_fields.bits.bit_depth_luma_minus8>  0)
> +        || (pSequenceParameter->seq_fields.bits.bit_depth_chroma_minus8>  0))
> +        size_shift = 2;
>
>       if (log2_ctb_size == 5) num_cu_record = 16;
>       else if (log2_ctb_size == 4) num_cu_record = 4;
> @@ -991,12 +1005,12 @@ static void gen9_hcpe_init(VADriverContextP ctx,
>
>       /* Current internal buffer for HCP */
>
> -    size = ALIGN(pSequenceParameter->pic_width_in_luma_samples, 32)>>  3;
> +    size = ALIGN(pSequenceParameter->pic_width_in_luma_samples, 32)>>  size_shift;
>       size<<= 6;
>       ALLOC_ENCODER_BUFFER((&mfc_context->deblocking_filter_line_buffer), "line buffer", size);
>       ALLOC_ENCODER_BUFFER((&mfc_context->deblocking_filter_tile_line_buffer), "tile line buffer", size);
>
> -    size = ALIGN(pSequenceParameter->pic_height_in_luma_samples + 6 * width_in_ctb, 32)>>  3;
> +    size = ALIGN(pSequenceParameter->pic_height_in_luma_samples + 6 * width_in_ctb, 32)>>  size_shift;
>       size<<= 6;
>       ALLOC_ENCODER_BUFFER((&mfc_context->deblocking_filter_tile_column_buffer), "tile column buffer", size);
>
> @@ -1026,15 +1040,15 @@ static void gen9_hcpe_init(VADriverContextP ctx,
>           ALLOC_ENCODER_BUFFER((&mfc_context->metadata_tile_column_buffer), "metadata tile column buffer", size);
>       }
>
> -    size = ALIGN(((pSequenceParameter->pic_width_in_luma_samples>>  1) + 3 * width_in_ctb), 16)>>  3;
> +    size = ALIGN(((pSequenceParameter->pic_width_in_luma_samples>>  1) + 3 * width_in_ctb), 16)>>  size_shift;
>       size<<= 6;
>       ALLOC_ENCODER_BUFFER((&mfc_context->sao_line_buffer), "sao line buffer", size);
>
> -    size = ALIGN(((pSequenceParameter->pic_width_in_luma_samples>>  1) + 6 * width_in_ctb), 16)>>  3;
> +    size = ALIGN(((pSequenceParameter->pic_width_in_luma_samples>>  1) + 6 * width_in_ctb), 16)>>  size_shift;
>       size<<= 6;
>       ALLOC_ENCODER_BUFFER((&mfc_context->sao_tile_line_buffer), "sao tile line buffer", size);
>
> -    size = ALIGN(((pSequenceParameter->pic_height_in_luma_samples>>  1) + 6 * height_in_ctb), 16)>>  3;
> +    size = ALIGN(((pSequenceParameter->pic_height_in_luma_samples>>  1) + 6 * height_in_ctb), 16)>>  size_shift;
>       size<<= 6;
>       ALLOC_ENCODER_BUFFER((&mfc_context->sao_tile_column_buffer), "sao tile column buffer", size);
>
> @@ -1707,8 +1721,8 @@ gen9_hcpe_hevc_pipeline_slice_programing(VADriverContextP ctx,
>       }
>
>       /* only support for 8-bit pixel bit-depth */
> -    assert(pSequenceParameter->seq_fields.bits.bit_depth_luma_minus8 == 0);
> -    assert(pSequenceParameter->seq_fields.bits.bit_depth_chroma_minus8 == 0);
> +    assert(pSequenceParameter->seq_fields.bits.bit_depth_luma_minus8>= 0&&  pSequenceParameter->seq_fields.bits.bit_depth_luma_minus8<= 2);
> +    assert(pSequenceParameter->seq_fields.bits.bit_depth_chroma_minus8>= 0&&  pSequenceParameter->seq_fields.bits.bit_depth_chroma_minus8<= 2);
>       assert(pPicParameter->pic_init_qp>= 0&&  pPicParameter->pic_init_qp<  52);
>       assert(qp>= 0&&  qp<  52);
>
> @@ -2733,6 +2747,7 @@ VAStatus gen9_hcpe_pipeline(VADriverContextP ctx,
>
>       switch (profile) {
>       case VAProfileHEVCMain:
> +    case VAProfileHEVCMain10:
>           vaStatus = gen9_hcpe_hevc_encode_picture(ctx, encode_state, encoder_context);
>           break;
>
> diff --git a/src/gen9_vme.c b/src/gen9_vme.c
> index 1625c2b..188292e 100644
> --- a/src/gen9_vme.c
> +++ b/src/gen9_vme.c
> @@ -329,11 +329,13 @@ gen9_vme_surface_setup(VADriverContextP ctx,
>                          int is_intra,
>                          struct intel_encoder_context *encoder_context)
>   {
> +    struct gen6_vme_context *vme_context = encoder_context->vme_context;
>       struct object_surface *obj_surface;
>
>       /*Setup surfaces state*/
>       /* current picture for encoding */
> -    obj_surface = encode_state->input_yuv_object;
> +    obj_surface = vme_context->input_yuv_object_internal;
> +    assert(obj_surface);
>       gen9_vme_source_surface_state(ctx, 0, obj_surface, encoder_context);
>       gen9_vme_media_source_surface_state(ctx, 4, obj_surface, encoder_context);
>       gen9_vme_media_chroma_source_surface_state(ctx, 6, obj_surface, encoder_context);
> @@ -1417,11 +1419,17 @@ gen9_vme_hevc_surface_setup(VADriverContextP ctx,
>                          int is_intra,
>                          struct intel_encoder_context *encoder_context)
>   {
> +    struct gen6_vme_context *vme_context = encoder_context->vme_context;
>       struct object_surface *obj_surface;
> +    VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
>
>       /*Setup surfaces state*/
>       /* current picture for encoding */
> -    obj_surface = encode_state->input_yuv_object;
> +    if((pSequenceParameter->seq_fields.bits.bit_depth_luma_minus8>  0)
> +        || (pSequenceParameter->seq_fields.bits.bit_depth_chroma_minus8>  0))
> +        obj_surface = vme_context->input_yuv_object_internal;
> +    else
> +        obj_surface = encode_state->input_yuv_object;
>       gen9_vme_source_surface_state(ctx, 0, obj_surface, encoder_context);
>       gen9_vme_media_source_surface_state(ctx, 4, obj_surface, encoder_context);
>       gen9_vme_media_chroma_source_surface_state(ctx, 6, obj_surface, encoder_context);
> @@ -1785,6 +1793,7 @@ static void
>   gen9_vme_context_destroy(void *context)
>   {
>       struct gen6_vme_context *vme_context = context;
> +    int i = 0;
>
>       gen8_gpe_context_destroy(&vme_context->gpe_context);
>
> @@ -1819,7 +1828,7 @@ Bool gen9_vme_context_init(VADriverContextP ctx, struct intel_encoder_context *e
>   {
>       struct gen6_vme_context *vme_context = calloc(1, sizeof(struct gen6_vme_context));
>       struct i965_kernel *vme_kernel_list = NULL;
> -    int i965_kernel_num;
> +    int i965_kernel_num, i;
>
>       switch (encoder_context->codec) {
>       case CODEC_H264:
> @@ -1885,5 +1894,16 @@ Bool gen9_vme_context_init(VADriverContextP ctx, struct intel_encoder_context *e
>
>       vme_context->vme_state_message = malloc(VME_MSG_LENGTH * sizeof(int));
>
> +    vme_context->driver_context = ctx;
> +
> +    // HEVC 10bit
> +    vme_context->input_yuv_surface_internal = VA_INVALID_SURFACE;
> +    vme_context->input_yuv_object_internal = NULL;
> +    for(i = 0 ; i<  16 ; i++) {
> +        vme_context->reference_surface_internal[i] = VA_INVALID_SURFACE;
> +        vme_context->reference_objects_internal[i] = NULL;
> +    }
> +
> +
>       return True;
>   }
> diff --git a/src/i965_device_info.c b/src/i965_device_info.c
> index 47fd50a..1633924 100644
> --- a/src/i965_device_info.c
> +++ b/src/i965_device_info.c
> @@ -469,6 +469,7 @@ static struct hw_codec_info kbl_hw_codec_info = {
>       .has_h264_mvc_encoding = 1,
>       .has_hevc_decoding = 1,
>       .has_hevc_encoding = 1,
> +    .has_hevc10_encoding = 1,
>       .has_hevc10_decoding = 1,
>       .has_vp9_decoding = 1,
>       .has_vpp_p010 = 1,
> diff --git a/src/i965_drv_video.c b/src/i965_drv_video.c
> index 77b9f37..9e9393e 100644
> --- a/src/i965_drv_video.c
> +++ b/src/i965_drv_video.c
> @@ -120,6 +120,8 @@
>
>   #define HAS_HEVC10_DECODING(ctx)        ((ctx)->codec_info->has_hevc10_decoding&&  \
>                                            (ctx)->intel.has_bsd)
> +#define HAS_HEVC10_ENCODING(ctx)        ((ctx)->codec_info->has_hevc10_encoding&&  \
> +                                         (ctx)->intel.has_bsd)
>
>   #define HAS_VPP_P010(ctx)        ((ctx)->codec_info->has_vpp_p010&&  \
>                                            (ctx)->intel.has_bsd)
> @@ -605,7 +607,8 @@ i965_QueryConfigProfiles(VADriverContextP ctx,
>           profile_list[i++] = VAProfileHEVCMain;
>       }
>
> -    if (HAS_HEVC10_DECODING(i965)) {
> +    if (HAS_HEVC10_DECODING(i965)||
> +        HAS_HEVC10_ENCODING(i965)) {
>           profile_list[i++] = VAProfileHEVCMain10;
>       }
>
> @@ -728,6 +731,9 @@ i965_QueryConfigEntrypoints(VADriverContextP ctx,
>           if (HAS_HEVC10_DECODING(i965))
>               entrypoint_list[n++] = VAEntrypointVLD;
>
> +        if (HAS_HEVC10_ENCODING(i965))
> +            entrypoint_list[n++] = VAEntrypointEncSlice;
> +
>           break;
>
>       case VAProfileVP9Profile0:
> @@ -852,7 +858,8 @@ i965_validate_config(VADriverContextP ctx, VAProfile profile,
>           break;
>
>       case VAProfileHEVCMain10:
> -        if (HAS_HEVC10_DECODING(i965)&&  (entrypoint == VAEntrypointVLD))
> +        if ((HAS_HEVC10_DECODING(i965)&&  (entrypoint == VAEntrypointVLD))||
> +            (HAS_HEVC10_ENCODING(i965)&&  (entrypoint == VAEntrypointEncSlice)))
>               va_status = VA_STATUS_SUCCESS;
>           else
>               va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
> @@ -988,7 +995,8 @@ i965_GetConfigAttributes(VADriverContextP ctx,
>                       profile == VAProfileH264High ||
>                       profile == VAProfileH264StereoHigh ||
>                       profile == VAProfileH264MultiviewHigh ||
> -                    profile == VAProfileHEVCMain) {
> +                    profile == VAProfileHEVCMain ||
> +                    profile == VAProfileHEVCMain10) {
>                       attrib_list[i].value |= (VA_ENC_PACKED_HEADER_RAW_DATA |
>                                                VA_ENC_PACKED_HEADER_SLICE);
>                   }
> @@ -3270,7 +3278,8 @@ i965_encoder_render_picture(VADriverContextP ctx,
>               if ((param->type == VAEncPackedHeaderRawData) ||
>                   (param->type == VAEncPackedHeaderSlice)) {
>                   vaStatus = I965_RENDER_ENCODE_BUFFER(packed_header_params_ext);
> -            } else if((obj_config->profile == VAProfileHEVCMain)&&
> +            } else if((obj_config->profile == VAProfileHEVCMain ||
> +                obj_config->profile == VAProfileHEVCMain10)&&
>                   (encode->last_packed_header_type == VAEncPackedHeaderSequence)) {
>                   vaStatus = i965_encoder_render_packed_header_parameter_buffer(ctx,
>                                                                             obj_context,
> @@ -3368,7 +3377,8 @@ i965_encoder_render_picture(VADriverContextP ctx,
>                       ((encode->last_packed_header_type&  (~VAEncPackedHeaderMiscMask)) != 0)),
>                       VA_STATUS_ERROR_ENCODING_ERROR);
>
> -                if((obj_config->profile == VAProfileHEVCMain)&&
> +                if((obj_config->profile == VAProfileHEVCMain ||
> +                    obj_config->profile == VAProfileHEVCMain10)&&
>                       (encode->last_packed_header_type == VAEncPackedHeaderSequence)) {
>
>                           vaStatus = i965_encoder_render_packed_header_data_buffer(ctx,
> diff --git a/src/i965_drv_video.h b/src/i965_drv_video.h
> index 9fe042f..d9644a7 100644
> --- a/src/i965_drv_video.h
> +++ b/src/i965_drv_video.h
> @@ -404,6 +404,7 @@ struct hw_codec_info
>       unsigned int has_h264_mvc_encoding:1;
>       unsigned int has_hevc_decoding:1;
>       unsigned int has_hevc_encoding:1;
> +    unsigned int has_hevc10_encoding:1;
>       unsigned int has_hevc10_decoding:1;
>       unsigned int has_vp9_decoding:1;
>       unsigned int has_vpp_p010:1;
> diff --git a/src/i965_encoder.c b/src/i965_encoder.c
> index 47368fb..a2c214b 100644
> --- a/src/i965_encoder.c
> +++ b/src/i965_encoder.c
> @@ -126,15 +126,21 @@ intel_encoder_check_yuv_surface(VADriverContextP ctx,
>       if (!obj_surface || !obj_surface->bo)
>           return VA_STATUS_ERROR_INVALID_PARAMETER;
>
> -    if (obj_surface->fourcc == VA_FOURCC_NV12) {
> -        unsigned int tiling = 0, swizzle = 0;
> +    if (VAProfileHEVCMain10 == profile&&
> +        obj_surface->fourcc == VA_FOURCC_NV12)
> +        return VA_STATUS_ERROR_INVALID_PARAMETER;
>
> +    if (obj_surface->fourcc == VA_FOURCC_NV12 ||
> +        (VAProfileHEVCMain10 == profile&&
> +        obj_surface->fourcc == VA_FOURCC_P010)) {
> +
> +        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;
>               encode_state->input_yuv_object = obj_surface;
> -            return clear_border(obj_surface);
> +            goto HEVC10_EXIT;
>           }
>       }
>
> @@ -150,7 +156,7 @@ intel_encoder_check_yuv_surface(VADriverContextP ctx,
>       status = i965_CreateSurfaces(ctx,
>                                    obj_surface->orig_width,
>                                    obj_surface->orig_height,
> -                                 VA_RT_FORMAT_YUV420,
> +                                 (VAProfileHEVCMain10 != profile ? VA_RT_FORMAT_YUV420:VA_RT_FORMAT_YUV420_10BPP),
>                                    1,
>                                    &encoder_context->input_yuv_surface);

The surface allocation should be based on Bit_depth requirement instead 
of profile.
Based on HEVC spec, the Main10 profile can support the 8/10 bit-depth. 
In such case if the 8-bit depth is used, the NV12 surface is enough.

>       ASSERT_RET(status == VA_STATUS_SUCCESS, status);
> @@ -158,7 +164,7 @@ intel_encoder_check_yuv_surface(VADriverContextP ctx,
>       obj_surface = SURFACE(encoder_context->input_yuv_surface);
>       encode_state->input_yuv_object = obj_surface;
>       assert(obj_surface);
> -    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
> +    i965_check_alloc_surface_bo(ctx, obj_surface, 1, (VAProfileHEVCMain10 != profile ?VA_FOURCC_NV12:VA_FOURCC_P010), SUBSAMPLE_YUV420);
>
>       dst_surface.base = (struct object_base *)obj_surface;
>       dst_surface.type = I965_SURFACE_TYPE_SURFACE;
> @@ -173,6 +179,50 @@ intel_encoder_check_yuv_surface(VADriverContextP ctx,
>
>       encoder_context->is_tmp_id = 1;
>
> +HEVC10_EXIT:
> +    if(VAProfileHEVCMain10 == profile)
> +    {
> +        struct gen6_vme_context *vme_context = encoder_context->vme_context;
> +        rect.x = 0;
> +        rect.y = 0;
> +        rect.width = obj_surface->orig_width;
> +        rect.height = obj_surface->orig_height;
> +
> +        src_surface.base = (struct object_base *)obj_surface;
> +        src_surface.type = I965_SURFACE_TYPE_SURFACE;
> +        src_surface.flags = I965_SURFACE_FLAG_FRAME;
> +
> +        if(SURFACE(vme_context->input_yuv_surface_internal) == NULL)
> +        {
> +            status = i965_CreateSurfaces(ctx,
> +                obj_surface->orig_width,
> +                obj_surface->orig_height,
> +                VA_RT_FORMAT_YUV420,
> +                1,
> +&vme_context->input_yuv_surface_internal);
> +            assert(status == VA_STATUS_SUCCESS);
> +
> +            if (status != VA_STATUS_SUCCESS)
> +                return status;
> +        }
> +
> +        obj_surface = SURFACE(vme_context->input_yuv_surface_internal);
> +        vme_context->input_yuv_object_internal = obj_surface;
> +        assert(obj_surface);
> +        i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
> +
> +        dst_surface.base = (struct object_base *)obj_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);
> +        i965_SyncSurface(ctx,vme_context->input_yuv_surface_internal);
> +    }
>       return clear_border(obj_surface);
>   }
>
> @@ -493,7 +543,7 @@ intel_encoder_check_vp8_parameter(VADriverContextP ctx,
>       if (!obj_surface)
>           goto error;
>
> -    encode_state->reconstructed_object = obj_surface;
> +    encode_state->reconstructed_object = obj_surface;
>       obj_buffer = BUFFER(pic_param->coded_buf);
>       assert(obj_buffer&&  obj_buffer->buffer_store&&  obj_buffer->buffer_store->bo);
>
> @@ -546,12 +596,24 @@ intel_encoder_check_hevc_parameter(VADriverContextP ctx,
>                                     struct intel_encoder_context *encoder_context)
>   {
>       struct i965_driver_data *i965 = i965_driver_data(ctx);
> +    struct gen6_vme_context *vme_context = encoder_context->vme_context;
>       struct object_surface *obj_surface;	
>       struct object_buffer *obj_buffer;
> +    VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
>       VAEncPictureParameterBufferHEVC *pic_param = (VAEncPictureParameterBufferHEVC *)encode_state->pic_param_ext->buffer;
>       VAEncSliceParameterBufferHEVC *slice_param;
> +    unsigned int is_hevc10 = 0;
> +    struct i965_surface src_surface, dst_surface;
> +    VAStatus status;
> +    VARectangle rect;
>       int i;
>
> +    assert(vme_context);
> +
> +    if((pSequenceParameter->seq_fields.bits.bit_depth_luma_minus8>  0)
> +        || (pSequenceParameter->seq_fields.bits.bit_depth_chroma_minus8>  0))
> +        is_hevc10 = 1;
> +
>       assert(!(pic_param->decoded_curr_pic.flags&  VA_PICTURE_HEVC_INVALID));
>
>       if (pic_param->decoded_curr_pic.flags&  VA_PICTURE_HEVC_INVALID)
> @@ -583,15 +645,63 @@ intel_encoder_check_hevc_parameter(VADriverContextP ctx,
>               if (!obj_surface)
>                   goto error;
>
> -            if (obj_surface->bo)
> +            if (obj_surface->bo) {
>                   encode_state->reference_objects[i] = obj_surface;
> +                if(is_hevc10) {
> +                    //conver P010->NV12
> +                    assert(obj_surface->fourcc == VA_FOURCC_P010);
> +                    rect.x = 0;
> +                    rect.y = 0;
> +                    rect.width = obj_surface->orig_width;
> +                    rect.height = obj_surface->orig_height;
> +
> +                    src_surface.base = (struct object_base *)obj_surface;
> +                    src_surface.type = I965_SURFACE_TYPE_SURFACE;
> +                    src_surface.flags = I965_SURFACE_FLAG_FRAME;
> +
> +                    if(SURFACE(vme_context->reference_surface_internal[i]) == NULL)
> +                    {
> +                        status = i965_CreateSurfaces(ctx,
> +                            obj_surface->orig_width,
> +                            obj_surface->orig_height,
> +                            VA_RT_FORMAT_YUV420,
> +                            1,
> +&vme_context->reference_surface_internal[i]);
> +                        assert(status == VA_STATUS_SUCCESS);
> +
> +                        if (status != VA_STATUS_SUCCESS)
> +                            return status;
> +                    }
> +
> +                    obj_surface = SURFACE(vme_context->reference_surface_internal[i]);
> +                    vme_context->reference_objects_internal[i] = obj_surface;
> +                    assert(obj_surface);
> +                    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
> +
> +                    dst_surface.base = (struct object_base *)obj_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);
> +                    i965_SyncSurface(ctx,vme_context->reference_surface_internal[i]);
> +                }
> +            }
>               else
> +            {
>                   encode_state->reference_objects[i] = NULL; /* FIXME: Warning or Error ??? */
> +            }
>           }
>       }
>
>       for ( ; i<  15; i++)
> +    {
>           encode_state->reference_objects[i] = NULL;
> +    }
>
>       for (i = 0; i<  encode_state->num_slice_params_ext; i++) {
>           slice_param = (VAEncSliceParameterBufferHEVC *)encode_state->slice_params_ext[i]->buffer;
> @@ -725,7 +835,8 @@ intel_encoder_sanity_check_input(VADriverContextP ctx,
>           break;
>       }
>
> -    case VAProfileHEVCMain:  {
> +    case VAProfileHEVCMain:
> +    case VAProfileHEVCMain10:  {
>           vaStatus = intel_encoder_check_hevc_parameter(ctx, encode_state, encoder_context);
>           if (vaStatus != VA_STATUS_SUCCESS)
>               goto out;
> @@ -867,6 +978,7 @@ intel_enc_hw_context_init(VADriverContextP ctx,
>           break;
>
>       case VAProfileHEVCMain:
> +    case VAProfileHEVCMain10:
>           encoder_context->codec = CODEC_HEVC;
>           break;
>
> @@ -947,7 +1059,7 @@ gen9_enc_hw_context_init(VADriverContextP ctx, struct object_config *obj_config)
>       if (obj_config->entrypoint == VAEntrypointEncSliceLP) {
>           return intel_enc_hw_context_init(ctx, obj_config, NULL, gen9_vdenc_context_init);
>       } else {
> -        if (obj_config->profile == VAProfileHEVCMain) {
> +        if ((obj_config->profile == VAProfileHEVCMain) || (obj_config->profile == VAProfileHEVCMain10)) {
>               return intel_enc_hw_context_init(ctx, obj_config, gen9_vme_context_init, gen9_hcpe_context_init);
>           } else if (obj_config->profile == VAProfileJPEGBaseline)
>               return intel_enc_hw_context_init(ctx, obj_config, gen8_vme_context_init, gen8_mfc_context_init);



More information about the Libva mailing list