From 62b07c01d1a2ba9e34321edeb1310696b772ae26 Mon Sep 17 00:00:00 2001 From: Hyunjun Ko Date: Fri, 4 Jul 2025 15:17:29 +0900 Subject: [PATCH] vulkan/video: fix to write a h264 slice header for CAVLC mode In CAVLC mode, slice header doesn't need to be aligned. Instead encoder needs exact bits written in the slice header in order to set the offset correctly. This fixes encoding with entropy_coding_mode_flag false. Signed-off-by: Hyunjun Ko Acked-by: Lionel Landwerlin Part-of: --- src/intel/vulkan/genX_cmd_video_enc.c | 5 ++--- src/vulkan/runtime/vk_video.c | 24 +++++++++++++++++++----- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/intel/vulkan/genX_cmd_video_enc.c b/src/intel/vulkan/genX_cmd_video_enc.c index 86050c8ff1d..1d0ebd7e547 100644 --- a/src/intel/vulkan/genX_cmd_video_enc.c +++ b/src/intel/vulkan/genX_cmd_video_enc.c @@ -1151,15 +1151,14 @@ anv_h264_encode_video(struct anv_cmd_buffer *cmd, const VkVideoEncodeInfoKHR *en unsigned h_in_mb = align(src_img->vk.extent.height, ANV_MB_HEIGHT) / ANV_MB_HEIGHT; uint8_t slice_header_data[256] = { 0, }; - size_t slice_header_data_len_in_bytes = 0; + size_t slice_header_data_len_in_bits = 0; vk_video_encode_h264_slice_header(frame_info->pStdPictureInfo, sps, pps, slice_header, slice_qp - (pps->pic_init_qp_minus26 + 26), - &slice_header_data_len_in_bytes, + &slice_header_data_len_in_bits, &slice_header_data); - uint32_t slice_header_data_len_in_bits = slice_header_data_len_in_bytes * 8; anv_batch_emit(&cmd->batch, GENX(MFX_AVC_SLICE_STATE), avc_slice) { avc_slice.SliceType = slice_type; diff --git a/src/vulkan/runtime/vk_video.c b/src/vulkan/runtime/vk_video.c index cc53d5d7d34..57d3dc4b210 100644 --- a/src/vulkan/runtime/vk_video.c +++ b/src/vulkan/runtime/vk_video.c @@ -2500,20 +2500,34 @@ vk_video_encode_h264_slice_header(const StdVideoEncodeH264PictureInfo *pic_info, } } + uint32_t bits_written = 0; + if (pps->flags.entropy_coding_mode_flag) { + /* CABAC */ int left = vl_bitstream_get_num_bits_for_byte_align(&enc); int val = (1 << left) - 1; - if (left) vl_bitstream_put_bits(&enc, left, val); - ASSERTED bool is_aligned = vl_bitstream_is_byte_aligned(&enc); - assert(is_aligned); + bits_written = vl_bitstream_get_byte_count(&enc) * 8; + } else { + /* CAVLC */ + uint32_t bits_in_last_byte = enc.bits_to_go == 32 ? 0 : 32 - enc.bits_to_go; + uint32_t bytes_written = enc.offset; + bits_written = bytes_written * 8 + bits_in_last_byte; + + /* Just padding to be aligned for flush, doesn't matter for the slice header. + */ + if (!vl_bitstream_is_byte_aligned(&enc)) { + uint32_t left = vl_bitstream_get_num_bits_for_byte_align(&enc); + + if (left) + vl_bitstream_put_bits(&enc, left, 0); + } } - vl_bitstream_rbsp_trailing(&enc); vl_bitstream_flush(&enc); - *data_size_ptr += vl_bitstream_get_byte_count(&enc); + *data_size_ptr += bits_written; vl_bitstream_encoder_free(&enc); return;