#![forbid(unsafe_code)]
use super::bitstream::{RbspWriter, push_rbsp_with_emulation_prevention};
const PROFILE_IDC_MAIN: u8 = 1;
const NAL_TYPE_VPS: u8 = 32;
const NAL_TYPE_SPS: u8 = 33;
const NAL_TYPE_PPS: u8 = 34;
const CB_MIN_LOG2: u32 = 3;
const CB_DIFF_LOG2: u32 = 2; const TB_MIN_LOG2: u32 = 2;
const TB_DIFF_LOG2: u32 = 3; const TRANSFORM_HIERARCHY_DEPTH: u32 = 3;
fn write_profile_tier_level_main(w: &mut RbspWriter, general_tier_flag: u8, general_level_idc: u8) {
w.write_bits(0, 2); w.write_bit(general_tier_flag);
w.write_bits(u32::from(PROFILE_IDC_MAIN), 5); let compat = 1u32 << (31 - u32::from(PROFILE_IDC_MAIN)); w.write_bits(compat, 32);
w.write_bit(1); w.write_bit(0); w.write_bit(0); w.write_bit(1); w.write_zero_bits(43); w.write_bit(0); w.write_u8(general_level_idc);
}
fn write_vps(w: &mut RbspWriter, general_tier_flag: u8, general_level_idc: u8) {
w.write_bits(0, 4); w.write_bit(1); w.write_bit(1); w.write_bits(0, 6); w.write_bits(0, 3); w.write_bit(1); w.write_bits(0xffff, 16); write_profile_tier_level_main(w, general_tier_flag, general_level_idc);
w.write_bit(0); w.write_ue(0); w.write_ue(0); w.write_ue(0); w.write_bits(0, 6); w.write_ue(0); w.write_bit(0); w.write_bit(0); w.rbsp_trailing_bits();
}
fn write_sps(
w: &mut RbspWriter,
width: u32,
height: u32,
general_tier_flag: u8,
general_level_idc: u8,
) {
w.write_bits(0, 4); w.write_bits(0, 3); w.write_bit(1); write_profile_tier_level_main(w, general_tier_flag, general_level_idc);
w.write_ue(0); w.write_ue(1); w.write_ue(width); w.write_ue(height); w.write_bit(0); w.write_ue(0); w.write_ue(0); w.write_ue(0); w.write_bit(0); w.write_ue(0); w.write_ue(0); w.write_ue(0); w.write_ue(CB_MIN_LOG2 - 3); w.write_ue(CB_DIFF_LOG2); w.write_ue(TB_MIN_LOG2 - 2); w.write_ue(TB_DIFF_LOG2); w.write_ue(TRANSFORM_HIERARCHY_DEPTH); w.write_ue(TRANSFORM_HIERARCHY_DEPTH); w.write_bit(0); w.write_bit(0); w.write_bit(0); w.write_bit(0); w.write_ue(0); w.write_bit(0); w.write_bit(0); w.write_bit(0); w.write_bit(0); w.write_bit(0); w.rbsp_trailing_bits();
}
fn write_pps(w: &mut RbspWriter) {
w.write_ue(0); w.write_ue(0); w.write_bit(0); w.write_bit(0); w.write_bits(0, 3); w.write_bit(0); w.write_bit(0); w.write_ue(0); w.write_ue(0); w.write_se(0); w.write_bit(0); w.write_bit(0); w.write_bit(0); w.write_se(0); w.write_se(0); w.write_bit(0); w.write_bit(0); w.write_bit(0); w.write_bit(0); w.write_bit(0); w.write_bit(0); w.write_bit(1); w.write_bit(0); w.write_bit(0); w.write_bit(0); w.write_ue(0); w.write_bit(0); w.write_bit(0); w.rbsp_trailing_bits();
}
fn annex_b_nal_hevc(nal_unit_type: u8, rbsp: &[u8]) -> Vec<u8> {
let mut out = Vec::with_capacity(rbsp.len() + rbsp.len() / 2 + 6);
out.extend_from_slice(&[0, 0, 0, 1, nal_unit_type << 1, 0x01]);
push_rbsp_with_emulation_prevention(&mut out, rbsp);
out
}
pub(super) fn build_hevc_headers(
width: u32,
height: u32,
general_tier_flag: u8,
general_level_idc: u8,
) -> Vec<u8> {
let mut vps_w = RbspWriter::new();
write_vps(&mut vps_w, general_tier_flag, general_level_idc);
let vps_rbsp = vps_w.finish();
let mut sps_w = RbspWriter::new();
write_sps(
&mut sps_w,
width,
height,
general_tier_flag,
general_level_idc,
);
let sps_rbsp = sps_w.finish();
let mut pps_w = RbspWriter::new();
write_pps(&mut pps_w);
let pps_rbsp = pps_w.finish();
let mut out = annex_b_nal_hevc(NAL_TYPE_VPS, &vps_rbsp);
out.extend(annex_b_nal_hevc(NAL_TYPE_SPS, &sps_rbsp));
out.extend(annex_b_nal_hevc(NAL_TYPE_PPS, &pps_rbsp));
out
}