From 13eaae060e98cc3f51dc9d027309e9b80acabc7a Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 31 Aug 2018 10:13:52 +0200 Subject: [PATCH] Add support for H265 decoding, including predictive frames Some features are missing, such as scaling lists (quantization) and 10-bit output. Signed-off-by: Paul Kocialkowski --- src/Makefile.am | 4 +- src/config.c | 8 + src/context.c | 4 + src/h265.c | 403 ++++++++++++++++++++++++++++++++++++++++++++++++ src/h265.h | 37 +++++ src/picture.c | 28 ++++ src/surface.h | 6 + 7 files changed, 488 insertions(+), 2 deletions(-) create mode 100644 src/h265.c create mode 100644 src/h265.h diff --git a/src/Makefile.am b/src/Makefile.am index 0d3c33f..19cafbb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,13 +6,13 @@ backend_libs = -lpthread -ldl $(DRM_LIBS) $(LIBVA_DEPS_LIBS) backend_c = request.c object_heap.c config.c surface.c context.c buffer.c \ mpeg2.c picture.c subpicture.c image.c v4l2.c video.c media.c utils.c \ - h264.c + h264.c h265.c backend_s = tiled_yuv.S backend_h = request.h object_heap.h config.h surface.h context.h buffer.h \ mpeg2.h picture.h subpicture.h image.h v4l2.h video.h media.h utils.h \ - tiled_yuv.h h264.h + tiled_yuv.h h264.h h265.h v4l2_request_drv_video_la_LTLIBRARIES = v4l2_request_drv_video.la v4l2_request_drv_video_ladir = $(LIBVA_DRIVERS_PATH) diff --git a/src/config.c b/src/config.c index a2de9dc..fcbfe6b 100644 --- a/src/config.c +++ b/src/config.c @@ -54,6 +54,7 @@ VAStatus RequestCreateConfig(VADriverContextP context, VAProfile profile, case VAProfileH264ConstrainedBaseline: case VAProfileH264MultiviewHigh: case VAProfileH264StereoHigh: + case VAProfileHEVCMain: if (entrypoint != VAEntrypointVLD) return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT; break; @@ -129,6 +130,12 @@ VAStatus RequestQueryConfigProfiles(VADriverContextP context, profiles[index++] = VAProfileH264StereoHigh; } + found = v4l2_find_format(driver_data->video_fd, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + V4L2_PIX_FMT_HEVC_SLICE); + if (found && index < (V4L2_REQUEST_MAX_CONFIG_ATTRIBUTES - 1)) + profiles[index++] = VAProfileHEVCMain; + *profiles_count = index; return VA_STATUS_SUCCESS; @@ -147,6 +154,7 @@ VAStatus RequestQueryConfigEntrypoints(VADriverContextP context, case VAProfileH264ConstrainedBaseline: case VAProfileH264MultiviewHigh: case VAProfileH264StereoHigh: + case VAProfileHEVCMain: entrypoints[0] = VAEntrypointVLD; *entrypoints_count = 1; break; diff --git a/src/context.c b/src/context.c index 2ed199f..c6ebf0c 100644 --- a/src/context.c +++ b/src/context.c @@ -90,6 +90,10 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id, pixelformat = V4L2_PIX_FMT_H264_SLICE; break; + case VAProfileHEVCMain: + pixelformat = V4L2_PIX_FMT_HEVC_SLICE; + break; + default: status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE; goto error; diff --git a/src/h265.c b/src/h265.c new file mode 100644 index 0000000..40c24a6 --- /dev/null +++ b/src/h265.c @@ -0,0 +1,403 @@ +/* + * Copyright (c) 2016 Florent Revest, + * 2007 Intel Corporation. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "mpeg2.h" +#include "context.h" +#include "request.h" +#include "surface.h" + +#include +#include + +#include +#include + +#include + +#include "v4l2.h" + +#define H265_NAL_UNIT_TYPE_SHIFT 1 +#define H265_NAL_UNIT_TYPE_MASK ((1 << 6) - 1) +#define H265_NUH_TEMPORAL_ID_PLUS1_SHIFT 0 +#define H265_NUH_TEMPORAL_ID_PLUS1_MASK ((1 << 3) - 1) + +static void h265_fill_pps(VAPictureParameterBufferHEVC *picture, + VASliceParameterBufferHEVC *slice, + struct v4l2_ctrl_hevc_pps *pps) +{ + memset(pps, 0, sizeof(*pps)); + + pps->dependent_slice_segment_flag = + slice->LongSliceFlags.fields.dependent_slice_segment_flag; + pps->output_flag_present_flag = + picture->slice_parsing_fields.bits.output_flag_present_flag; + pps->num_extra_slice_header_bits = + picture->num_extra_slice_header_bits; + pps->sign_data_hiding_enabled_flag = + picture->pic_fields.bits.sign_data_hiding_enabled_flag; + pps->cabac_init_present_flag = + picture->slice_parsing_fields.bits.cabac_init_present_flag; + pps->init_qp_minus26 = picture->init_qp_minus26; + pps->constrained_intra_pred_flag = + picture->pic_fields.bits.constrained_intra_pred_flag; + pps->transform_skip_enabled_flag = + picture->pic_fields.bits.transform_skip_enabled_flag; + pps->cu_qp_delta_enabled_flag = + picture->pic_fields.bits.cu_qp_delta_enabled_flag; + pps->diff_cu_qp_delta_depth = picture->diff_cu_qp_delta_depth; + pps->pps_cb_qp_offset = picture->pps_cb_qp_offset; + pps->pps_cr_qp_offset = picture->pps_cr_qp_offset; + pps->pps_slice_chroma_qp_offsets_present_flag = + picture->slice_parsing_fields.bits.pps_slice_chroma_qp_offsets_present_flag; + pps->weighted_pred_flag = + picture->pic_fields.bits.weighted_pred_flag; + pps->weighted_bipred_flag = + picture->pic_fields.bits.weighted_bipred_flag; + pps->transquant_bypass_enabled_flag = + picture->pic_fields.bits.transquant_bypass_enabled_flag; + pps->tiles_enabled_flag = + picture->pic_fields.bits.tiles_enabled_flag; + pps->entropy_coding_sync_enabled_flag = + picture->pic_fields.bits.entropy_coding_sync_enabled_flag; + pps->num_tile_columns_minus1 = picture->num_tile_columns_minus1; + pps->num_tile_rows_minus1 = picture->num_tile_rows_minus1; + pps->loop_filter_across_tiles_enabled_flag = + picture->pic_fields.bits.loop_filter_across_tiles_enabled_flag; + pps->pps_loop_filter_across_slices_enabled_flag = + picture->pic_fields.bits.pps_loop_filter_across_slices_enabled_flag; + pps->deblocking_filter_override_enabled_flag = + picture->slice_parsing_fields.bits.deblocking_filter_override_enabled_flag; + pps->pps_disable_deblocking_filter_flag = + picture->slice_parsing_fields.bits.pps_disable_deblocking_filter_flag; + pps->pps_beta_offset_div2 = picture->pps_beta_offset_div2; + pps->pps_tc_offset_div2 = picture->pps_tc_offset_div2; + pps->lists_modification_present_flag = + picture->slice_parsing_fields.bits.lists_modification_present_flag; + pps->log2_parallel_merge_level_minus2 = + picture->log2_parallel_merge_level_minus2; +} + +static void h265_fill_sps(VAPictureParameterBufferHEVC *picture, + struct v4l2_ctrl_hevc_sps *sps) +{ + memset(sps, 0, sizeof(*sps)); + + sps->chroma_format_idc = picture->pic_fields.bits.chroma_format_idc; + sps->separate_colour_plane_flag = + picture->pic_fields.bits.separate_colour_plane_flag; + sps->pic_width_in_luma_samples = picture->pic_width_in_luma_samples; + sps->pic_height_in_luma_samples = picture->pic_height_in_luma_samples; + sps->bit_depth_luma_minus8 = picture->bit_depth_luma_minus8; + sps->bit_depth_chroma_minus8 = picture->bit_depth_chroma_minus8; + sps->log2_max_pic_order_cnt_lsb_minus4 = + picture->log2_max_pic_order_cnt_lsb_minus4; + sps->sps_max_dec_pic_buffering_minus1 = + picture->sps_max_dec_pic_buffering_minus1; + sps->sps_max_num_reorder_pics = 0; + sps->sps_max_latency_increase_plus1 = 0; + sps->log2_min_luma_coding_block_size_minus3 = + picture->log2_min_luma_coding_block_size_minus3; + sps->log2_diff_max_min_luma_coding_block_size = + picture->log2_diff_max_min_luma_coding_block_size; + sps->log2_min_luma_transform_block_size_minus2 = + picture->log2_min_transform_block_size_minus2; + sps->log2_diff_max_min_luma_transform_block_size = + picture->log2_diff_max_min_transform_block_size; + sps->max_transform_hierarchy_depth_inter = + picture->max_transform_hierarchy_depth_inter; + sps->max_transform_hierarchy_depth_intra = + picture->max_transform_hierarchy_depth_intra; + sps->scaling_list_enabled_flag = + picture->pic_fields.bits.scaling_list_enabled_flag; + sps->amp_enabled_flag = picture->pic_fields.bits.amp_enabled_flag; + sps->sample_adaptive_offset_enabled_flag = + picture->slice_parsing_fields.bits.sample_adaptive_offset_enabled_flag; + sps->pcm_enabled_flag = picture->pic_fields.bits.pcm_enabled_flag; + sps->pcm_sample_bit_depth_luma_minus1 = + picture->pcm_sample_bit_depth_luma_minus1; + sps->pcm_sample_bit_depth_chroma_minus1 = + picture->pcm_sample_bit_depth_chroma_minus1; + sps->log2_min_pcm_luma_coding_block_size_minus3 = + picture->log2_min_pcm_luma_coding_block_size_minus3; + sps->log2_diff_max_min_pcm_luma_coding_block_size = + picture->log2_diff_max_min_pcm_luma_coding_block_size; + sps->pcm_loop_filter_disabled_flag = + picture->pic_fields.bits.pcm_loop_filter_disabled_flag; + sps->num_short_term_ref_pic_sets = picture->num_short_term_ref_pic_sets; + sps->long_term_ref_pics_present_flag = + picture->slice_parsing_fields.bits.long_term_ref_pics_present_flag; + sps->num_long_term_ref_pics_sps = picture->num_long_term_ref_pic_sps; + sps->sps_temporal_mvp_enabled_flag = + picture->slice_parsing_fields.bits.sps_temporal_mvp_enabled_flag; + sps->strong_intra_smoothing_enabled_flag = + picture->pic_fields.bits.strong_intra_smoothing_enabled_flag; +} + +static void h265_fill_slice_params(VAPictureParameterBufferHEVC *picture, + VASliceParameterBufferHEVC *slice, + struct object_heap *surface_heap, + void *source_data, + struct v4l2_ctrl_hevc_slice_params *slice_params) +{ + struct object_surface *surface_object; + VAPictureHEVC *hevc_picture; + uint8_t nal_unit_type; + uint8_t nuh_temporal_id_plus1; + uint32_t data_bit_offset; + uint8_t pic_struct; + uint8_t field_pic; + uint8_t slice_type; + unsigned int num_active_dpb_entries; + unsigned int num_rps_poc_st_curr_before; + unsigned int num_rps_poc_st_curr_after; + unsigned int num_rps_poc_lt_curr; + uint8_t *b; + unsigned int count; + unsigned int o, i, j; + + /* Extract the missing NAL header information. */ + + b = source_data + slice->slice_data_offset; + + nal_unit_type = (b[0] >> H265_NAL_UNIT_TYPE_SHIFT) & + H265_NAL_UNIT_TYPE_MASK; + nuh_temporal_id_plus1 = (b[1] >> H265_NUH_TEMPORAL_ID_PLUS1_SHIFT) & + H265_NUH_TEMPORAL_ID_PLUS1_MASK; + + /* + * VAAPI only provides a byte-aligned value for the slice segment data + * offset, although it appears that the offset is not always aligned. + * Search for the first one bit in the previous byte, that marks the + * start of the slice segment to correct the value. + */ + + b = source_data + (slice->slice_data_offset + + slice->slice_data_byte_offset) - 1; + + for (o = 0; o < 8; o++) + if (*b & (1 << o)) + break; + + /* Include the one bit. */ + o++; + + data_bit_offset = (slice->slice_data_offset + + slice->slice_data_byte_offset) * 8 - o; + + memset(slice_params, 0, sizeof(*slice_params)); + + slice_params->bit_size = slice->slice_data_size * 8; + slice_params->data_bit_offset = data_bit_offset; + slice_params->nal_unit_type = nal_unit_type; + slice_params->nuh_temporal_id_plus1 = nuh_temporal_id_plus1; + + slice_type = slice->LongSliceFlags.fields.slice_type; + + slice_params->slice_type = slice_type, + slice_params->colour_plane_id = + slice->LongSliceFlags.fields.color_plane_id; + slice_params->slice_pic_order_cnt = + picture->CurrPic.pic_order_cnt; + slice_params->slice_sao_luma_flag = + slice->LongSliceFlags.fields.slice_sao_luma_flag; + slice_params->slice_sao_chroma_flag = + slice->LongSliceFlags.fields.slice_sao_chroma_flag; + slice_params->slice_temporal_mvp_enabled_flag = + slice->LongSliceFlags.fields.slice_temporal_mvp_enabled_flag; + slice_params->num_ref_idx_l0_active_minus1 = + slice->num_ref_idx_l0_active_minus1; + slice_params->num_ref_idx_l1_active_minus1 = + slice->num_ref_idx_l1_active_minus1; + slice_params->mvd_l1_zero_flag = + slice->LongSliceFlags.fields.mvd_l1_zero_flag; + slice_params->cabac_init_flag = + slice->LongSliceFlags.fields.cabac_init_flag; + slice_params->collocated_from_l0_flag = + slice->LongSliceFlags.fields.collocated_from_l0_flag; + slice_params->collocated_ref_idx = slice->collocated_ref_idx; + slice_params->five_minus_max_num_merge_cand = + slice->five_minus_max_num_merge_cand; + slice_params->use_integer_mv_flag = 0; + slice_params->slice_qp_delta = slice->slice_qp_delta; + slice_params->slice_cb_qp_offset = slice->slice_cb_qp_offset; + slice_params->slice_cr_qp_offset = slice->slice_cr_qp_offset; + slice_params->slice_act_y_qp_offset = 0; + slice_params->slice_act_cb_qp_offset = 0; + slice_params->slice_act_cr_qp_offset = 0; + slice_params->slice_deblocking_filter_disabled_flag = + slice->LongSliceFlags.fields.slice_deblocking_filter_disabled_flag; + slice_params->slice_beta_offset_div2 = slice->slice_beta_offset_div2; + slice_params->slice_tc_offset_div2 = slice->slice_tc_offset_div2; + slice_params->slice_loop_filter_across_slices_enabled_flag = + slice->LongSliceFlags.fields.slice_loop_filter_across_slices_enabled_flag; + + if (picture->CurrPic.flags & VA_PICTURE_HEVC_FIELD_PIC) { + if (picture->CurrPic.flags & VA_PICTURE_HEVC_BOTTOM_FIELD) + pic_struct = 2; + else + pic_struct = 1; + } else { + pic_struct = 0; + } + + slice_params->pic_struct = pic_struct; + + num_active_dpb_entries = 0; + num_rps_poc_st_curr_before = 0; + num_rps_poc_st_curr_after = 0; + num_rps_poc_lt_curr = 0; + + for (i = 0; i < 15 && slice_type != V4L2_HEVC_SLICE_TYPE_I ; i++) { + hevc_picture = &picture->ReferenceFrames[i]; + + if (hevc_picture->picture_id == VA_INVALID_SURFACE || + (hevc_picture->flags & VA_PICTURE_HEVC_INVALID) != 0) + break; + + surface_object = (struct object_surface *) + object_heap_lookup(surface_heap, + hevc_picture->picture_id); + if (surface_object == NULL) + break; + + slice_params->dpb[i].buffer_index = + surface_object->destination_index; + + if ((hevc_picture->flags & VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE) != 0) { + slice_params->dpb[i].rps = + V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE; + num_rps_poc_st_curr_before++; + } else if ((hevc_picture->flags & VA_PICTURE_HEVC_RPS_ST_CURR_AFTER) != 0) { + slice_params->dpb[i].rps = + V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_AFTER; + num_rps_poc_st_curr_after++; + } else if ((hevc_picture->flags & VA_PICTURE_HEVC_RPS_LT_CURR) != 0) { + slice_params->dpb[i].rps = + V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR; + num_rps_poc_lt_curr++; + } + + field_pic = !!(hevc_picture->flags & VA_PICTURE_HEVC_FIELD_PIC); + + slice_params->dpb[i].field_pic = field_pic; + + /* TODO: Interleaved: Get the POC for each field. */ + slice_params->dpb[i].pic_order_cnt[0] = + hevc_picture->pic_order_cnt; + + num_active_dpb_entries++; + } + + slice_params->num_active_dpb_entries = num_active_dpb_entries; + + count = slice_params->num_ref_idx_l0_active_minus1 + 1; + + for (i = 0; i < count && slice_type != V4L2_HEVC_SLICE_TYPE_I; i++) + slice_params->ref_idx_l0[i] = slice->RefPicList[0][i]; + + count = slice_params->num_ref_idx_l1_active_minus1 + 1; + + for (i = 0; i < count && slice_type == V4L2_HEVC_SLICE_TYPE_B ; i++) + slice_params->ref_idx_l1[i] = slice->RefPicList[1][i]; + + slice_params->num_rps_poc_st_curr_before = num_rps_poc_st_curr_before; + slice_params->num_rps_poc_st_curr_after = num_rps_poc_st_curr_after; + slice_params->num_rps_poc_lt_curr = num_rps_poc_lt_curr; + + slice_params->pred_weight_table.luma_log2_weight_denom = + slice->luma_log2_weight_denom; + slice_params->pred_weight_table.delta_chroma_log2_weight_denom = + slice->delta_chroma_log2_weight_denom; + + for (i = 0; i < 15 && slice_type != V4L2_HEVC_SLICE_TYPE_I; i++) { + slice_params->pred_weight_table.delta_luma_weight_l0[i] = + slice->delta_luma_weight_l0[i]; + slice_params->pred_weight_table.luma_offset_l0[i] = + slice->luma_offset_l0[i]; + + for (j = 0; j < 2; j++) { + slice_params->pred_weight_table.delta_chroma_weight_l0[i][j] = + slice->delta_chroma_weight_l0[i][j]; + slice_params->pred_weight_table.chroma_offset_l0[i][j] = + slice->ChromaOffsetL0[i][j]; + } + } + + for (i = 0; i < 15 && slice_type == V4L2_HEVC_SLICE_TYPE_B; i++) { + slice_params->pred_weight_table.delta_luma_weight_l1[i] = + slice->delta_luma_weight_l1[i]; + slice_params->pred_weight_table.luma_offset_l1[i] = + slice->luma_offset_l1[i]; + + for (j = 0; j < 2; j++) { + slice_params->pred_weight_table.delta_chroma_weight_l1[i][j] = + slice->delta_chroma_weight_l1[i][j]; + slice_params->pred_weight_table.chroma_offset_l1[i][j] = + slice->ChromaOffsetL1[i][j]; + } + } +} + +int h265_set_controls(struct request_data *driver_data, + struct object_context *context_object, + struct object_surface *surface_object) +{ + VAPictureParameterBufferHEVC *picture = + &surface_object->params.h265.picture; + VASliceParameterBufferHEVC *slice = + &surface_object->params.h265.slice; + VAIQMatrixBufferHEVC *iqmatrix = + &surface_object->params.h265.iqmatrix; + bool iqmatrix_set = surface_object->params.h265.iqmatrix_set; + struct v4l2_ctrl_hevc_pps pps; + struct v4l2_ctrl_hevc_sps sps; + struct v4l2_ctrl_hevc_slice_params slice_params; + int rc; + + h265_fill_pps(picture, slice, &pps); + + rc = v4l2_set_control(driver_data->video_fd, surface_object->request_fd, + V4L2_CID_MPEG_VIDEO_HEVC_PPS, &pps, sizeof(pps)); + if (rc < 0) + return VA_STATUS_ERROR_OPERATION_FAILED; + + h265_fill_sps(picture, &sps); + + rc = v4l2_set_control(driver_data->video_fd, surface_object->request_fd, + V4L2_CID_MPEG_VIDEO_HEVC_SPS, &sps, sizeof(sps)); + if (rc < 0) + return VA_STATUS_ERROR_OPERATION_FAILED; + + h265_fill_slice_params(picture, slice, &driver_data->surface_heap, + surface_object->source_data, &slice_params); + + rc = v4l2_set_control(driver_data->video_fd, surface_object->request_fd, + V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS, + &slice_params, sizeof(slice_params)); + if (rc < 0) + return VA_STATUS_ERROR_OPERATION_FAILED; + + return 0; +} diff --git a/src/h265.h b/src/h265.h new file mode 100644 index 0000000..ce412ee --- /dev/null +++ b/src/h265.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 Florent Revest, + * 2007 Intel Corporation. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _H265_H_ +#define _H265_H_ + +struct object_context; +struct object_surface; +struct request_data; + +int h265_set_controls(struct request_data *driver_data, + struct object_context *context_object, + struct object_surface *surface_object); + +#endif diff --git a/src/picture.c b/src/picture.c index 696b326..f1ec1c3 100644 --- a/src/picture.c +++ b/src/picture.c @@ -31,6 +31,7 @@ #include "surface.h" #include "h264.h" +#include "h265.h" #include "mpeg2.h" #include @@ -76,6 +77,7 @@ static VAStatus codec_store_buffer(struct request_data *driver_data, buffer_object->data, sizeof(surface_object->params.mpeg2.picture)); break; + case VAProfileH264Main: case VAProfileH264High: case VAProfileH264ConstrainedBaseline: @@ -85,6 +87,13 @@ static VAStatus codec_store_buffer(struct request_data *driver_data, buffer_object->data, sizeof(surface_object->params.h264.picture)); break; + + case VAProfileHEVCMain: + memcpy(&surface_object->params.h265.picture, + buffer_object->data, + sizeof(surface_object->params.h265.picture)); + break; + default: break; } @@ -102,6 +111,12 @@ static VAStatus codec_store_buffer(struct request_data *driver_data, sizeof(surface_object->params.h264.slice)); break; + case VAProfileHEVCMain: + memcpy(&surface_object->params.h265.slice, + buffer_object->data, + sizeof(surface_object->params.h265.slice)); + break; + default: break; } @@ -127,6 +142,13 @@ static VAStatus codec_store_buffer(struct request_data *driver_data, sizeof(surface_object->params.h264.matrix)); break; + case VAProfileHEVCMain: + memcpy(&surface_object->params.h265.iqmatrix, + buffer_object->data, + sizeof(surface_object->params.h265.iqmatrix)); + surface_object->params.h265.iqmatrix_set = true; + break; + default: break; } @@ -164,6 +186,12 @@ static VAStatus codec_set_controls(struct request_data *driver_data, return VA_STATUS_ERROR_OPERATION_FAILED; break; + case VAProfileHEVCMain: + rc = h265_set_controls(driver_data, context, surface_object); + if (rc < 0) + return VA_STATUS_ERROR_OPERATION_FAILED; + break; + default: return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; } diff --git a/src/surface.h b/src/surface.h index c3f69da..56a366a 100644 --- a/src/surface.h +++ b/src/surface.h @@ -73,6 +73,12 @@ struct object_surface { VAPictureParameterBufferH264 picture; VASliceParameterBufferH264 slice; } h264; + struct { + VAPictureParameterBufferHEVC picture; + VASliceParameterBufferHEVC slice; + VAIQMatrixBufferHEVC iqmatrix; + bool iqmatrix_set; + } h265; } params; int request_fd;