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:
@@ -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
|
||||
|
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user