[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