blob: 66f933bd20a4956cea11f2cb79b4509e3112dcf2 [file] [log] [blame]
use serde::{Deserialize, Serialize};
use crate::{
CodingUnitContext, CodingUnitKind, CodingUnitLocator, Frame, PartitionContext, PartitionIterator, PartitionLocator,
Superblock, SymbolContext, SymbolRange,
};
#[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub struct SuperblockLocator {
pub index: usize,
}
impl SuperblockLocator {
pub fn new(index: usize) -> Self {
Self { index }
}
pub fn try_resolve<'a>(&self, frame: &'a Frame) -> Option<SuperblockContext<'a>> {
frame.superblocks.get(self.index).map(|superblock| SuperblockContext {
superblock,
frame,
locator: *self,
})
}
pub fn resolve<'a>(&self, frame: &'a Frame) -> SuperblockContext<'a> {
self.try_resolve(frame).unwrap()
}
}
#[derive(Copy, Clone, Debug)]
pub struct SuperblockContext<'a> {
pub superblock: &'a Superblock,
pub frame: &'a Frame,
pub locator: SuperblockLocator,
}
impl<'a> SuperblockContext<'a> {
pub fn iter_partitions(&self, kind: CodingUnitKind) -> impl Iterator<Item = PartitionContext<'a>> {
let root = match kind {
CodingUnitKind::Shared | CodingUnitKind::LumaOnly => self.superblock.luma_partition_tree.as_ref().unwrap(),
CodingUnitKind::ChromaOnly => self.superblock.chroma_partition_tree.as_ref().unwrap(),
};
let root_locator = PartitionLocator::new(Vec::new(), kind, self.locator);
let root_context = PartitionContext {
partition: root,
superblock_context: *self,
locator: root_locator,
};
PartitionIterator {
stack: vec![(root_context, 0)],
max_depth: None,
}
}
pub fn root_partition(&self, kind: CodingUnitKind) -> Option<PartitionContext<'a>> {
self.iter_partitions(kind).next()
}
// Consuming self simplifies lifetime management in caller.
pub fn iter_coding_units(self, kind: CodingUnitKind) -> impl Iterator<Item = CodingUnitContext<'a>> {
let coding_units = match kind {
CodingUnitKind::Shared | CodingUnitKind::LumaOnly => self.superblock.coding_units_shared.iter(),
CodingUnitKind::ChromaOnly => self.superblock.coding_units_chroma.iter(),
};
coding_units
.enumerate()
.map(move |(index, coding_unit)| CodingUnitContext {
coding_unit,
superblock_context: self,
locator: CodingUnitLocator::new(self.locator, kind, index),
})
}
pub fn iter_symbols(&self, range: Option<SymbolRange>) -> impl Iterator<Item = SymbolContext<'a>> {
let range = range.unwrap_or(SymbolRange {
start: 0,
end: self.superblock.symbols.len() as u32,
});
self.superblock.symbols[range.start as usize..range.end as usize]
.iter()
.map(|sym| SymbolContext {
symbol: sym,
info: self.frame.symbol_info.get(&sym.info_id),
superblock: self.superblock,
})
}
}