use crate::av2::entropy::ByteWriter;
use crate::av2::headers::{Config, frame_header, frame_header_body, obu};
use crate::err::EncodeError;
#[inline]
fn write_screen_content_and_intrabc(b: &mut ByteWriter, cfg: &Config, allow_intrabc: bool) {
if cfg.lossless {
b.write_bit(1); b.write_bit(0); }
b.write_bit(allow_intrabc as u32);
if allow_intrabc {
b.write_bit(1); b.write_bit(1); }
}
pub(crate) fn tile_payload_of<'a>(
still_frame_obu: &'a [u8],
cfg: &Config,
sw: u32,
sh: u32,
tiles: (usize, usize, usize),
) -> &'a [u8] {
let mut i = 0;
loop {
let b = still_frame_obu[i];
i += 1;
if b & 0x80 == 0 {
break;
}
}
let payload = &still_frame_obu[i + 1..];
let hdr_len = frame_header(cfg, sw, sh, tiles).len();
&payload[hdr_len..]
}
pub(crate) fn video_key_frame(
cfg: &Config,
sw: u32,
sh: u32,
tile: &[u8],
order_hint: u64,
tiles: (usize, usize, usize),
) -> Result<Vec<u8>, EncodeError> {
let has_chroma = cfg.layout.has_chroma();
let mut b = ByteWriter::new();
b.write_bit(1); b.write_uvlc(0); b.write_uvlc(0); b.write_bit(1); b.write_bit(0); b.write_bits((order_hint & 0x7f) as u32, 7); write_screen_content_and_intrabc(&mut b, cfg, cfg.allow_intrabc);
frame_header_body(&mut b, cfg, sw, sh, tiles, has_chroma, true, false);
b.align_with_zero();
let mut payload = b.into_bytes();
payload.extend_from_slice(tile);
Ok(obu(4, &payload))
}
pub(crate) struct VideoInterFrameSpec<'a> {
pub(crate) sw: u32,
pub(crate) sh: u32,
pub(crate) tile: &'a [u8],
pub(crate) order_hint: u64,
pub(crate) tiles: (usize, usize, usize),
pub(crate) reference_slot: usize,
pub(crate) second_reference_slot: Option<usize>,
pub(crate) refresh_slot: usize,
}
pub(crate) fn video_inter_frame(
cfg: &Config,
spec: VideoInterFrameSpec<'_>,
) -> Result<Vec<u8>, EncodeError> {
let VideoInterFrameSpec {
sw,
sh,
tile,
order_hint,
tiles,
reference_slot,
second_reference_slot,
refresh_slot,
} = spec;
let has_chroma = cfg.layout.has_chroma();
let mut b = ByteWriter::new();
b.write_bit(1); b.write_uvlc(0); b.write_uvlc(0); b.write_bit(1); b.write_bit(1); b.write_bit(0); b.write_bits((order_hint & 0x7f) as u32, 7); b.write_bit(1); b.write_bit(0); b.write_bits(7, 3); b.write_bits(1u32 << refresh_slot, 8);
b.write_bit(1); let num_total_refs = 1 + u32::from(second_reference_slot.is_some());
b.write_bits(num_total_refs, 3);
b.write_bits(reference_slot as u32, 3); if let Some(second) = second_reference_slot {
b.write_bits(second as u32, 3); }
write_screen_content_and_intrabc(&mut b, cfg, false);
b.write_bit(1); b.write_bit(0); b.write_bits(0, 2); frame_header_body(&mut b, cfg, sw, sh, tiles, has_chroma, true, true);
b.align_with_zero();
let mut payload = b.into_bytes();
payload.extend_from_slice(tile);
Ok(obu(7, &payload))
}