#[derive(Debug, Default)]
pub struct BitWriter {
bytes: Vec<u8>,
bitpos: u32,
}
impl BitWriter {
pub fn new() -> Self {
Self::default()
}
fn put_bit(&mut self, v: bool) {
if self.bitpos == 0 {
self.bytes.push(0);
}
if v {
let mask = 0x80u8 >> self.bitpos;
*self.bytes.last_mut().unwrap() |= mask;
}
self.bitpos += 1;
if self.bitpos == 8 {
self.bitpos = 0;
}
}
pub fn put_u(&mut self, v: u32, bits: u32) {
for i in (0..bits).rev() {
self.put_bit((v >> i) & 1 == 1);
}
}
pub fn put_ue(&mut self, v: u32) {
let x = v + 1;
let bits = 32 - x.leading_zeros();
for _ in 0..(bits - 1) {
self.put_bit(false);
}
for i in (0..bits).rev() {
self.put_bit((x >> i) & 1 == 1);
}
}
pub fn put_se(&mut self, v: i32) {
let ue = if v < 0 { (-2 * v) as u32 } else { (2 * v) as u32 };
self.put_ue(ue);
}
pub fn valid_bits(&self) -> usize {
if self.bitpos == 0 {
self.bytes.len() * 8
} else {
(self.bytes.len() - 1) * 8 + self.bitpos as usize
}
}
pub fn finish(mut self) -> Vec<u8> {
self.put_bit(true); while self.bitpos != 0 {
self.put_bit(false);
}
let input = std::mem::take(&mut self.bytes);
let mut out = Vec::with_capacity(input.len() * 2);
let mut zeros = 0u32;
for &b in &input {
out.push(b);
if zeros >= 2 && (b as u32) <= 3 {
out.push(3);
zeros = 0;
} else {
zeros = if b == 0 { zeros + 1 } else { 0 };
}
}
out
}
}
pub fn make_sps(width_mbs: u32, height_mbs: u32, level_idc: u32, max_ref_frames: u32) -> Vec<u8> {
let mut w = BitWriter::new();
w.put_u(100, 8); w.put_u(0x00, 8); w.put_u(level_idc, 8);
w.put_ue(0); w.put_ue(1); w.put_ue(0); w.put_ue(0); w.put_bit(false); w.put_bit(false); w.put_ue(0); w.put_ue(0); w.put_ue(4); w.put_ue(max_ref_frames); w.put_bit(false); w.put_ue(width_mbs - 1); w.put_ue(height_mbs - 1); w.put_bit(true); w.put_bit(true); w.put_bit(false); w.put_bit(false); w.finish()
}
pub fn make_pps() -> Vec<u8> {
let mut w = BitWriter::new();
w.put_ue(0); w.put_ue(0); w.put_bit(false); w.put_bit(false); w.put_ue(0); w.put_ue(0); w.put_ue(0); w.put_bit(false); w.put_u(0, 2); w.put_se(0); w.put_se(0); w.put_se(0); w.put_bit(true); w.put_bit(false); w.put_bit(false); w.put_bit(false); w.put_bit(false); w.put_se(0); w.finish()
}
pub fn make_slice_hdr(is_idr: bool, frame_num: u32, poc_lsb: u32, idr_pic_id: u32) -> (Vec<u8>, u32) {
let mut w = BitWriter::new();
w.put_ue(0); w.put_ue(if is_idr { 7 } else { 5 }); w.put_ue(0); w.put_u(frame_num & 0xF, 4); if is_idr {
w.put_ue(idr_pic_id); }
w.put_u(poc_lsb & 0xFF, 8); if !is_idr {
w.put_bit(false); w.put_bit(false); }
if is_idr {
w.put_bit(false); w.put_bit(false); } else {
w.put_bit(false); }
w.put_se(0); w.put_ue(0); w.put_se(0); w.put_se(0);
let rbsp_bits = w.valid_bits() as u32;
let mut out = Vec::with_capacity(4 + 8);
out.extend_from_slice(&[0, 0, 1]);
out.push(if is_idr { 0x65 } else { 0x41 });
out.extend_from_slice(&w.bytes);
(out, 32 + rbsp_bits)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sps_matches_verified_bytes() {
let sps = make_sps(20, 15, 31, 1);
assert_eq!(sps, vec![0x64, 0x00, 0x1f, 0xac, 0xca, 0x81, 0x41, 0xf9]);
}
#[test]
fn pps_matches_verified_bytes() {
let pps = make_pps();
assert_eq!(pps, vec![0xce, 0x3c, 0x30]);
}
#[test]
fn slice_hdr_idr_layout() {
let (bytes, bits) = make_slice_hdr(true, 0, 0, 1);
assert_eq!(&bytes[0..4], &[0, 0, 1, 0x65]);
assert_eq!(bits, 32 + 30);
}
#[test]
fn slice_hdr_p_layout() {
let (bytes, bits) = make_slice_hdr(false, 1, 1, 0);
assert_eq!(&bytes[0..4], &[0, 0, 1, 0x41]);
assert_eq!(bits, 32 + 26);
}
#[test]
fn exp_golomb_lengths() {
let mut w = BitWriter::new();
w.put_ue(0);
w.put_ue(1);
w.put_ue(7);
w.put_se(-1);
w.put_se(3);
let bits = w.valid_bits();
assert_eq!(bits, 19);
}
#[test]
fn exp_golomb_bit_patterns() {
let mut w = BitWriter::new();
w.put_ue(0);
w.put_ue(1);
assert_eq!(&w.bytes, &[0xA0]);
let mut w = BitWriter::new();
w.put_ue(5); assert_eq!(w.valid_bits(), 5);
let mut w = BitWriter::new();
w.put_se(-2); assert_eq!(&w.bytes, &[0x28]);
}
}