#![allow(
clippy::redundant_pub_crate,
reason = "workspace `unreachable_pub` policy (Cargo.toml) wants `pub(crate)` here; \
clippy::pedantic's redundant_pub_crate disagrees for private modules — the \
two lints are mutually exclusive for this shape, workspace policy wins"
)]
use vulkanalia::vk::video as native;
#[derive(Debug, Clone, Copy)]
pub(crate) struct McAlignedExtent {
pub(crate) width_mbs: u32,
pub(crate) height_mbs: u32,
}
impl McAlignedExtent {
pub(crate) const fn from_pixels(width: u32, height: u32) -> Option<Self> {
if width == 0 || height == 0 || width % 16 != 0 || height % 16 != 0 {
return None;
}
Some(Self {
width_mbs: width / 16,
height_mbs: height / 16,
})
}
}
fn sps_flags(
direct_8x8_inference_flag: bool,
frame_mbs_only_flag: bool,
) -> native::StdVideoH264SpsFlags {
let mut flags = native::StdVideoH264SpsFlags {
_bitfield_align_1: [],
_bitfield_1: native::__BindgenBitfieldUnit::new([0u8; 2]),
__bindgen_padding_0: 0,
};
flags.set_direct_8x8_inference_flag(u32::from(direct_8x8_inference_flag));
flags.set_frame_mbs_only_flag(u32::from(frame_mbs_only_flag));
flags
}
const fn pps_flags() -> native::StdVideoH264PpsFlags {
native::StdVideoH264PpsFlags {
_bitfield_align_1: [],
_bitfield_1: native::__BindgenBitfieldUnit::new([0u8; 1]),
__bindgen_padding_0: [0; 3],
}
}
fn idr_picture_info_flags() -> native::StdVideoEncodeH264PictureInfoFlags {
let mut flags = native::StdVideoEncodeH264PictureInfoFlags {
_bitfield_align_1: [],
_bitfield_1: native::__BindgenBitfieldUnit::new([0u8; 4]),
};
flags.set_IdrPicFlag(1);
flags.set_is_reference(1);
flags
}
const fn slice_header_flags() -> native::StdVideoEncodeH264SliceHeaderFlags {
native::StdVideoEncodeH264SliceHeaderFlags {
_bitfield_align_1: [],
_bitfield_1: native::__BindgenBitfieldUnit::new([0u8; 4]),
}
}
const fn reference_lists_info_flags() -> native::StdVideoEncodeH264ReferenceListsInfoFlags {
native::StdVideoEncodeH264ReferenceListsInfoFlags {
_bitfield_align_1: [],
_bitfield_1: native::__BindgenBitfieldUnit::new([0u8; 4]),
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct SpsGopParams {
pub(crate) log2_max_frame_num_minus4: u8,
pub(crate) max_num_ref_frames: u8,
}
impl SpsGopParams {
pub(crate) const IDR_ONLY: Self = Self {
log2_max_frame_num_minus4: 0,
max_num_ref_frames: 0,
};
}
pub(crate) fn build_sps(
extent: McAlignedExtent,
gop: SpsGopParams,
) -> native::StdVideoH264SequenceParameterSet {
native::StdVideoH264SequenceParameterSet {
flags: sps_flags(true, true),
profile_idc: native::STD_VIDEO_H264_PROFILE_IDC_BASELINE,
level_idc: native::STD_VIDEO_H264_LEVEL_IDC_1_0,
chroma_format_idc: native::STD_VIDEO_H264_CHROMA_FORMAT_IDC_420,
seq_parameter_set_id: 0,
bit_depth_luma_minus8: 0,
bit_depth_chroma_minus8: 0,
log2_max_frame_num_minus4: gop.log2_max_frame_num_minus4,
pic_order_cnt_type: native::STD_VIDEO_H264_POC_TYPE_2,
offset_for_non_ref_pic: 0,
offset_for_top_to_bottom_field: 0,
log2_max_pic_order_cnt_lsb_minus4: 0,
num_ref_frames_in_pic_order_cnt_cycle: 0,
max_num_ref_frames: gop.max_num_ref_frames,
reserved1: 0,
pic_width_in_mbs_minus1: extent.width_mbs - 1,
pic_height_in_map_units_minus1: extent.height_mbs - 1,
frame_crop_left_offset: 0,
frame_crop_right_offset: 0,
frame_crop_top_offset: 0,
frame_crop_bottom_offset: 0,
reserved2: 0,
pOffsetForRefFrame: core::ptr::null(),
pScalingLists: core::ptr::null(),
pSequenceParameterSetVui: core::ptr::null(),
}
}
pub(crate) const fn build_pps() -> native::StdVideoH264PictureParameterSet {
native::StdVideoH264PictureParameterSet {
flags: pps_flags(),
seq_parameter_set_id: 0,
pic_parameter_set_id: 0,
num_ref_idx_l0_default_active_minus1: 0,
num_ref_idx_l1_default_active_minus1: 0,
weighted_bipred_idc: native::StdVideoH264WeightedBipredIdc(0),
pic_init_qp_minus26: 0,
pic_init_qs_minus26: 0,
chroma_qp_index_offset: 0,
second_chroma_qp_index_offset: 0,
pScalingLists: core::ptr::null(),
}
}
pub(crate) const fn build_empty_reference_lists() -> native::StdVideoEncodeH264ReferenceListsInfo {
native::StdVideoEncodeH264ReferenceListsInfo {
flags: reference_lists_info_flags(),
num_ref_idx_l0_active_minus1: 0,
num_ref_idx_l1_active_minus1: 0,
RefPicList0: [0xFF; 32],
RefPicList1: [0xFF; 32],
refList0ModOpCount: 0,
refList1ModOpCount: 0,
refPicMarkingOpCount: 0,
reserved1: [0; 7],
pRefList0ModOperations: core::ptr::null(),
pRefList1ModOperations: core::ptr::null(),
pRefPicMarkingOperations: core::ptr::null(),
}
}
pub(crate) fn build_idr_picture_info() -> native::StdVideoEncodeH264PictureInfo {
native::StdVideoEncodeH264PictureInfo {
flags: idr_picture_info_flags(),
seq_parameter_set_id: 0,
pic_parameter_set_id: 0,
idr_pic_id: 0,
primary_pic_type: native::STD_VIDEO_H264_PICTURE_TYPE_IDR,
frame_num: 0,
PicOrderCnt: 0,
temporal_id: 0,
reserved1: [0; 3],
pRefLists: core::ptr::null(),
}
}
pub(crate) const fn build_idr_slice_header() -> native::StdVideoEncodeH264SliceHeader {
native::StdVideoEncodeH264SliceHeader {
flags: slice_header_flags(),
first_mb_in_slice: 0,
slice_type: native::STD_VIDEO_H264_SLICE_TYPE_I,
slice_alpha_c0_offset_div2: 0,
slice_beta_offset_div2: 0,
slice_qp_delta: 0,
reserved1: 0,
cabac_init_idc: native::StdVideoH264CabacInitIdc(0),
disable_deblocking_filter_idc: native::StdVideoH264DisableDeblockingFilterIdc(0),
pWeightTable: core::ptr::null(),
}
}
fn p_picture_info_flags() -> native::StdVideoEncodeH264PictureInfoFlags {
let mut flags = native::StdVideoEncodeH264PictureInfoFlags {
_bitfield_align_1: [],
_bitfield_1: native::__BindgenBitfieldUnit::new([0u8; 4]),
};
flags.set_is_reference(1);
flags
}
pub(crate) const fn build_p_slice_header() -> native::StdVideoEncodeH264SliceHeader {
native::StdVideoEncodeH264SliceHeader {
flags: slice_header_flags(),
first_mb_in_slice: 0,
slice_type: native::STD_VIDEO_H264_SLICE_TYPE_P,
slice_alpha_c0_offset_div2: 0,
slice_beta_offset_div2: 0,
slice_qp_delta: 0,
reserved1: 0,
cabac_init_idc: native::StdVideoH264CabacInitIdc(0),
disable_deblocking_filter_idc: native::StdVideoH264DisableDeblockingFilterIdc(0),
pWeightTable: core::ptr::null(),
}
}
pub(crate) const fn build_single_reference_list(
ref_slot: u8,
) -> native::StdVideoEncodeH264ReferenceListsInfo {
let mut list = build_empty_reference_lists();
list.num_ref_idx_l0_active_minus1 = 0;
list.RefPicList0[0] = ref_slot;
list
}
pub(crate) const fn build_reference_info(
frame_num: u32,
poc: i32,
is_idr: bool,
) -> native::StdVideoEncodeH264ReferenceInfo {
native::StdVideoEncodeH264ReferenceInfo {
flags: reference_info_flags(),
primary_pic_type: if is_idr {
native::STD_VIDEO_H264_PICTURE_TYPE_IDR
} else {
native::STD_VIDEO_H264_PICTURE_TYPE_P
},
FrameNum: frame_num,
PicOrderCnt: poc,
long_term_pic_num: 0,
long_term_frame_idx: 0,
temporal_id: 0,
}
}
const fn reference_info_flags() -> native::StdVideoEncodeH264ReferenceInfoFlags {
native::StdVideoEncodeH264ReferenceInfoFlags {
_bitfield_align_1: [],
_bitfield_1: native::__BindgenBitfieldUnit::new([0u8; 4]),
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct FrameStdStructs {
pub(crate) picture_info: native::StdVideoEncodeH264PictureInfo,
pub(crate) reference_lists: native::StdVideoEncodeH264ReferenceListsInfo,
pub(crate) slice_header: native::StdVideoEncodeH264SliceHeader,
pub(crate) setup_reference_info: native::StdVideoEncodeH264ReferenceInfo,
}
pub(crate) fn build_frame_structs(
frame_num: u32,
poc: i32,
idr_pic_id: u16,
is_idr: bool,
reference_slot: Option<u8>,
) -> FrameStdStructs {
let primary_pic_type = if is_idr {
native::STD_VIDEO_H264_PICTURE_TYPE_IDR
} else {
native::STD_VIDEO_H264_PICTURE_TYPE_P
};
let picture_info = native::StdVideoEncodeH264PictureInfo {
flags: if is_idr {
idr_picture_info_flags()
} else {
p_picture_info_flags()
},
seq_parameter_set_id: 0,
pic_parameter_set_id: 0,
idr_pic_id,
primary_pic_type,
frame_num,
PicOrderCnt: poc,
temporal_id: 0,
reserved1: [0; 3],
pRefLists: core::ptr::null(),
};
let reference_lists =
reference_slot.map_or_else(build_empty_reference_lists, build_single_reference_list);
let slice_header = if is_idr {
build_idr_slice_header()
} else {
build_p_slice_header()
};
let setup_reference_info = build_reference_info(frame_num, poc, is_idr);
FrameStdStructs {
picture_info,
reference_lists,
slice_header,
setup_reference_info,
}
}