[Libva] [PATCH V3 6/7] HEVC ENC:Added HEVC support in API function
Xiang, Haihao
haihao.xiang at intel.com
Tue Jan 6 21:03:11 PST 2015
On Wed, 2015-01-07 at 11:01 +0800, Qu,Pengfei wrote:
> Signed-off-by: Qu,Pengfei <Pengfei.Qu at intel.com>
> ---
> src/i965_device_info.c | 1 +
> src/i965_drv_video.c | 121 +++++++++++++++++++++++++++++++++++++++++--------
> 2 files changed, 103 insertions(+), 19 deletions(-)
>
> diff --git a/src/i965_device_info.c b/src/i965_device_info.c
> index d03aceb..9ccc85e 100755
> --- a/src/i965_device_info.c
> +++ b/src/i965_device_info.c
> @@ -347,6 +347,7 @@ static struct hw_codec_info skl_hw_codec_info = {
> .has_blending = 1,
> .has_h264_mvc_encoding = 1,
> .has_hevc_decoding = 1,
> + .has_hevc_encoding = 1,
>
> .num_filters = 5,
> .filters = {
> diff --git a/src/i965_drv_video.c b/src/i965_drv_video.c
> index 74895da..ca9703b 100644
> --- a/src/i965_drv_video.c
> +++ b/src/i965_drv_video.c
> @@ -104,6 +104,9 @@
> #define HAS_HEVC_DECODING(ctx) ((ctx)->codec_info->has_hevc_decoding && \
> (ctx)->intel.has_bsd)
>
> +#define HAS_HEVC_ENCODING(ctx) ((ctx)->codec_info->has_hevc_encoding && \
> + (ctx)->intel.has_bsd)
> +
> static int get_sampling_from_fourcc(unsigned int fourcc);
>
> /* Check whether we are rendering to X11 (VA/X11 or VA/GLX API) */
> @@ -376,7 +379,10 @@ is_image_busy(struct i965_driver_data *i965, struct object_image *obj_image)
> }
>
> #define I965_PACKED_HEADER_BASE 0
> -#define I965_PACKED_MISC_HEADER_BASE 3
> +#define I965_SEQ_PACKED_HEADER_BASE 0
> +#define I965_SEQ_PACKED_HEADER_END 2
> +#define I965_PIC_PACKED_HEADER_BASE 2
> +#define I965_PACKED_MISC_HEADER_BASE 4
>
> int
> va_enc_packed_type_to_idx(int packed_type)
> @@ -393,15 +399,15 @@ va_enc_packed_type_to_idx(int packed_type)
>
> switch (packed_type) {
> case VAEncPackedHeaderSequence:
> - idx = I965_PACKED_HEADER_BASE + 0;
> + idx = I965_SEQ_PACKED_HEADER_BASE + 0;
> break;
>
> case VAEncPackedHeaderPicture:
> - idx = I965_PACKED_HEADER_BASE + 1;
> + idx = I965_PIC_PACKED_HEADER_BASE + 0;
> break;
>
> case VAEncPackedHeaderSlice:
> - idx = I965_PACKED_HEADER_BASE + 2;
> + idx = I965_PIC_PACKED_HEADER_BASE + 1;
> break;
>
> default:
> @@ -411,7 +417,7 @@ va_enc_packed_type_to_idx(int packed_type)
> }
> }
>
> - ASSERT_RET(idx < 4, 0);
> + ASSERT_RET(idx < 5, 0);
> return idx;
> }
>
> @@ -465,7 +471,8 @@ i965_QueryConfigProfiles(VADriverContextP ctx,
> profile_list[i++] = VAProfileH264StereoHigh;
> }
>
> - if (HAS_HEVC_DECODING(i965)) {
> + if (HAS_HEVC_DECODING(i965)||
> + HAS_HEVC_ENCODING(i965)) {
> profile_list[i++] = VAProfileHEVCMain;
> }
>
> @@ -548,6 +555,9 @@ i965_QueryConfigEntrypoints(VADriverContextP ctx,
> if (HAS_HEVC_DECODING(i965))
> entrypoint_list[n++] = VAEntrypointVLD;
>
> + if (HAS_HEVC_ENCODING(i965))
> + entrypoint_list[n++] = VAEntrypointEncSlice;
> +
> break;
>
> default:
> @@ -639,7 +649,8 @@ i965_validate_config(VADriverContextP ctx, VAProfile profile,
> break;
>
> case VAProfileHEVCMain:
> - if (HAS_HEVC_DECODING(i965) && (entrypoint == VAEntrypointVLD))
> + if ((HAS_HEVC_DECODING(i965) && (entrypoint == VAEntrypointVLD))||
> + (HAS_HEVC_ENCODING(i965) && (entrypoint == VAEntrypointEncSlice)))
> va_status = VA_STATUS_SUCCESS;
> else
> va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
> @@ -729,7 +740,8 @@ i965_GetConfigAttributes(VADriverContextP ctx,
> profile == VAProfileH264Main ||
> profile == VAProfileH264High ||
> profile == VAProfileH264StereoHigh ||
> - profile == VAProfileH264MultiviewHigh) {
> + profile == VAProfileH264MultiviewHigh ||
> + profile == VAProfileHEVCMain) {
> attrib_list[i].value |= (VA_ENC_PACKED_HEADER_RAW_DATA |
> VA_ENC_PACKED_HEADER_SLICE);
> }
> @@ -1894,6 +1906,8 @@ i965_CreateContext(VADriverContextP ctx,
> obj_context->codec_state.encode.slice_header_index =
> calloc(obj_context->codec_state.encode.max_slice_num, sizeof(int));
>
> + obj_context->codec_state.encode.vps_sps_seq_index = 0;
> +
> obj_context->codec_state.encode.slice_index = 0;
> packed_attrib = i965_lookup_config_attribute(obj_config, VAConfigAttribEncPackedHeaders);
> if (packed_attrib)
> @@ -1980,6 +1994,20 @@ i965_create_buffer_internal(VADriverContextP ctx,
> struct object_buffer *obj_buffer = NULL;
> struct buffer_store *buffer_store = NULL;
> int bufferID;
> + struct object_context *obj_context = NULL;
> + struct object_config *obj_config = NULL;
> + VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
> +
> + if (i965->current_context_id == VA_INVALID_ID)
> + return vaStatus;
> +
> + obj_context = CONTEXT(i965->current_context_id);
> +
> + if (!obj_context)
> + return vaStatus;
> +
> + obj_config = obj_context->obj_config;
> + assert(obj_config);
>
> /* Validate type */
> switch (type) {
> @@ -2053,7 +2081,11 @@ i965_create_buffer_internal(VADriverContextP ctx,
> struct i965_coded_buffer_segment *coded_buffer_segment;
>
> dri_bo_map(buffer_store->bo, 1);
> - coded_buffer_segment = (struct i965_coded_buffer_segment *)buffer_store->bo->virtual;
> + if(obj_config->profile == VAProfileHEVCMain){
> + coded_buffer_segment = (struct i965_coded_buffer_segment *)(buffer_store->bo->virtual + ALIGN(size - 0x1000, 0x1000));
> + }else {
> + coded_buffer_segment = (struct i965_coded_buffer_segment *)buffer_store->bo->virtual;
> + }
Now I965_CODEDBUFFER_HEADER_SIZE is defined as 0x1000, you can place
coded_buffer_segment at the beginning of the buffer too, and you will
change few code to support coded buffer for HEVC
> coded_buffer_segment->base.size = size - I965_CODEDBUFFER_HEADER_SIZE;
> coded_buffer_segment->base.bit_offset = 0;
> coded_buffer_segment->base.status = 0;
> @@ -2131,9 +2163,22 @@ i965_MapBuffer(VADriverContextP ctx,
> void **pbuf) /* out */
> {
> struct i965_driver_data *i965 = i965_driver_data(ctx);
> + struct object_context *obj_context = NULL;
> + struct object_config *obj_config = NULL;
> struct object_buffer *obj_buffer = BUFFER(buf_id);
> VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
>
> + if (i965->current_context_id == VA_INVALID_ID)
> + return vaStatus;
> +
> + obj_context = CONTEXT(i965->current_context_id);
> +
> + if (!obj_context)
> + return vaStatus;
> +
> + obj_config = obj_context->obj_config;
> + assert(obj_config);
> +
> ASSERT_RET(obj_buffer && obj_buffer->buffer_store, VA_STATUS_ERROR_INVALID_BUFFER);
> ASSERT_RET(obj_buffer->buffer_store->bo || obj_buffer->buffer_store->buffer, VA_STATUS_ERROR_INVALID_BUFFER);
> ASSERT_RET(!(obj_buffer->buffer_store->bo && obj_buffer->buffer_store->buffer), VA_STATUS_ERROR_INVALID_BUFFER);
> @@ -2157,21 +2202,28 @@ i965_MapBuffer(VADriverContextP ctx,
> if (obj_buffer->type == VAEncCodedBufferType) {
> int i;
> unsigned char *buffer = NULL;
> + unsigned int header_offset = I965_CODEDBUFFER_HEADER_SIZE;
> struct i965_coded_buffer_segment *coded_buffer_segment = (struct i965_coded_buffer_segment *)(obj_buffer->buffer_store->bo->virtual);
>
> + if(obj_config->profile == VAProfileHEVCMain){
> + coded_buffer_segment = (struct i965_coded_buffer_segment *)(obj_buffer->buffer_store->bo->virtual + ALIGN(obj_buffer->size_element - 0x1000, 0x1000));
> + *pbuf = (unsigned char *)(obj_buffer->buffer_store->bo->virtual + ALIGN(obj_buffer->size_element - 0x1000, 0x1000));
> + }
> +
> if (!coded_buffer_segment->mapped) {
> unsigned char delimiter0, delimiter1, delimiter2, delimiter3, delimiter4;
>
> - coded_buffer_segment->base.buf = buffer = (unsigned char *)(obj_buffer->buffer_store->bo->virtual) + I965_CODEDBUFFER_HEADER_SIZE;
>
> if (coded_buffer_segment->codec == CODEC_H264 ||
> coded_buffer_segment->codec == CODEC_H264_MVC) {
> + coded_buffer_segment->base.buf = buffer = (unsigned char *)(obj_buffer->buffer_store->bo->virtual) + I965_CODEDBUFFER_HEADER_SIZE;
> delimiter0 = H264_DELIMITER0;
> delimiter1 = H264_DELIMITER1;
> delimiter2 = H264_DELIMITER2;
> delimiter3 = H264_DELIMITER3;
> delimiter4 = H264_DELIMITER4;
> } else if (coded_buffer_segment->codec == CODEC_MPEG2) {
> + coded_buffer_segment->base.buf = buffer = (unsigned char *)(obj_buffer->buffer_store->bo->virtual) + I965_CODEDBUFFER_HEADER_SIZE;
> delimiter0 = MPEG2_DELIMITER0;
> delimiter1 = MPEG2_DELIMITER1;
> delimiter2 = MPEG2_DELIMITER2;
> @@ -2179,26 +2231,35 @@ i965_MapBuffer(VADriverContextP ctx,
> delimiter4 = MPEG2_DELIMITER4;
> } else if(coded_buffer_segment->codec == CODEC_JPEG) {
> //In JPEG End of Image (EOI = 0xDDF9) marker can be used for delimiter.
> + coded_buffer_segment->base.buf = buffer = (unsigned char *)(obj_buffer->buffer_store->bo->virtual);
> delimiter0 = 0xFF;
> delimiter1 = 0xD9;
> - } else {
> + } else if (coded_buffer_segment->codec == CODEC_HEVC) {
> + coded_buffer_segment->base.buf = buffer = (unsigned char *)(obj_buffer->buffer_store->bo->virtual);
> + header_offset = 0 ;
> + delimiter0 = HEVC_DELIMITER0;
> + delimiter1 = HEVC_DELIMITER1;
> + delimiter2 = HEVC_DELIMITER2;
> + delimiter3 = HEVC_DELIMITER3;
> + delimiter4 = HEVC_DELIMITER4;
> + } else {
> ASSERT_RET(0, VA_STATUS_ERROR_UNSUPPORTED_PROFILE);
> }
>
> if(coded_buffer_segment->codec == CODEC_JPEG) {
> - for(i = 0; i < obj_buffer->size_element - I965_CODEDBUFFER_HEADER_SIZE - 1 - 0x1000; i++) {
> + for(i = 0; i < obj_buffer->size_element - header_offset - 1 - 0x1000; i++) {
> if( (buffer[i] == 0xFF) && (buffer[i + 1] == 0xD9)) {
> break;
> }
> }
>
> - if (i == obj_buffer->size_element - I965_CODEDBUFFER_HEADER_SIZE - 1 - 0x1000) {
> + if (i == obj_buffer->size_element - header_offset - 1 - 0x1000) {
> coded_buffer_segment->base.status |= VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK;
> }
>
> coded_buffer_segment->base.size = i + 2;
> } else {
> - for (i = 0; i < obj_buffer->size_element - I965_CODEDBUFFER_HEADER_SIZE - 3 - 0x1000; i++) {
> + for (i = 0; i < obj_buffer->size_element - header_offset - 3 - 0x1000; i++) {
> if ((buffer[i] == delimiter0) &&
> (buffer[i + 1] == delimiter1) &&
> (buffer[i + 2] == delimiter2) &&
> @@ -2207,7 +2268,7 @@ i965_MapBuffer(VADriverContextP ctx,
> break;
> }
>
> - if (i == obj_buffer->size_element - I965_CODEDBUFFER_HEADER_SIZE - 3 - 0x1000) {
> + if (i == obj_buffer->size_element - header_offset - 3 - 0x1000) {
> coded_buffer_segment->base.status |= VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK;
> }
> coded_buffer_segment->base.size = i;
> @@ -2383,6 +2444,7 @@ i965_BeginPicture(VADriverContextP ctx,
> obj_context->codec_state.encode.num_packed_header_params_ext = 0;
> obj_context->codec_state.encode.num_packed_header_data_ext = 0;
> obj_context->codec_state.encode.slice_index = 0;
> + obj_context->codec_state.encode.vps_sps_seq_index = 0;
> } else {
> obj_context->codec_state.decode.current_render_target = render_target;
> i965_release_buffer_store(&obj_context->codec_state.decode.pic_param);
> @@ -2586,11 +2648,14 @@ i965_encoder_render_picture(VADriverContextP ctx,
> {
> struct i965_driver_data *i965 = i965_driver_data(ctx);
> struct object_context *obj_context = CONTEXT(context);
> + struct object_config *obj_config;
> VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
> struct encode_state *encode;
> int i;
>
> ASSERT_RET(obj_context, VA_STATUS_ERROR_INVALID_CONTEXT);
> + obj_config = obj_context->obj_config;
> + ASSERT_RET(obj_config, VA_STATUS_ERROR_INVALID_CONFIG);
>
> encode = &obj_context->codec_state.encode;
> for (i = 0; i < num_buffers; i++) {
> @@ -2664,6 +2729,12 @@ 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)&&
> + (encode->last_packed_header_type == VAEncPackedHeaderSequence)) {
> + vaStatus = i965_encoder_render_packed_header_parameter_buffer(ctx,
> + obj_context,
> + obj_buffer,
> + va_enc_packed_type_to_idx(encode->last_packed_header_type) + encode->vps_sps_seq_index);
> } else {
> vaStatus = i965_encoder_render_packed_header_parameter_buffer(ctx,
> obj_context,
> @@ -2751,10 +2822,22 @@ i965_encoder_render_picture(VADriverContextP ctx,
> (((encode->last_packed_header_type & VAEncPackedHeaderMiscMask) == VAEncPackedHeaderMiscMask) &&
> ((encode->last_packed_header_type & (~VAEncPackedHeaderMiscMask)) != 0)),
> VA_STATUS_ERROR_ENCODING_ERROR);
> - vaStatus = i965_encoder_render_packed_header_data_buffer(ctx,
> - obj_context,
> - obj_buffer,
> - va_enc_packed_type_to_idx(encode->last_packed_header_type));
> +
> + if((obj_config->profile == VAProfileHEVCMain)&&
> + (encode->last_packed_header_type == VAEncPackedHeaderSequence)) {
> +
> + vaStatus = i965_encoder_render_packed_header_data_buffer(ctx,
> + obj_context,
> + obj_buffer,
> + va_enc_packed_type_to_idx(encode->last_packed_header_type) + encode->vps_sps_seq_index);
> + encode->vps_sps_seq_index = (encode->vps_sps_seq_index + 1) % I965_SEQ_PACKED_HEADER_END;
> + }else{
> + vaStatus = i965_encoder_render_packed_header_data_buffer(ctx,
> + obj_context,
> + obj_buffer,
> + va_enc_packed_type_to_idx(encode->last_packed_header_type));
> +
> + }
> }
> encode->last_packed_header_type = 0;
> break;
More information about the Libva
mailing list