blob: 310ab6fdf1c07d92e63423d840d8c744fb2c3563 [file] [log] [blame]
use serde::{Deserialize, Serialize};
use crate::{CodingUnitContext, CodingUnitLocator, Frame, Plane, ProtoEnumMapping, TransformUnit};
// TX blocks larger than 32x32 have all coefficients other than the top-left 32x32 set to 0.
pub const MAX_COEFFS_SIZE: usize = 32;
impl TransformUnit {
pub fn primary_tx_type_or_skip(&self, frame: &Frame) -> String {
let tx_type = self.tx_type;
// Only lower 4-bits used for primary transform. Upper bits are IST.
let tx_type = tx_type & 0xF;
if self.skip == 1 {
"SKIP".to_owned()
} else {
frame
.enum_lookup(ProtoEnumMapping::TransformType, tx_type)
.unwrap_or(format!("UNKNOWN ({tx_type})"))
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub struct TransformUnitLocator {
pub coding_unit: CodingUnitLocator,
pub plane: Plane,
/// Index of this tranform unit with its parent.
pub index: usize,
}
// Note: Converting plane to a usize does not automatically get the correct index into a coding unit's transform planes.
// e.g., in SDP mode, the chroma coding units will have two planes, but with plane IDs (1, 2), not (0, 1).
impl TransformUnitLocator {
pub fn new(coding_unit: CodingUnitLocator, plane: Plane, index: usize) -> Self {
Self {
coding_unit,
plane,
index,
}
}
pub fn try_resolve<'a>(&self, frame: &'a Frame) -> Option<TransformUnitContext<'a>> {
let coding_unit_context = self.coding_unit.try_resolve(frame)?;
let plane_index = coding_unit_context.coding_unit.plane_index(self.plane).ok()?;
let transform_unit = coding_unit_context
.coding_unit
.transform_planes
.get(plane_index)?
.transform_units
.get(self.index)?;
Some(TransformUnitContext {
transform_unit,
coding_unit_context,
locator: *self,
})
}
pub fn resolve<'a>(&self, frame: &'a Frame) -> TransformUnitContext<'a> {
self.try_resolve(frame).unwrap()
}
}
#[derive(Copy, Clone)]
pub struct TransformUnitContext<'a> {
pub transform_unit: &'a TransformUnit,
pub coding_unit_context: CodingUnitContext<'a>,
pub locator: TransformUnitLocator,
}