vulkan/video: add h264 headers encode

Vulkan video has parameter overrides, where the driver can override the
driver provided parameters with an encoded bitstream where it has made
changes.

This is the support code to encode the bitstream headers for h264
from parameters (sps/pps).

Reviewed-by: Hyunjun Ko <zzoon@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25874>
This commit is contained in:
Dave Airlie
2023-10-17 11:30:20 +10:00
committed by Marge Bot
parent 8243145f02
commit d46162981a
2 changed files with 210 additions and 0 deletions

View File

@@ -27,6 +27,7 @@
#include "vk_alloc.h"
#include "vk_device.h"
#include "util/vl_rbsp.h"
#include "util/vl_bitstream.h"
VkResult
vk_video_session_init(struct vk_device *device,
@@ -1366,4 +1367,200 @@ vk_video_get_h265_level(StdVideoH265LevelIdc level)
return vk_video_h265_levels[level];
}
static void
emit_nalu_header(struct vl_bitstream_encoder *enc,
int nal_ref, int nal_unit)
{
enc->prevent_start_code = false;
vl_bitstream_put_bits(enc, 24, 0);
vl_bitstream_put_bits(enc, 8, 1);
vl_bitstream_put_bits(enc, 1, 0);
vl_bitstream_put_bits(enc, 2, nal_ref); /* SPS NAL REF */
vl_bitstream_put_bits(enc, 5, nal_unit); /* SPS NAL UNIT */
vl_bitstream_flush(enc);
enc->prevent_start_code = true;
}
static void
encode_hrd_params(struct vl_bitstream_encoder *enc,
const StdVideoH264HrdParameters *hrd)
{
vl_bitstream_exp_golomb_ue(enc, hrd->cpb_cnt_minus1);
vl_bitstream_put_bits(enc, 4, hrd->bit_rate_scale);
vl_bitstream_put_bits(enc, 4, hrd->cpb_size_scale);
for (int sched_sel_idx = 0; sched_sel_idx <= hrd->cpb_cnt_minus1; sched_sel_idx++) {
vl_bitstream_exp_golomb_ue(enc, hrd->bit_rate_value_minus1[sched_sel_idx]);
vl_bitstream_exp_golomb_ue(enc, hrd->cpb_size_value_minus1[sched_sel_idx]);
vl_bitstream_put_bits(enc, 1, hrd->cbr_flag[sched_sel_idx]);
}
vl_bitstream_put_bits(enc, 5, hrd->initial_cpb_removal_delay_length_minus1);
vl_bitstream_put_bits(enc, 5, hrd->cpb_removal_delay_length_minus1);
vl_bitstream_put_bits(enc, 5, hrd->dpb_output_delay_length_minus1);
vl_bitstream_put_bits(enc, 5, hrd->time_offset_length);
}
void
vk_video_encode_h264_sps(StdVideoH264SequenceParameterSet *sps,
size_t size_limit,
size_t *data_size_ptr,
void *data_ptr)
{
struct vl_bitstream_encoder enc;
uint32_t data_size = *data_size_ptr;
vl_bitstream_encoder_clear(&enc, data_ptr, data_size, size_limit);
emit_nalu_header(&enc, 3, H264_NAL_SPS);
vl_bitstream_put_bits(&enc, 8, sps->profile_idc);
vl_bitstream_put_bits(&enc, 1, sps->flags.constraint_set0_flag);
vl_bitstream_put_bits(&enc, 1, sps->flags.constraint_set1_flag);
vl_bitstream_put_bits(&enc, 1, sps->flags.constraint_set2_flag);
vl_bitstream_put_bits(&enc, 1, sps->flags.constraint_set3_flag);
vl_bitstream_put_bits(&enc, 1, sps->flags.constraint_set4_flag);
vl_bitstream_put_bits(&enc, 1, sps->flags.constraint_set5_flag);
vl_bitstream_put_bits(&enc, 2, 0);
vl_bitstream_put_bits(&enc, 8, vk_video_get_h264_level(sps->level_idc));
vl_bitstream_exp_golomb_ue(&enc, sps->seq_parameter_set_id);
if (sps->profile_idc == STD_VIDEO_H264_PROFILE_IDC_HIGH /* high10 as well */) {
vl_bitstream_exp_golomb_ue(&enc, sps->chroma_format_idc);
vl_bitstream_exp_golomb_ue(&enc, sps->bit_depth_luma_minus8);
vl_bitstream_exp_golomb_ue(&enc, sps->bit_depth_chroma_minus8);
vl_bitstream_put_bits(&enc, 1, sps->flags.qpprime_y_zero_transform_bypass_flag);
vl_bitstream_put_bits(&enc, 1, sps->flags.seq_scaling_matrix_present_flag);
}
vl_bitstream_exp_golomb_ue(&enc, sps->log2_max_frame_num_minus4);
vl_bitstream_exp_golomb_ue(&enc, sps->pic_order_cnt_type);
if (sps->pic_order_cnt_type == 0)
vl_bitstream_exp_golomb_ue(&enc, sps->log2_max_pic_order_cnt_lsb_minus4);
vl_bitstream_exp_golomb_ue(&enc, sps->max_num_ref_frames);
vl_bitstream_put_bits(&enc, 1, sps->flags.gaps_in_frame_num_value_allowed_flag);
vl_bitstream_exp_golomb_ue(&enc, sps->pic_width_in_mbs_minus1);
vl_bitstream_exp_golomb_ue(&enc, sps->pic_height_in_map_units_minus1);
vl_bitstream_put_bits(&enc, 1, sps->flags.frame_mbs_only_flag);
vl_bitstream_put_bits(&enc, 1, sps->flags.direct_8x8_inference_flag);
vl_bitstream_put_bits(&enc, 1, sps->flags.frame_cropping_flag);
if (sps->flags.frame_cropping_flag) {
vl_bitstream_exp_golomb_ue(&enc, sps->frame_crop_left_offset);
vl_bitstream_exp_golomb_ue(&enc, sps->frame_crop_right_offset);
vl_bitstream_exp_golomb_ue(&enc, sps->frame_crop_top_offset);
vl_bitstream_exp_golomb_ue(&enc, sps->frame_crop_bottom_offset);
}
vl_bitstream_put_bits(&enc, 1, sps->flags.vui_parameters_present_flag); /* vui parameters preseent flag */
if (sps->flags.vui_parameters_present_flag) {
const StdVideoH264SequenceParameterSetVui *vui = sps->pSequenceParameterSetVui;
vl_bitstream_put_bits(&enc, 1, vui->flags.aspect_ratio_info_present_flag);
if (vui->flags.aspect_ratio_info_present_flag) {
vl_bitstream_put_bits(&enc, 8, vui->aspect_ratio_idc);
if (vui->aspect_ratio_idc == STD_VIDEO_H264_ASPECT_RATIO_IDC_EXTENDED_SAR) {
vl_bitstream_put_bits(&enc, 16, vui->sar_width);
vl_bitstream_put_bits(&enc, 16, vui->sar_height);
}
vl_bitstream_put_bits(&enc, 1, vui->flags.overscan_info_present_flag);
if (vui->flags.overscan_info_present_flag)
vl_bitstream_put_bits(&enc, 1, vui->flags.overscan_appropriate_flag);
vl_bitstream_put_bits(&enc, 1, vui->flags.video_signal_type_present_flag);
if (vui->flags.video_signal_type_present_flag) {
vl_bitstream_put_bits(&enc, 3, vui->video_format);
vl_bitstream_put_bits(&enc, 1, vui->flags.video_full_range_flag);
vl_bitstream_put_bits(&enc, 1, vui->flags.color_description_present_flag);
if (vui->flags.color_description_present_flag) {
vl_bitstream_put_bits(&enc, 8, vui->colour_primaries);
vl_bitstream_put_bits(&enc, 8, vui->transfer_characteristics);
vl_bitstream_put_bits(&enc, 8, vui->matrix_coefficients);
}
}
vl_bitstream_put_bits(&enc, 1, vui->flags.chroma_loc_info_present_flag);
if (vui->flags.chroma_loc_info_present_flag) {
vl_bitstream_exp_golomb_ue(&enc, vui->chroma_sample_loc_type_top_field);
vl_bitstream_exp_golomb_ue(&enc, vui->chroma_sample_loc_type_bottom_field);
}
vl_bitstream_put_bits(&enc, 1, vui->flags.timing_info_present_flag);
if (vui->flags.timing_info_present_flag) {
vl_bitstream_put_bits(&enc, 32, vui->num_units_in_tick);
vl_bitstream_put_bits(&enc, 32, vui->time_scale);
vl_bitstream_put_bits(&enc, 32, vui->flags.fixed_frame_rate_flag);
}
vl_bitstream_put_bits(&enc, 1, vui->flags.nal_hrd_parameters_present_flag);
if (vui->flags.nal_hrd_parameters_present_flag)
encode_hrd_params(&enc, vui->pHrdParameters);
vl_bitstream_put_bits(&enc, 1, vui->flags.vcl_hrd_parameters_present_flag);
if (vui->flags.vcl_hrd_parameters_present_flag)
encode_hrd_params(&enc, vui->pHrdParameters);
if (vui->flags.nal_hrd_parameters_present_flag || vui->flags.vcl_hrd_parameters_present_flag)
vl_bitstream_put_bits(&enc, 1, 0);
vl_bitstream_put_bits(&enc, 1, 0);
vl_bitstream_put_bits(&enc, 1, vui->flags.bitstream_restriction_flag);
if (vui->flags.bitstream_restriction_flag) {
vl_bitstream_put_bits(&enc, 1, 0);
vl_bitstream_exp_golomb_ue(&enc, 0);
vl_bitstream_exp_golomb_ue(&enc, 0);
vl_bitstream_exp_golomb_ue(&enc, 0);
vl_bitstream_exp_golomb_ue(&enc, 0);
vl_bitstream_exp_golomb_ue(&enc, vui->max_num_reorder_frames);
vl_bitstream_exp_golomb_ue(&enc, vui->max_dec_frame_buffering);
}
}
}
vl_bitstream_rbsp_trailing(&enc);
vl_bitstream_flush(&enc);
*data_size_ptr += vl_bitstream_get_byte_count(&enc);
vl_bitstream_encoder_free(&enc);
}
void
vk_video_encode_h264_pps(StdVideoH264PictureParameterSet *pps,
bool high_profile,
size_t size_limit,
size_t *data_size_ptr,
void *data_ptr)
{
struct vl_bitstream_encoder enc;
uint32_t data_size = *data_size_ptr;
vl_bitstream_encoder_clear(&enc, data_ptr, data_size, size_limit);
emit_nalu_header(&enc, 3, H264_NAL_SPS);
vl_bitstream_exp_golomb_ue(&enc, pps->pic_parameter_set_id);
vl_bitstream_exp_golomb_ue(&enc, pps->seq_parameter_set_id);
vl_bitstream_put_bits(&enc, 1, pps->flags.entropy_coding_mode_flag);
vl_bitstream_put_bits(&enc, 1, pps->flags.bottom_field_pic_order_in_frame_present_flag);
vl_bitstream_exp_golomb_ue(&enc, 0); /* num_slice_groups_minus1 */
vl_bitstream_exp_golomb_ue(&enc, pps->num_ref_idx_l0_default_active_minus1);
vl_bitstream_exp_golomb_ue(&enc, pps->num_ref_idx_l1_default_active_minus1);
vl_bitstream_put_bits(&enc, 1, pps->flags.weighted_pred_flag);
vl_bitstream_put_bits(&enc, 2, pps->weighted_bipred_idc);
vl_bitstream_exp_golomb_se(&enc, pps->pic_init_qp_minus26);
vl_bitstream_exp_golomb_se(&enc, pps->pic_init_qs_minus26);
vl_bitstream_exp_golomb_se(&enc, pps->chroma_qp_index_offset);
vl_bitstream_put_bits(&enc, 1, pps->flags.deblocking_filter_control_present_flag);
vl_bitstream_put_bits(&enc, 1, pps->flags.constrained_intra_pred_flag);
vl_bitstream_put_bits(&enc, 1, pps->flags.redundant_pic_cnt_present_flag);
/* high profile */
if (high_profile) {
vl_bitstream_put_bits(&enc, 1, pps->flags.transform_8x8_mode_flag);
vl_bitstream_put_bits(&enc, 1, pps->flags.pic_scaling_matrix_present_flag);
vl_bitstream_exp_golomb_se(&enc, pps->second_chroma_qp_index_offset);
}
vl_bitstream_rbsp_trailing(&enc);
vl_bitstream_flush(&enc);
*data_size_ptr += vl_bitstream_get_byte_count(&enc);
vl_bitstream_encoder_free(&enc);
}
#endif

View File

@@ -252,6 +252,19 @@ const StdVideoH265PictureParameterSet *
vk_video_find_h265_enc_std_pps(const struct vk_video_session_parameters *params,
uint32_t id);
void
vk_video_encode_h264_sps(StdVideoH264SequenceParameterSet *sps,
size_t size_limit,
size_t *data_size_ptr,
void *data_ptr);
void
vk_video_encode_h264_pps(StdVideoH264PictureParameterSet *pps,
bool high_profile,
size_t size_limit,
size_t *data_size_ptr,
void *data_ptr);
unsigned
vk_video_get_h265_nal_unit(StdVideoH265PictureType pic_type, bool irap_pic_flag);