use crate::av2::cfl::CflChoice;
use crate::av2::coder::Coeff;
thread_local! {
static TILE_SUBENCODE: std::cell::Cell<bool> = const { std::cell::Cell::new(false) };
}
pub(crate) struct TileSubencodeGuard(bool);
impl TileSubencodeGuard {
#[inline]
pub(crate) fn enter() -> Self {
let prev = TILE_SUBENCODE.with(|c| c.replace(true));
TileSubencodeGuard(prev)
}
}
impl Drop for TileSubencodeGuard {
#[inline]
fn drop(&mut self) {
let prev = self.0;
TILE_SUBENCODE.set(prev);
}
}
#[inline]
pub(crate) fn in_tile_subencode() -> bool {
TILE_SUBENCODE.with(|c| c.get())
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum WholePart {
Split,
Vert4,
Horz4,
}
#[derive(Clone)]
pub(crate) enum WholeChroma {
Cfl(CflChoice),
Mode(usize),
}
#[derive(Clone)]
pub(crate) struct Whole64Decision {
pub part: WholePart,
pub tus: [Vec<Coeff>; 4],
pub mode_idx: usize,
pub angle_delta: i8,
pub chroma: WholeChroma,
pub recon_y: Vec<f32>,
pub recon_u: Vec<f32>,
pub recon_v: Vec<f32>,
}
#[derive(Clone)]
pub(crate) struct LeafDecision {
pub bw_mi: usize,
pub bh_mi: usize,
pub tu: Vec<Coeff>,
pub mode_idx: usize,
pub recon_y: Vec<f32>,
}
#[derive(Clone)]
pub(crate) struct Leaf400 {
pub bw_mi: usize,
pub bh_mi: usize,
pub tus: Vec<Vec<Coeff>>,
pub mode_idx: usize,
pub tx_idx: usize,
pub recon_y: Vec<f32>,
}
#[derive(Clone)]
pub(crate) enum Sb400 {
Walk(Vec<Leaf400>),
Fallback,
}
#[derive(Clone)]
pub(crate) struct Leaf420 {
pub bw_mi: usize,
pub bh_mi: usize,
pub tus: Vec<Vec<Coeff>>,
pub mode_idx: usize,
pub tx_idx: usize,
pub recon_y: Vec<f32>,
pub chroma: Option<CflChoice>,
}
#[derive(Clone)]
pub(crate) enum Sb420 {
Walk(Vec<Leaf420>),
Fallback,
}
pub(crate) enum LeafWalk<'a> {
Off,
Capture(&'a mut Vec<LeafDecision>),
Replay(&'a LeafDecision),
}
#[derive(Clone)]
pub(crate) enum SbDecision {
Whole64(Box<Whole64Decision>),
Walk(Vec<LeafDecision>),
Fallback,
}
#[derive(Clone, Default)]
pub(crate) struct DecisionRecord {
entries: Vec<SbDecision>,
parts: Vec<crate::av2::leaf::LumaPartitionDecision>,
mhccp: Vec<Option<CflChoice>>,
luma420: Vec<Luma420>,
chroma422_whole: Vec<Option<CflChoice>>,
luma400: Vec<Sb400>,
luma420_walk: Vec<Sb420>,
}
impl DecisionRecord {
pub(crate) fn new() -> Self {
Self {
entries: Vec::new(),
parts: Vec::new(),
mhccp: Vec::new(),
luma420: Vec::new(),
chroma422_whole: Vec::new(),
luma400: Vec::new(),
luma420_walk: Vec::new(),
}
}
pub(crate) fn push(&mut self, d: SbDecision) {
self.entries.push(d);
}
pub(crate) fn push_part(&mut self, p: crate::av2::leaf::LumaPartitionDecision) {
self.parts.push(p);
}
pub(crate) fn push_mhccp(&mut self, m: Option<CflChoice>) {
self.mhccp.push(m);
}
pub(crate) fn len(&self) -> usize {
self.entries.len()
}
#[allow(dead_code)]
pub(crate) fn append(&mut self, mut other: DecisionRecord) {
self.entries.append(&mut other.entries);
self.parts.append(&mut other.parts);
self.mhccp.append(&mut other.mhccp);
self.luma420.append(&mut other.luma420);
self.chroma422_whole.append(&mut other.chroma422_whole);
self.luma400.append(&mut other.luma400);
self.luma420_walk.append(&mut other.luma420_walk);
}
pub(crate) fn push_sb400(&mut self, s: Sb400) {
self.luma400.push(s);
}
pub(crate) fn push_sb420(&mut self, s: Sb420) {
self.luma420_walk.push(s);
}
}
pub(crate) struct DecisionCursor<'a> {
rec: &'a DecisionRecord,
at: usize,
part_at: usize,
mhccp_at: usize,
luma420_at: usize,
chroma422_whole_at: usize,
luma400_at: usize,
luma420_walk_at: usize,
}
impl<'a> DecisionCursor<'a> {
pub(crate) fn new(rec: &'a DecisionRecord) -> Self {
Self {
rec,
at: 0,
part_at: 0,
mhccp_at: 0,
luma420_at: 0,
chroma422_whole_at: 0,
luma400_at: 0,
luma420_walk_at: 0,
}
}
pub(crate) fn next_sb400(&mut self) -> Option<&'a Sb400> {
let s = self.rec.luma400.get(self.luma400_at);
if s.is_some() {
self.luma400_at += 1;
}
s
}
pub(crate) fn next_sb420(&mut self) -> Option<&'a Sb420> {
let s = self.rec.luma420_walk.get(self.luma420_walk_at);
if s.is_some() {
self.luma420_walk_at += 1;
}
s
}
pub(crate) fn next_part(&mut self) -> Option<crate::av2::leaf::LumaPartitionDecision> {
let p = self.rec.parts.get(self.part_at).copied();
if p.is_some() {
self.part_at += 1;
}
p
}
pub(crate) fn next_mhccp(&mut self) -> Option<Option<CflChoice>> {
let m = self.rec.mhccp.get(self.mhccp_at).cloned();
if m.is_some() {
self.mhccp_at += 1;
}
m
}
pub(crate) fn next(&mut self) -> &'a SbDecision {
static FALLBACK: SbDecision = SbDecision::Fallback;
let d = self.rec.entries.get(self.at).unwrap_or(&FALLBACK);
self.at += 1;
d
}
}
#[derive(Clone)]
pub(crate) struct Luma420 {
pub tus: [Vec<Coeff>; 4],
pub mode_idx: usize,
pub adelta: i8,
pub recon_y: Vec<f32>,
}
impl DecisionRecord {
pub(crate) fn push_luma420(&mut self, l: Luma420) {
self.luma420.push(l);
}
pub(crate) fn push_chroma422_whole(&mut self, c: Option<CflChoice>) {
self.chroma422_whole.push(c);
}
}
impl<'a> DecisionCursor<'a> {
pub(crate) fn next_luma420(&mut self) -> Option<Luma420> {
let l = self.rec.luma420.get(self.luma420_at).cloned();
if l.is_some() {
self.luma420_at += 1;
}
l
}
pub(crate) fn next_chroma422_whole(&mut self) -> Option<Option<CflChoice>> {
let c = self
.rec
.chroma422_whole
.get(self.chroma422_whole_at)
.cloned();
if c.is_some() {
self.chroma422_whole_at += 1;
}
c
}
}
pub(crate) enum DecideMode<'a> {
Off,
Capture(&'a mut DecisionRecord),
Replay(DecisionCursor<'a>),
}