use std::sync::Arc;
use v_frame::{frame::Frame, pixel::Pixel, plane::Plane};
use crate::{
data::motion::{RefMEStats, ReferenceFramesSet},
math::Fixed,
};
pub const ALLOWED_REF_FRAMES: &[RefType] = &[RefType::LAST_FRAME];
pub const INTER_REFS_PER_FRAME: usize = 7;
#[derive(Clone)]
pub struct FrameState<T: Pixel> {
pub input: Arc<Frame<T>>,
pub input_hres: Option<Arc<Plane<T>>>, pub input_qres: Option<Arc<Plane<T>>>, pub frame_me_stats: RefMEStats,
}
impl<T: Pixel> FrameState<T> {
pub fn new_with_frame_and_me_stats_and_rec(frame: Arc<Frame<T>>, me_stats: RefMEStats) -> Self {
Self {
input: frame,
input_hres: None,
input_qres: None,
frame_me_stats: me_stats,
}
}
}
#[allow(non_camel_case_types)]
#[allow(dead_code)]
#[derive(PartialEq, Eq, PartialOrd, Copy, Clone, Debug)]
pub enum RefType {
INTRA_FRAME = 0,
LAST_FRAME = 1,
LAST2_FRAME = 2,
LAST3_FRAME = 3,
GOLDEN_FRAME = 4,
BWDREF_FRAME = 5,
ALTREF2_FRAME = 6,
ALTREF_FRAME = 7,
NONE_FRAME = 8,
}
impl RefType {
pub fn to_index(self) -> usize {
use self::RefType::{INTRA_FRAME, NONE_FRAME};
match self {
NONE_FRAME => {
panic!("Tried to get slot of NONE_FRAME");
}
INTRA_FRAME => {
panic!("Tried to get slot of INTRA_FRAME");
}
_ => (self as usize) - 1,
}
}
}
#[derive(Clone)]
pub struct FrameInvariants<T: Pixel> {
pub w_in_b: usize,
pub h_in_b: usize,
pub ref_frames: [u8; INTER_REFS_PER_FRAME],
pub rec_buffer: ReferenceFramesSet<T>,
}
impl<T: Pixel> FrameInvariants<T> {
pub fn new(width: usize, height: usize) -> Self {
let w_in_b = 2 * width.align_power_of_two_and_shift(3); let h_in_b = 2 * height.align_power_of_two_and_shift(3);
Self {
w_in_b,
h_in_b,
ref_frames: [0; INTER_REFS_PER_FRAME],
rec_buffer: ReferenceFramesSet::new(),
}
}
pub fn new_key_frame(width: usize, height: usize) -> Self {
Self::new(width, height)
}
pub(crate) fn new_inter_frame(
previous_coded_fi: &Self,
output_frameno_in_gop: u64,
) -> Option<Self> {
let mut fi = previous_coded_fi.clone();
let idx_in_group_output = get_idx_in_group_output(output_frameno_in_gop);
let order_hint = get_order_hint(output_frameno_in_gop, idx_in_group_output);
let slot_idx = get_slot_idx(0, order_hint);
fi.ref_frames = [(slot_idx + 4 - 1) as u8 % 4; INTER_REFS_PER_FRAME];
Some(fi)
}
}
const fn get_slot_idx(level: u64, order_hint: u32) -> u32 {
if level == 0 {
order_hint & 3
} else {
3 + level as u32
}
}
fn get_idx_in_group_output(output_frameno_in_gop: u64) -> u64 {
debug_assert!(output_frameno_in_gop > 0);
output_frameno_in_gop - 1
}
fn get_order_hint(output_frameno_in_gop: u64, idx_in_group_output: u64) -> u32 {
debug_assert!(output_frameno_in_gop > 0);
let group_idx = output_frameno_in_gop - 1;
let offset = idx_in_group_output + 1;
(group_idx + offset) as u32
}