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 <zzoon@igalia.com>
Acked-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36152>
This commit is contained in:
Hyunjun Ko
2025-07-04 15:17:29 +09:00
committed by Marge Bot
parent 94619a0f4b
commit 62b07c01d1
2 changed files with 21 additions and 8 deletions
+2 -3
View File
@@ -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;
+19 -5
View File
@@ -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;