use crate::include::common::bitdepth::BPC;
use crate::include::common::bitdepth::BitDepth;
use crate::include::common::bitdepth::BitDepth8;
use crate::include::common::bitdepth::BitDepth16;
use crate::include::dav1d::common::Rav1dDataProps;
use crate::include::dav1d::data::Rav1dData;
use crate::include::dav1d::dav1d::Rav1dDecodeFrameType;
use crate::include::dav1d::dav1d::Rav1dEventFlags;
use crate::include::dav1d::dav1d::Rav1dInloopFilterType;
use crate::include::dav1d::headers::DRav1d;
use crate::include::dav1d::headers::Dav1dFrameHeader;
use crate::include::dav1d::headers::Dav1dSequenceHeader;
use crate::include::dav1d::headers::Rav1dContentLightLevel;
use crate::include::dav1d::headers::Rav1dFrameHeader;
use crate::include::dav1d::headers::Rav1dITUTT35;
use crate::include::dav1d::headers::Rav1dMasteringDisplay;
use crate::include::dav1d::headers::Rav1dSequenceHeader;
use crate::include::dav1d::headers::Rav1dWarpedMotionParams;
use crate::include::dav1d::picture::Rav1dPicAllocator;
use crate::include::dav1d::picture::Rav1dPicture;
use crate::src::align::Align16;
use crate::src::align::Align64;
use crate::src::align::AlignedVec64;
use crate::src::align::ArrayDefault;
use crate::src::cdef::Rav1dCdefDSPContext;
use crate::src::cdf::CdfContext;
use crate::src::cdf::CdfThreadContext;
use crate::src::cpu::CpuFlags;
use crate::src::cpu::rav1d_get_cpu_flags;
use crate::src::disjoint_mut::DisjointImmutGuard;
use crate::src::disjoint_mut::DisjointMut;
use crate::src::disjoint_mut::DisjointMutArcSlice;
use crate::src::disjoint_mut::DisjointMutGuard;
use crate::src::env::BlockContext;
use crate::src::error::Rav1dError;
use crate::src::filmgrain::GRAIN_HEIGHT;
use crate::src::filmgrain::GRAIN_WIDTH;
use crate::src::filmgrain::Rav1dFilmGrainDSPContext;
use crate::src::ipred::Rav1dIntraPredDSPContext;
use crate::src::itx::Rav1dInvTxfmDSPContext;
use crate::src::levels::Av1Block;
use crate::src::levels::Filter2d;
use crate::src::levels::SegmentId;
use crate::src::levels::TxfmType;
use crate::src::levels::WHT_WHT;
use crate::src::lf_mask::Av1Filter;
use crate::src::lf_mask::Av1FilterLUT;
use crate::src::lf_mask::Av1Restoration;
use crate::src::lf_mask::Av1RestorationUnit;
use crate::src::log::Rav1dLogger;
use crate::src::loopfilter::Rav1dLoopFilterDSPContext;
use crate::src::looprestoration::Rav1dLoopRestorationDSPContext;
use crate::src::lr_apply::LrRestorePlanes;
use crate::src::mc::Rav1dMCDSPContext;
use crate::src::mem::MemPool;
use crate::src::msac::MsacContext;
use crate::src::msac::Rav1dMsacDSPContext;
use crate::src::pal::Rav1dPalDSPContext;
use crate::src::picture::PictureFlags;
use crate::src::picture::Rav1dThreadPicture;
use crate::src::recon::BackupIpredEdgeFn;
use crate::src::recon::CopyPalBlockFn;
use crate::src::recon::FilterSbrowFn;
use crate::src::recon::ReadCoefBlocksFn;
use crate::src::recon::ReadPalPlaneFn;
use crate::src::recon::ReadPalUVFn;
use crate::src::recon::ReconBInterFn;
use crate::src::recon::ReconBIntraFn;
use crate::src::recon::rav1d_backup_ipred_edge;
use crate::src::recon::rav1d_copy_pal_block_uv;
use crate::src::recon::rav1d_copy_pal_block_y;
use crate::src::recon::rav1d_filter_sbrow;
use crate::src::recon::rav1d_filter_sbrow_cdef;
use crate::src::recon::rav1d_filter_sbrow_deblock_cols;
use crate::src::recon::rav1d_filter_sbrow_deblock_rows;
use crate::src::recon::rav1d_filter_sbrow_lr;
use crate::src::recon::rav1d_filter_sbrow_resize;
use crate::src::recon::rav1d_read_coef_blocks;
use crate::src::recon::rav1d_read_pal_plane;
use crate::src::recon::rav1d_read_pal_uv;
use crate::src::recon::rav1d_recon_b_inter;
use crate::src::recon::rav1d_recon_b_intra;
use crate::src::refmvs::Rav1dRefmvsDSPContext;
use crate::src::refmvs::RefMvsFrame;
use crate::src::refmvs::RefMvsTemporalBlock;
use crate::src::refmvs::RefmvsTile;
use crate::src::relaxed_atomic::RelaxedAtomic;
use crate::src::thread_task::Rav1dTaskIndex;
use crate::src::thread_task::Rav1dTasks;
use atomig::Atom;
use atomig::Atomic;
#[allow(non_camel_case_types)]
type ptrdiff_t = isize;
use parking_lot::Condvar;
use parking_lot::Mutex;
use parking_lot::RwLock;
use parking_lot::RwLockReadGuard;
use std::ffi::c_int;
use std::ffi::c_uint;
use std::mem;
use std::ops::Deref;
use std::ops::Range;
use std::sync::Arc;
use std::sync::OnceLock;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::AtomicI32;
use std::sync::atomic::AtomicU8;
use std::sync::atomic::AtomicU32;
use std::sync::atomic::Ordering;
use strum::FromRepr;
use zerocopy::FromBytes;
use zerocopy::FromZeros;
use zerocopy::Immutable;
use zerocopy::IntoBytes;
use zerocopy::KnownLayout;
#[derive(Default)]
pub struct Rav1dDSPContext {
pub pal: Rav1dPalDSPContext,
pub refmvs: Rav1dRefmvsDSPContext,
pub msac: Rav1dMsacDSPContext,
}
impl Rav1dDSPContext {
pub const fn default() -> Self {
Self {
pal: Rav1dPalDSPContext::default(),
refmvs: Rav1dRefmvsDSPContext::default(),
msac: Rav1dMsacDSPContext::default(),
}
}
pub const fn new(flags: CpuFlags) -> Self {
Self {
pal: Rav1dPalDSPContext::new(flags),
refmvs: Rav1dRefmvsDSPContext::new(flags),
msac: Rav1dMsacDSPContext::new(flags),
}
}
pub fn get() -> &'static Self {
static DSP: OnceLock<Rav1dDSPContext> = OnceLock::new();
DSP.get_or_init(|| {
let flags = rav1d_get_cpu_flags();
Self::new(flags)
})
}
}
impl Default for &'static Rav1dDSPContext {
fn default() -> Self {
Rav1dDSPContext::get()
}
}
pub(crate) struct Rav1dBitDepthDSPContext {
pub fg: Rav1dFilmGrainDSPContext,
pub ipred: Rav1dIntraPredDSPContext,
pub mc: Rav1dMCDSPContext,
pub itx: Rav1dInvTxfmDSPContext,
pub lf: Rav1dLoopFilterDSPContext,
pub cdef: Rav1dCdefDSPContext,
pub lr: Rav1dLoopRestorationDSPContext,
}
impl Rav1dBitDepthDSPContext {
pub const fn _default<BD: BitDepth>() -> Self {
Self {
fg: Rav1dFilmGrainDSPContext::default::<BD>(),
ipred: Rav1dIntraPredDSPContext::default::<BD>(),
mc: Rav1dMCDSPContext::default::<BD>(),
itx: Rav1dInvTxfmDSPContext::default::<BD>(),
lf: Rav1dLoopFilterDSPContext::default::<BD>(),
cdef: Rav1dCdefDSPContext::default::<BD>(),
lr: Rav1dLoopRestorationDSPContext::default::<BD>(),
}
}
pub const fn new<BD: BitDepth>(flags: CpuFlags, bpc: u8) -> Self {
Self {
fg: Rav1dFilmGrainDSPContext::new::<BD>(flags),
ipred: Rav1dIntraPredDSPContext::new::<BD>(flags),
mc: Rav1dMCDSPContext::new::<BD>(flags),
itx: Rav1dInvTxfmDSPContext::new::<BD>(flags, bpc),
lf: Rav1dLoopFilterDSPContext::new::<BD>(flags),
cdef: Rav1dCdefDSPContext::new::<BD>(flags),
lr: Rav1dLoopRestorationDSPContext::new::<BD>(flags, bpc),
}
}
pub fn get(bpc: u8) -> Option<&'static Self> {
static BPC8: OnceLock<Rav1dBitDepthDSPContext> = OnceLock::new();
static BPC10: OnceLock<Rav1dBitDepthDSPContext> = OnceLock::new();
static BPC12: OnceLock<Rav1dBitDepthDSPContext> = OnceLock::new();
Some(match bpc {
8 => BPC8.get_or_init(|| {
let flags = rav1d_get_cpu_flags();
Self::new::<BitDepth8>(flags, bpc)
}),
10 => BPC10.get_or_init(|| {
let flags = rav1d_get_cpu_flags();
Self::new::<BitDepth16>(flags, bpc)
}),
12 => BPC12.get_or_init(|| {
let flags = rav1d_get_cpu_flags();
Self::new::<BitDepth16>(flags, bpc)
}),
_ => return None,
})
}
}
impl Default for &'static Rav1dBitDepthDSPContext {
fn default() -> Self {
Rav1dBitDepthDSPContext::get(8).unwrap()
}
}
#[derive(Clone, Default)]
pub(crate) struct Rav1dTileGroupHeader {
pub start: c_int,
pub end: c_int,
}
#[derive(Clone, Default)]
pub(crate) struct Rav1dTileGroup {
pub data: Rav1dData,
pub hdr: Rav1dTileGroupHeader,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum TaskType {
Init = 0,
InitCdf = 1,
TileEntropy = 2,
EntropyProgress = 3,
TileReconstruction = 4,
DeblockCols = 5,
DeblockRows = 6,
Cdef = 7,
SuperResolution = 8,
LoopRestoration = 9,
ReconstructionProgress = 10,
FgPrep = 11,
FgApply = 12,
}
impl Default for TaskType {
fn default() -> Self {
Self::Init
}
}
#[derive(Default)]
#[repr(C)]
pub(crate) struct Rav1dContextFrameThread {
pub out_delayed: Box<[Rav1dThreadPicture]>,
pub next: c_uint,
}
pub type GrainLut<Entry> = [[Entry; GRAIN_WIDTH]; GRAIN_HEIGHT + 1];
pub struct GrainBD<BD: BitDepth> {
pub grain_lut: Align16<[GrainLut<BD::Entry>; 3]>,
pub scaling: Align64<[BD::Scaling; 3]>,
}
impl<BD: BitDepth> Default for GrainBD<BD> {
fn default() -> Self {
Self {
grain_lut: ArrayDefault::default(),
scaling: ArrayDefault::default(),
}
}
}
pub enum Grain {
#[cfg(feature = "bitdepth_8")]
Bpc8(GrainBD<BitDepth8>),
#[cfg(feature = "bitdepth_16")]
Bpc16(GrainBD<BitDepth16>),
}
impl Default for Grain {
fn default() -> Self {
cfg_if::cfg_if! {
if #[cfg(feature = "bitdepth_8")] {
Self::Bpc8(Default::default())
} else if #[cfg(feature = "bitdepth_16")] {
Self::Bpc16(Default::default())
} else {
compile_error!("No bitdepths enabled");
}
}
}
}
#[derive(Default)]
#[repr(C)]
pub(crate) struct TaskThreadDataDelayedFg {
pub in_0: Rav1dPicture,
pub out: Rav1dPicture,
pub type_0: TaskType,
pub grain: Grain,
}
#[derive(Default)]
#[repr(C)]
pub(crate) struct TaskThreadData {
pub lock: Mutex<()>,
pub cond: Condvar,
pub first: AtomicU32,
pub cur: RelaxedAtomic<u32>,
pub reset_task_cur: AtomicU32,
pub cond_signaled: AtomicI32,
pub delayed_fg_exec: RelaxedAtomic<i32>,
pub delayed_fg_cond: Condvar,
pub delayed_fg_progress: [AtomicI32; 2],
pub delayed_fg: RwLock<TaskThreadDataDelayedFg>,
}
#[derive(Default)]
#[repr(C)]
pub(crate) struct Rav1dContextRefs {
pub p: Rav1dThreadPicture,
pub segmap: Option<DisjointMutArcSlice<SegmentId>>,
pub refmvs: Option<DisjointMutArcSlice<RefMvsTemporalBlock>>,
pub refpoc: [c_uint; 7],
}
pub(crate) enum Rav1dContextTaskType {
Worker,
Single(Mutex<Box<Rav1dTaskContext>>),
}
pub(crate) struct Rav1dContextTaskThread {
pub task: Rav1dContextTaskType,
pub thread_data: Arc<Rav1dTaskContextTaskThread>,
}
impl Rav1dContextTaskThread {
pub fn flushed(&self) -> bool {
self.thread_data.flushed.get()
}
}
#[derive(Default)]
pub struct Rav1dState {
pub(crate) tiles: Vec<Rav1dTileGroup>,
pub(crate) n_tiles: c_int,
pub(crate) seq_hdr: Option<Arc<DRav1d<Rav1dSequenceHeader, Dav1dSequenceHeader>>>, pub(crate) frame_hdr: Option<Arc<DRav1d<Rav1dFrameHeader, Dav1dFrameHeader>>>, pub(crate) content_light: Option<Arc<Rav1dContentLightLevel>>,
pub(crate) mastering_display: Option<Arc<Rav1dMasteringDisplay>>,
pub(crate) itut_t35: Arc<Mutex<Vec<Rav1dITUTT35>>>,
pub(crate) in_0: Rav1dData,
pub(crate) out: Rav1dThreadPicture,
pub(crate) cache: Rav1dThreadPicture,
pub(crate) frame_thread: Rav1dContextFrameThread,
pub(crate) refs: [Rav1dContextRefs; 8],
pub(crate) cdf: [CdfThreadContext; 8],
pub(crate) operating_point_idc: c_uint,
pub(crate) max_spatial_id: u8,
pub(crate) drain: bool,
pub(crate) frame_flags: PictureFlags,
pub(crate) event_flags: Rav1dEventFlags,
pub(crate) cached_error_props: Rav1dDataProps,
pub(crate) cached_error: Option<Rav1dError>,
}
#[derive(Default)]
#[repr(C)]
#[repr(align(64))]
pub struct Rav1dContext {
pub(crate) state: Mutex<Rav1dState>,
pub(crate) fc: Box<[Rav1dFrameContext]>,
pub(crate) tc: Box<[Rav1dContextTaskThread]>,
pub(crate) flush: AtomicBool,
pub(crate) task_thread: Arc<TaskThreadData>,
pub dsp: &'static Rav1dDSPContext,
pub(crate) allocator: Rav1dPicAllocator,
pub(crate) apply_grain: bool,
pub(crate) operating_point: u8,
pub(crate) all_layers: bool,
pub(crate) frame_size_limit: c_uint,
pub(crate) strict_std_compliance: bool,
pub(crate) output_invisible_frames: bool,
pub(crate) inloop_filters: Rav1dInloopFilterType,
pub(crate) decode_frame_type: Rav1dDecodeFrameType,
pub(crate) logger: Option<Rav1dLogger>,
pub(crate) picture_pool: Arc<MemPool<u8>>,
}
#[derive(Default)]
#[repr(C)]
pub struct Rav1dTask {
pub frame_idx: c_uint,
pub tile_idx: c_uint,
pub type_0: TaskType,
pub sby: c_int,
pub recon_progress: c_int,
pub deblock_progress: c_int,
pub deps_skip: RelaxedAtomic<i32>,
pub next: Atomic<Rav1dTaskIndex>,
}
impl Rav1dTask {
pub fn init(frame_idx: c_uint) -> Self {
Self {
type_0: TaskType::Init,
frame_idx,
sby: 0,
deblock_progress: 0,
recon_progress: 0,
..Default::default()
}
}
pub fn next(&self) -> Rav1dTaskIndex {
self.next.load(Ordering::SeqCst)
}
pub fn set_next(&self, next: Rav1dTaskIndex) {
self.next.store(next, Ordering::SeqCst)
}
}
impl Rav1dTask {
pub fn without_next(&self) -> Self {
Self {
frame_idx: self.frame_idx,
tile_idx: self.tile_idx,
type_0: self.type_0,
sby: self.sby,
recon_progress: self.recon_progress,
deblock_progress: self.deblock_progress,
deps_skip: self.deps_skip.clone(),
next: Default::default(),
}
}
}
#[derive(Default)]
#[repr(C)]
pub struct ScalableMotionParams {
pub scale: c_int, pub step: c_int,
}
pub(crate) struct Rav1dFrameContextBdFn {
pub recon_b_intra: ReconBIntraFn,
pub recon_b_inter: ReconBInterFn,
pub filter_sbrow: FilterSbrowFn,
pub filter_sbrow_deblock_cols: FilterSbrowFn,
pub filter_sbrow_deblock_rows: FilterSbrowFn,
pub filter_sbrow_cdef: fn(&Rav1dContext, &Rav1dFrameData, &mut Rav1dTaskContext, c_int) -> (),
pub filter_sbrow_resize: FilterSbrowFn,
pub filter_sbrow_lr: FilterSbrowFn,
pub backup_ipred_edge: BackupIpredEdgeFn,
pub read_coef_blocks: ReadCoefBlocksFn,
pub copy_pal_block_y: CopyPalBlockFn,
pub copy_pal_block_uv: CopyPalBlockFn,
pub read_pal_plane: ReadPalPlaneFn,
pub read_pal_uv: ReadPalUVFn,
}
impl Rav1dFrameContextBdFn {
pub const fn new<BD: BitDepth>() -> Self {
Self {
recon_b_inter: rav1d_recon_b_inter::<BD>,
recon_b_intra: rav1d_recon_b_intra::<BD>,
filter_sbrow: rav1d_filter_sbrow::<BD>,
filter_sbrow_deblock_cols: rav1d_filter_sbrow_deblock_cols::<BD>,
filter_sbrow_deblock_rows: rav1d_filter_sbrow_deblock_rows::<BD>,
filter_sbrow_cdef: rav1d_filter_sbrow_cdef::<BD>,
filter_sbrow_resize: rav1d_filter_sbrow_resize::<BD>,
filter_sbrow_lr: rav1d_filter_sbrow_lr::<BD>,
backup_ipred_edge: rav1d_backup_ipred_edge::<BD>,
read_coef_blocks: rav1d_read_coef_blocks::<BD>,
copy_pal_block_y: rav1d_copy_pal_block_y::<BD>,
copy_pal_block_uv: rav1d_copy_pal_block_uv::<BD>,
read_pal_plane: rav1d_read_pal_plane::<BD>,
read_pal_uv: rav1d_read_pal_uv::<BD>,
}
}
pub const fn get(bpc: BPC) -> &'static Self {
const BPC8: Rav1dFrameContextBdFn = Rav1dFrameContextBdFn::new::<BitDepth8>();
const BPC16: Rav1dFrameContextBdFn = Rav1dFrameContextBdFn::new::<BitDepth16>();
match bpc {
BPC::BPC8 => &BPC8,
BPC::BPC16 => &BPC16,
}
}
}
#[derive(Clone, Copy, Default, Atom)]
pub struct CodedBlockInfo(i16);
impl CodedBlockInfo {
const TXTP_BITS: u8 = (TxfmType::BITS - WHT_WHT.leading_zeros()) as u8;
pub const fn eob(&self) -> i16 {
self.0 >> Self::TXTP_BITS
}
pub const fn txtp(&self) -> TxfmType {
(self.0 & ((1 << Self::TXTP_BITS) - 1)) as TxfmType
}
pub const fn new(eob: i16, txtp: TxfmType) -> Self {
debug_assert!(eob << Self::TXTP_BITS >> Self::TXTP_BITS == eob);
Self((eob << Self::TXTP_BITS) | (txtp as i16))
}
}
#[derive(Default)]
#[repr(C)]
pub struct Pal {
data: DisjointMut<AlignedVec64<u8>>,
}
type PalArray<BD> = [[<BD as BitDepth>::Pixel; 8]; 3];
impl Pal {
pub fn try_resize(&mut self, n: usize) -> Result<(), std::collections::TryReserveError> {
self.data.try_resize(n * 8 * 3, Default::default())
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn index<'a: 'b, 'b, BD: BitDepth>(
&'a self,
index: usize,
) -> DisjointImmutGuard<'b, AlignedVec64<u8>, PalArray<BD>> {
self.data.element_as(index)
}
pub fn index_mut<'a: 'b, 'b, BD: BitDepth>(
&'a self,
index: usize,
) -> DisjointMutGuard<'b, AlignedVec64<u8>, PalArray<BD>> {
self.data.mut_element_as(index)
}
}
#[derive(Default)]
#[repr(C)]
pub struct Rav1dFrameContextFrameThread {
pub next_tile_row: [RelaxedAtomic<i32>; 2],
pub b: DisjointMut<Vec<Av1Block>>,
pub cbi: Vec<RelaxedAtomic<CodedBlockInfo>>,
pub pal: Pal,
pub pal_idx: DisjointMut<AlignedVec64<u8>>,
pub cf: DisjointMut<AlignedVec64<u8>>,
pub tile_start_off: Vec<u32>,
}
#[derive(Default)]
pub(crate) struct TxLpfRightEdge {
inner: DisjointMut<Vec<u8>>,
}
impl TxLpfRightEdge {
#[allow(dead_code)]
pub fn new() -> Self {
Self {
inner: DisjointMut::default(),
}
}
pub fn try_resize(
&mut self,
right_edge_size: usize,
value: u8,
) -> Result<(), std::collections::TryReserveError> {
self.inner.try_resize(right_edge_size * 32 * 2, value)
}
pub fn get<'a>(
&'a self,
index_y: Range<usize>,
index_uv: Range<usize>,
) -> (
impl 'a + Deref<Target = [u8]>,
impl 'a + Deref<Target = [u8]>,
) {
let mid = self.inner.len() / 2;
assert!(index_y.end <= mid);
let (uv_start, uv_end) = (index_uv.start + mid, index_uv.end + mid);
(
self.inner.index(index_y),
self.inner.index(uv_start..uv_end),
)
}
pub fn copy_from_slice_y(&self, index: Range<usize>, src: &[u8]) {
#[allow(unused_mut)]
let mut slice_mut = self.inner.index_mut(index);
slice_mut.copy_from_slice(src);
}
pub fn copy_from_slice_uv(&self, index: Range<usize>, src: &[u8]) {
let mid = self.inner.len() / 2;
#[allow(unused_mut)]
let mut slice_mut = self.inner.index_mut(index.start + mid..index.end + mid);
slice_mut.copy_from_slice(src);
}
}
#[repr(C)]
pub struct Rav1dFrameContextLf {
pub level: Vec<AtomicU8>,
pub mask: Vec<Av1Filter>,
pub lr_mask: Vec<Av1Restoration>,
pub lim_lut: Align16<Av1FilterLUT>,
pub lvl: [Align16<[[[u8; 2]; 8]; 4]>; 8],
pub last_sharpness: u8,
pub tx_lpf_right_edge: TxLpfRightEdge,
pub cdef_line_buf: DisjointMut<AlignedVec64<u8>>,
pub lr_line_buf: DisjointMut<AlignedVec64<u8>>,
pub cdef_line: [[usize; 3]; 2],
pub cdef_lpf_line: [usize; 3],
pub lr_lpf_line: [usize; 3],
pub start_of_tile_row: Vec<u8>,
pub restore_planes: LrRestorePlanes,
}
impl Default for Rav1dFrameContextLf {
fn default() -> Self {
use crate::src::disjoint_mut::dm_new;
Self {
level: Vec::new(),
mask: Default::default(),
lr_mask: Default::default(),
lim_lut: Default::default(),
lvl: Default::default(),
last_sharpness: Default::default(),
tx_lpf_right_edge: Default::default(),
cdef_line_buf: dm_new(Default::default()),
lr_line_buf: dm_new(Default::default()),
cdef_line: Default::default(),
cdef_lpf_line: Default::default(),
lr_lpf_line: Default::default(),
start_of_tile_row: Default::default(),
restore_planes: Default::default(),
}
}
}
#[derive(Default)]
#[repr(C)]
pub(crate) struct Rav1dFrameContextTaskThread {
pub lock: Mutex<()>,
pub cond: Condvar,
pub ttd: Arc<TaskThreadData>,
pub tasks: Rav1dTasks,
pub init_done: AtomicI32,
pub done: [AtomicI32; 2],
pub retval: Mutex<Option<Rav1dError>>,
pub finished: AtomicBool, pub update_set: RelaxedAtomic<bool>, pub error: AtomicI32,
pub task_counter: AtomicI32,
}
#[derive(Default)]
pub(crate) struct Rav1dFrameContextFrameThreadProgress {
pub entropy: AtomicI32,
pub deblock: AtomicI32, pub frame: RwLock<Vec<AtomicU32>>,
pub copy_lpf: RwLock<Vec<AtomicU32>>,
}
pub(crate) struct Rav1dFrameContext {
pub index: usize,
pub data: RwLock<Rav1dFrameData>,
pub in_cdf: RwLock<CdfThreadContext>,
pub task_thread: Rav1dFrameContextTaskThread,
pub frame_thread_progress: Rav1dFrameContextFrameThreadProgress,
}
impl Rav1dFrameContext {
pub fn default(index: usize) -> Self {
Self {
index,
data: Default::default(),
in_cdf: Default::default(),
task_thread: Default::default(),
frame_thread_progress: Default::default(),
}
}
pub fn in_cdf<'a>(&'a self) -> RwLockReadGuard<'a, CdfThreadContext> {
self.in_cdf.try_read().unwrap()
}
pub fn frame_hdr(&self) -> Arc<DRav1d<Rav1dFrameHeader, Dav1dFrameHeader>> {
self.data
.try_read()
.unwrap()
.frame_hdr
.as_ref()
.unwrap()
.clone()
}
}
#[derive(Default)]
#[repr(C)]
pub(crate) struct Rav1dFrameData {
pub seq_hdr: Option<Arc<DRav1d<Rav1dSequenceHeader, Dav1dSequenceHeader>>>,
pub frame_hdr: Option<Arc<DRav1d<Rav1dFrameHeader, Dav1dFrameHeader>>>,
pub refp: [Rav1dThreadPicture; 7],
pub cur: Rav1dPicture,
pub sr_cur: Rav1dThreadPicture,
pub mvs: Option<DisjointMutArcSlice<RefMvsTemporalBlock>>, pub ref_mvs: [Option<DisjointMutArcSlice<RefMvsTemporalBlock>>; 7],
pub cur_segmap: Option<DisjointMutArcSlice<SegmentId>>, pub prev_segmap: Option<DisjointMutArcSlice<SegmentId>>,
pub refpoc: [c_uint; 7],
pub refrefpoc: [[c_uint; 7]; 7],
pub gmv_warp_allowed: [u8; 7],
pub out_cdf: CdfThreadContext,
pub tiles: Vec<Rav1dTileGroup>,
pub svc: [[ScalableMotionParams; 2]; 7],
pub resize_step: [c_int; 2],
pub resize_start: [c_int; 2],
pub ts: Vec<Rav1dTileState>,
pub dsp: &'static Rav1dBitDepthDSPContext,
pub ipred_edge: DisjointMut<AlignedVec64<u8>>, pub ipred_edge_off: usize,
pub b4_stride: ptrdiff_t,
pub w4: c_int,
pub h4: c_int,
pub bw: c_int,
pub bh: c_int,
pub sb128w: c_int,
pub sb128h: c_int,
pub sbh: c_int,
pub sb_shift: c_int,
pub sb_step: c_int,
pub sr_sb128w: c_int,
pub dq: [[[RelaxedAtomic<u16>; 2]; 3]; SegmentId::COUNT],
pub qm: [[Option<&'static [u8]>; 3]; 19],
pub a: Vec<BlockContext>,
pub rf: RefMvsFrame,
pub jnt_weights: [[u8; 7]; 7],
pub bitdepth_max: c_int,
pub frame_thread: Rav1dFrameContextFrameThread,
pub lf: Rav1dFrameContextLf,
pub lowest_pixel_mem: DisjointMut<Vec<[[c_int; 2]; 7]>>,
}
impl Rav1dFrameData {
pub fn bd_fn(&self) -> &'static Rav1dFrameContextBdFn {
let bpc = BPC::from_bitdepth_max(self.bitdepth_max);
Rav1dFrameContextBdFn::get(bpc)
}
pub fn frame_hdr(&self) -> &Rav1dFrameHeader {
self.frame_hdr.as_ref().unwrap()
}
pub fn seq_hdr(&self) -> &Rav1dSequenceHeader {
self.seq_hdr.as_ref().unwrap()
}
}
#[derive(Default)]
#[repr(C)]
pub struct Rav1dTileStateTiling {
pub col_start: i32,
pub col_end: i32,
pub row_start: i32,
pub row_end: i32,
pub col: i32,
pub row: i32,
}
#[derive(Default)]
#[repr(C)]
pub struct Rav1dTileStateFrameThread {
pub pal_idx: RelaxedAtomic<u32>,
pub cbi_idx: RelaxedAtomic<u32>,
pub cf: RelaxedAtomic<u32>,
}
#[derive(Default)]
#[repr(C, align(32))]
pub struct Rav1dTileStateContext {
pub cdf: CdfContext,
pub msac: MsacContext,
}
#[derive(Default)]
#[repr(C, align(32))]
pub struct Rav1dTileState {
pub context: Mutex<Rav1dTileStateContext>,
pub tiling: Rav1dTileStateTiling,
pub progress: [AtomicI32; 2],
pub frame_thread: [Rav1dTileStateFrameThread; 2],
pub lowest_pixel: usize,
pub dqmem: [[[RelaxedAtomic<u16>; 2]; 3]; SegmentId::COUNT],
pub dq: RelaxedAtomic<TileStateRef>,
pub last_qidx: RelaxedAtomic<u8>,
pub last_delta_lf: RelaxedAtomic<[i8; 4]>,
pub lflvlmem: RwLock<[Align16<[[[u8; 2]; 8]; 4]>; 8]>,
pub lflvl: RelaxedAtomic<TileStateRef>,
pub lr_ref: RwLock<[Av1RestorationUnit; 3]>,
}
#[derive(Clone, Copy, Default, FromRepr)]
#[repr(u8)]
pub enum TileStateRef {
#[default]
Frame,
Local,
}
impl Atom for TileStateRef {
type Repr = u8;
fn pack(self) -> Self::Repr {
self as u8
}
fn unpack(src: Self::Repr) -> Self {
Self::from_repr(src).unwrap_or_default()
}
}
pub const CF_LEN: usize = 32 * 32;
#[derive(FromZeros)]
#[repr(align(64))]
pub struct Cf([i32; CF_LEN]);
impl Cf {
#[allow(unused)]
pub fn select<BD: BitDepth>(&self) -> &[BD::Coef; CF_LEN] {
FromBytes::ref_from_prefix(IntoBytes::as_bytes(&self.0))
.unwrap()
.0
}
pub fn select_mut<BD: BitDepth>(&mut self) -> &mut [BD::Coef; CF_LEN] {
FromBytes::mut_from_prefix(IntoBytes::as_mut_bytes(&mut self.0))
.unwrap()
.0
}
}
#[derive(FromZeros)]
pub struct AlPal([u16; 8 * 3 * 32 * 2]);
impl AlPal {
pub fn select_mut<BD: BitDepth>(&mut self) -> &mut [[[[BD::Pixel; 8]; 3]; 32]; 2] {
FromBytes::mut_from_prefix(IntoBytes::as_mut_bytes(&mut self.0))
.unwrap()
.0
}
}
pub const COMPINTER_LEN: usize = 128 * 128;
pub const SEG_MASK_LEN: usize = 128 * 128;
#[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
#[repr(C, align(64))]
pub struct ScratchCompinter {
pub compinter: [[i16; COMPINTER_LEN]; 2],
pub seg_mask: [u8; SEG_MASK_LEN],
}
const SCRATCH_COMPINTER_SIZE: usize = mem::size_of::<ScratchCompinter>();
pub const SCRATCH_LAP_LEN: usize = 128 * 32;
#[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
#[repr(C, align(64))]
pub struct ScratchLapInter([u8; SCRATCH_COMPINTER_SIZE]);
impl ScratchLapInter {
pub fn lap_mut<BD: BitDepth>(&mut self) -> &mut [BD::Pixel; SCRATCH_LAP_LEN] {
FromBytes::mut_from_prefix(&mut self.0).unwrap().0
}
pub fn inter_mut(&mut self) -> &mut ScratchCompinter {
FromBytes::mut_from_prefix(&mut self.0).unwrap().0
}
}
pub const EMU_EDGE_LEN: usize = 320 * (256 + 7);
#[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
#[repr(C, align(64))]
pub struct ScratchEmuEdge([u8; EMU_EDGE_LEN * 2]);
impl ScratchEmuEdge {
pub fn buf_mut<BD: BitDepth>(&mut self) -> &mut [BD::Pixel; EMU_EDGE_LEN] {
FromBytes::mut_from_prefix(&mut self.0).unwrap().0
}
}
#[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
#[repr(C)]
pub struct ScratchInter {
pub lap_inter: ScratchLapInter,
pub emu_edge: ScratchEmuEdge,
}
#[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
#[repr(C, align(64))]
pub struct ScratchPal {
pub pal_order: [[u8; 8]; 64],
pub pal_ctx: [u8; 64],
}
#[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
#[repr(C, align(64))]
pub struct ScratchLevelsPal([u8; 32 * 34]);
impl ScratchLevelsPal {
pub fn levels_mut(&mut self) -> &mut [u8; 32 * 34] {
&mut self.0
}
pub fn pal_mut(&mut self) -> &mut ScratchPal {
FromBytes::mut_from_prefix(&mut self.0).unwrap().0
}
}
pub const SCRATCH_INTER_INTRA_BUF_LEN: usize = 64 * 64;
#[derive(Clone, Copy, FromBytes, IntoBytes, KnownLayout, Immutable)]
#[repr(C, align(64))]
pub struct ScratchInterIntraBuf([u16; SCRATCH_INTER_INTRA_BUF_LEN * 2]);
impl ScratchInterIntraBuf {
pub fn buf_mut<BD: BitDepth>(&mut self) -> &mut [BD::Pixel; SCRATCH_INTER_INTRA_BUF_LEN] {
FromBytes::mut_from_prefix(IntoBytes::as_mut_bytes(&mut self.0))
.unwrap()
.0
}
}
pub const SCRATCH_EDGE_LEN: usize = 257;
#[derive(Clone, Copy, FromBytes, IntoBytes, KnownLayout, Immutable)]
#[repr(C, align(64))]
pub struct ScratchEdgeBuf([u8; SCRATCH_EDGE_LEN * 2 + 62]);
impl ScratchEdgeBuf {
pub fn buf_mut<BD: BitDepth>(&mut self) -> &mut [BD::Pixel; SCRATCH_EDGE_LEN] {
FromBytes::mut_from_prefix(&mut self.0).unwrap().0
}
}
#[derive(Clone, Copy, FromBytes, IntoBytes, KnownLayout, Immutable)]
#[repr(C, align(16))] pub struct ScratchPalBuf([u8; 8 * 3 * 2]);
impl ScratchPalBuf {
pub fn buf<BD: BitDepth>(&self) -> &[[BD::Pixel; 8]; 3] {
FromBytes::ref_from_prefix(&self.0).unwrap().0
}
pub fn buf_mut<BD: BitDepth>(&mut self) -> &mut [[BD::Pixel; 8]; 3] {
FromBytes::mut_from_prefix(&mut self.0).unwrap().0
}
}
#[derive(Clone, Copy, FromBytes, IntoBytes, KnownLayout, Immutable)]
#[repr(C)]
pub struct ScratchInterIntraEdgePal {
pub interintra: ScratchInterIntraBuf,
pub edge: ScratchEdgeBuf,
pub pal: ScratchPalBuf,
_padding: [u8; 16],
}
pub const SCRATCH_AC_TXTP_LEN: usize = 32 * 32;
#[derive(Clone, Copy, FromBytes, IntoBytes, KnownLayout, Immutable)]
#[repr(C, align(64))]
pub struct ScratchAcTxtpMap([u8; SCRATCH_AC_TXTP_LEN * 2]);
impl ScratchAcTxtpMap {
pub fn ac_mut(&mut self) -> &mut [i16; SCRATCH_AC_TXTP_LEN] {
FromBytes::mut_from_prefix(&mut self.0).unwrap().0
}
pub fn txtp_map(&self) -> &[TxfmType; SCRATCH_AC_TXTP_LEN] {
FromBytes::ref_from_prefix(&self.0).unwrap().0
}
pub fn txtp_map_mut(&mut self) -> &mut [TxfmType; SCRATCH_AC_TXTP_LEN] {
FromBytes::mut_from_prefix(&mut self.0).unwrap().0
}
}
#[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
#[repr(C)]
pub struct ScratchInterIntra {
pub levels_pal: ScratchLevelsPal,
pub ac_txtp_map: ScratchAcTxtpMap,
pub pal_idx_y: [u8; 32 * 64],
pub pal_idx_uv: [u8; 64 * 64], pub interintra_edge_pal: ScratchInterIntraEdgePal,
}
const SCRATCH_SIZE: usize = mem::size_of::<ScratchInter>();
#[derive(FromZeros)]
#[repr(C)]
pub struct TaskContextScratch([u8; SCRATCH_SIZE]);
impl TaskContextScratch {
pub fn inter_mut(&mut self) -> &mut ScratchInter {
FromBytes::mut_from_prefix(&mut self.0).unwrap().0
}
pub fn inter_intra(&self) -> &ScratchInterIntra {
FromBytes::ref_from_prefix(&self.0).unwrap().0
}
pub fn inter_intra_mut(&mut self) -> &mut ScratchInterIntra {
FromBytes::mut_from_prefix(&mut self.0).unwrap().0
}
}
#[derive(Default)]
#[repr(C)]
pub struct Rav1dTaskContextFrameThread {
pub pass: c_int,
}
#[repr(C)]
pub(crate) struct Rav1dTaskContextTaskThread {
pub cond: Condvar,
pub ttd: Arc<TaskThreadData>,
pub flushed: RelaxedAtomic<bool>,
pub die: RelaxedAtomic<bool>,
pub c: Mutex<Option<Arc<Rav1dContext>>>,
}
impl Rav1dTaskContextTaskThread {
pub(crate) fn new(ttd: Arc<TaskThreadData>) -> Self {
Self {
cond: Condvar::new(),
ttd,
flushed: Default::default(),
die: Default::default(),
c: Default::default(),
}
}
}
#[derive(Clone, Copy, Default)]
pub struct Bxy {
pub x: c_int,
pub y: c_int,
}
#[repr(C)]
pub(crate) struct Rav1dTaskContext {
pub ts: usize, pub b: Bxy,
pub l: BlockContext,
pub a: usize, pub rt: RefmvsTile,
pub cf: Cf,
pub al_pal: AlPal,
pub pal_sz_uv: [[u8; 32]; 2],
pub scratch: TaskContextScratch,
pub warpmv: Rav1dWarpedMotionParams,
pub lf_mask: Option<usize>,
pub top_pre_cdef_toggle: c_int,
pub cur_sb_cdef_idx: usize, pub tl_4x4_filter: Filter2d,
pub frame_thread: Rav1dTaskContextFrameThread,
pub task_thread: Arc<Rav1dTaskContextTaskThread>,
}
impl Rav1dTaskContext {
pub(crate) fn new(task_thread: Arc<Rav1dTaskContextTaskThread>) -> Self {
Self {
ts: Default::default(),
b: Default::default(),
l: Default::default(),
a: Default::default(),
rt: Default::default(),
cf: FromZeros::new_zeroed(),
al_pal: FromZeros::new_zeroed(),
pal_sz_uv: Default::default(),
scratch: FromZeros::new_zeroed(),
warpmv: Default::default(),
lf_mask: Default::default(),
top_pre_cdef_toggle: Default::default(),
cur_sb_cdef_idx: Default::default(),
tl_4x4_filter: Default::default(),
frame_thread: Default::default(),
task_thread,
}
}
}