#![allow(dead_code)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u8)]
pub(crate) enum NalUnitType {
IdrWRadl = 7,
IdrNLp = 8,
Opi = 12,
Dci = 13,
Vps = 14,
Sps = 15,
Pps = 16,
PrefixAps = 17,
Ph = 19,
Aud = 20,
PrefixSei = 23,
}
impl NalUnitType {
pub(crate) fn value(self) -> u8 {
self as u8
}
}
#[derive(Default)]
pub(crate) struct BitWriter {
bytes: Vec<u8>,
cur: u8,
nbits: u8,
}
impl BitWriter {
pub(crate) fn new() -> Self {
BitWriter::default()
}
pub(crate) fn is_byte_aligned(&self) -> bool {
self.nbits == 0
}
pub(crate) fn bit_len(&self) -> usize {
self.bytes.len() * 8 + self.nbits as usize
}
#[inline]
pub(crate) fn put_bit(&mut self, bit: u32) {
self.cur = (self.cur << 1) | (bit as u8 & 1);
self.nbits += 1;
if self.nbits == 8 {
self.bytes.push(self.cur);
self.cur = 0;
self.nbits = 0;
}
}
pub(crate) fn put_bits(&mut self, value: u32, n: u32) {
debug_assert!(n <= 32);
let mut i = n;
while i > 0 {
i -= 1;
self.put_bit((value >> i) & 1);
}
}
pub(crate) fn put_ue(&mut self, value: u32) {
let v = value as u64 + 1;
let len = 64 - v.leading_zeros(); for _ in 0..(len - 1) {
self.put_bit(0);
}
let mut i = len;
while i > 0 {
i -= 1;
self.put_bit(((v >> i) & 1) as u32);
}
}
pub(crate) fn put_se(&mut self, value: i32) {
let code = if value <= 0 {
(-(value as i64) as u64) * 2
} else {
(value as u64) * 2 - 1
};
self.put_ue(code as u32);
}
pub(crate) fn rbsp_trailing_bits(&mut self) {
self.put_bit(1);
while self.nbits != 0 {
self.put_bit(0);
}
}
pub(crate) fn into_bytes(self) -> Vec<u8> {
debug_assert!(self.nbits == 0, "BitWriter not byte-aligned at finish");
self.bytes
}
pub(crate) fn byte_align(&mut self) {
while self.nbits != 0 {
self.put_bit(0);
}
}
}
pub(crate) fn rbsp_to_ebsp(rbsp: &[u8]) -> Vec<u8> {
let mut out = Vec::with_capacity(rbsp.len() + rbsp.len() / 16 + 4);
let mut zeros = 0u32;
for &b in rbsp {
if zeros >= 2 && b <= 0x03 {
out.push(0x03);
zeros = 0;
}
if b == 0 {
zeros += 1;
} else {
zeros = 0;
}
out.push(b);
}
out
}
pub(crate) fn ebsp_to_rbsp(ebsp: &[u8]) -> Vec<u8> {
let mut out = Vec::with_capacity(ebsp.len());
let mut zeros = 0;
let mut i = 0;
while i < ebsp.len() {
let b = ebsp[i];
if zeros >= 2 && b == 0x03 && i + 1 < ebsp.len() && ebsp[i + 1] <= 0x03 {
zeros = 0; } else {
out.push(b);
zeros = if b == 0 { zeros + 1 } else { 0 };
}
i += 1;
}
out
}
pub(crate) fn write_nal(nut: NalUnitType, rbsp: &[u8], temporal_id_plus1: u8) -> Vec<u8> {
let mut hdr = BitWriter::new();
hdr.put_bit(0); hdr.put_bit(0); hdr.put_bits(0, 6); hdr.put_bits(nut.value() as u32, 5);
hdr.put_bits(temporal_id_plus1 as u32, 3);
let header = hdr.into_bytes();
let mut nal = Vec::with_capacity(2 + rbsp.len() + 8);
nal.extend_from_slice(&header);
nal.extend_from_slice(&rbsp_to_ebsp(rbsp));
nal
}
pub(crate) fn annexb(nal: &[u8]) -> Vec<u8> {
let mut out = Vec::with_capacity(nal.len() + 4);
out.extend_from_slice(&[0, 0, 0, 1]);
out.extend_from_slice(nal);
out
}
pub(crate) struct BitReader<'a> {
data: &'a [u8],
bitpos: usize,
}
impl<'a> BitReader<'a> {
pub(crate) fn new(data: &'a [u8]) -> Self {
BitReader { data, bitpos: 0 }
}
pub(crate) fn bit_pos(&self) -> usize {
self.bitpos
}
#[inline]
pub(crate) fn read_bit(&mut self) -> u32 {
let byte = self.bitpos >> 3;
let bit = if byte < self.data.len() {
((self.data[byte] >> (7 - (self.bitpos & 7))) & 1) as u32
} else {
0
};
self.bitpos += 1;
bit
}
pub(crate) fn read_bits(&mut self, n: u32) -> u32 {
let mut v = 0;
for _ in 0..n {
v = (v << 1) | self.read_bit();
}
v
}
pub(crate) fn read_ue(&mut self) -> u32 {
let mut zeros = 0;
while self.read_bit() == 0 && zeros < 32 {
zeros += 1;
}
if zeros == 0 {
return 0;
}
let suffix = self.read_bits(zeros);
(1 << zeros) - 1 + suffix
}
pub(crate) fn read_se(&mut self) -> i32 {
let code = self.read_ue();
let k = ((code + 1) >> 1) as i32;
if code & 1 == 1 { k } else { -k }
}
pub(crate) fn byte_align(&mut self) {
while self.bitpos & 7 != 0 {
self.bitpos += 1;
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn reader_inverts_writer() {
let mut w = BitWriter::new();
w.put_bits(0b10110, 5);
w.put_ue(0);
w.put_ue(42);
w.put_se(-7);
w.put_se(13);
w.put_bits(0xABCD, 16);
w.byte_align();
let bytes = w.into_bytes();
let mut r = BitReader::new(&bytes);
assert_eq!(r.read_bits(5), 0b10110);
assert_eq!(r.read_ue(), 0);
assert_eq!(r.read_ue(), 42);
assert_eq!(r.read_se(), -7);
assert_eq!(r.read_se(), 13);
assert_eq!(r.read_bits(16), 0xABCD);
}
#[test]
fn ue_known_values() {
let cases: &[(u32, &[u32])] = &[
(0, &[1]),
(1, &[0, 1, 0]),
(2, &[0, 1, 1]),
(3, &[0, 0, 1, 0, 0]),
(4, &[0, 0, 1, 0, 1]),
];
for (v, bits) in cases {
let mut w = BitWriter::new();
w.put_ue(*v);
w.byte_align();
let total: Vec<u32> = {
let bytes = w.bytes.clone();
let mut out = Vec::new();
for byte in bytes {
for i in (0..8).rev() {
out.push(((byte >> i) & 1) as u32);
}
}
out
};
assert_eq!(&total[..bits.len()], *bits, "ue({v})");
}
}
#[test]
fn se_maps_to_expected_codenum() {
let map: &[(i32, u32)] = &[(0, 0), (1, 1), (-1, 2), (2, 3), (-2, 4)];
for (val, code) in map {
let mut a = BitWriter::new();
a.put_se(*val);
a.byte_align();
let mut b = BitWriter::new();
b.put_ue(*code);
b.byte_align();
assert_eq!(a.bytes, b.bytes, "se({val}) should equal ue({code})");
}
}
#[test]
fn emulation_prevention_inserts_03() {
assert_eq!(rbsp_to_ebsp(&[0, 0, 0]), vec![0, 0, 3, 0]);
assert_eq!(rbsp_to_ebsp(&[0, 0, 1]), vec![0, 0, 3, 1]);
assert_eq!(rbsp_to_ebsp(&[0, 0, 2]), vec![0, 0, 3, 2]);
assert_eq!(rbsp_to_ebsp(&[0, 0, 3]), vec![0, 0, 3, 3]);
assert_eq!(rbsp_to_ebsp(&[0, 1, 2]), vec![0, 1, 2]);
assert_eq!(rbsp_to_ebsp(&[0, 0, 0, 0]), vec![0, 0, 3, 0, 0]);
}
#[test]
fn nal_header_two_bytes() {
let nal = write_nal(NalUnitType::Sps, &[0xFF], 1);
assert_eq!(nal.len(), 3);
assert_eq!(nal[0], 0x00);
assert_eq!(nal[1], 0x79);
}
#[test]
fn rbsp_trailing_bits_aligns() {
let mut w = BitWriter::new();
w.put_bits(0b101, 3);
w.rbsp_trailing_bits();
assert!(w.is_byte_aligned());
assert_eq!(w.into_bytes(), vec![0xB0]);
}
}