use super::bitwriter::BitWriter;
use super::entropy::{next_k_ac_level, next_k_ac_run, next_k_dc};
pub fn encode_unsigned_codeword(writer: &mut BitWriter, value: u32, k: u32) {
let quotient = value >> k;
let remainder = value & ((1u32 << k) - 1);
for _ in 0..quotient {
writer.write_bit(true);
}
writer.write_bit(false);
if k > 0 {
writer.write_bits(remainder, k as u8);
}
}
pub fn encode_signed_codeword(writer: &mut BitWriter, value: i32, k: u32) {
let magnitude = value.unsigned_abs();
encode_unsigned_codeword(writer, magnitude, k);
if magnitude != 0 {
writer.write_bit(value < 0);
}
}
pub fn encode_block(writer: &mut BitWriter, quantized: &[i16; 64], prev_dc: i16) -> i16 {
let dc = quantized[0];
let dc_delta = i32::from(dc) - i32::from(prev_dc);
let k_dc = next_k_dc(prev_dc.unsigned_abs() as u32);
encode_signed_codeword(writer, dc_delta, k_dc);
let mut k_run = 3u32;
let mut k_level = 1u32;
let mut pos = 1usize;
let last_nonzero = {
let mut last = 0usize;
for i in 1..64 {
if quantized[i] != 0 {
last = i;
}
}
last
};
while pos < 64 {
let mut run = 0u32;
while (pos + run as usize) < 64 && quantized[pos + run as usize] == 0 {
run += 1;
}
if pos + run as usize >= 64 || pos > last_nonzero {
let remaining = (64 - pos) as u32;
encode_unsigned_codeword(writer, remaining, k_run);
break;
}
encode_unsigned_codeword(writer, run, k_run);
pos += run as usize;
let level = quantized[pos];
let magnitude = level.unsigned_abs() as u32;
let mag_minus1 = magnitude - 1;
encode_unsigned_codeword(writer, mag_minus1, k_level);
writer.write_bit(level < 0);
k_run = next_k_ac_run(run);
k_level = next_k_ac_level(magnitude);
pos += 1;
}
dc
}
#[cfg(test)]
mod tests {
use super::*;
use crate::prores::bitreader::BitReader;
use crate::prores::entropy::{decode_block, decode_signed_codeword, decode_unsigned_codeword};
#[test]
fn encode_decode_unsigned_roundtrip() {
let cases: &[(u32, u32)] = &[
(0, 0),
(0, 1),
(0, 3),
(1, 0),
(1, 1),
(1, 3),
(1, 5),
(2, 0),
(2, 3),
(2, 7),
(2, 15),
(3, 0),
(3, 7),
(3, 15),
(3, 63),
(4, 0),
(4, 15),
(4, 31),
(4, 127),
(5, 0),
(5, 31),
(5, 255),
(7, 127),
(7, 1023),
];
for &(k, val) in cases {
let mut w = BitWriter::new();
encode_unsigned_codeword(&mut w, val, k);
let bytes = w.into_bytes();
let mut r = BitReader::new(&bytes);
let decoded = decode_unsigned_codeword(&mut r, k).expect("decode");
assert_eq!(decoded, val, "k={k}, val={val}");
}
}
#[test]
fn encode_decode_signed_roundtrip() {
let cases: &[(u32, i32)] = &[
(0, 0),
(0, 1),
(0, -1),
(0, 3),
(0, -3),
(3, 0),
(3, 7),
(3, -7),
(5, -100),
(5, 100),
(7, 500),
(7, -500),
(7, 1023),
(7, -1023),
];
for &(k, val) in cases {
let mut w = BitWriter::new();
encode_signed_codeword(&mut w, val, k);
let bytes = w.into_bytes();
let mut r = BitReader::new(&bytes);
let decoded = decode_signed_codeword(&mut r, k).expect("decode");
assert_eq!(decoded, val, "k={k}, val={val}");
}
}
#[test]
fn encode_block_decode_block_dc_only() {
let mut quantized = [0i16; 64];
quantized[0] = 12;
let mut w = BitWriter::new();
encode_block(&mut w, &quantized, 0);
let bytes = w.into_bytes();
let mut r = BitReader::new(&bytes);
let (decoded_coeffs, new_dc) = decode_block(&mut r, 0).expect("decode");
assert_eq!(new_dc, 12, "DC should be 12");
assert_eq!(decoded_coeffs[0], 12);
for i in 1..64 {
assert_eq!(decoded_coeffs[i], 0, "AC[{i}] should be 0");
}
}
#[test]
fn encode_block_decode_block_ac_roundtrip() {
let mut quantized = [0i16; 64];
quantized[0] = 100; quantized[1] = 5; quantized[5] = -3; quantized[20] = 7; quantized[63] = -1;
let mut w = BitWriter::new();
let new_dc = encode_block(&mut w, &quantized, 50);
assert_eq!(new_dc, 100, "encode_block returns absolute DC");
let bytes = w.into_bytes();
let mut r = BitReader::new(&bytes);
let (decoded_coeffs, decoded_dc) = decode_block(&mut r, 50).expect("decode");
assert_eq!(decoded_dc, 100);
assert_eq!(decoded_coeffs[0], 100);
assert_eq!(decoded_coeffs[1], 5);
assert_eq!(decoded_coeffs[5], -3);
assert_eq!(decoded_coeffs[20], 7);
assert_eq!(decoded_coeffs[63], -1);
assert_eq!(decoded_coeffs[2], 0);
assert_eq!(decoded_coeffs[4], 0);
}
#[test]
fn encode_block_all_zeros() {
let quantized = [0i16; 64];
let mut w = BitWriter::new();
encode_block(&mut w, &quantized, 0);
let bytes = w.into_bytes();
let mut r = BitReader::new(&bytes);
let (decoded_coeffs, decoded_dc) = decode_block(&mut r, 0).expect("decode");
assert_eq!(decoded_dc, 0);
assert!(decoded_coeffs.iter().all(|&v| v == 0));
}
}