Commit 68c291cc authored by Monty's avatar Monty Committed by Monty Montgomery

Add data structures and complete header for loop filter

This patch adds basic data structures for tracking loop filter state,
as well as being able to encode complete loop filter frame header
syntax.  No functional change.
parent 41448102
......@@ -29,7 +29,7 @@ use std::*;
use self::REF_CONTEXTS;
use self::SINGLE_REFS;
const PLANES: usize = 3;
pub const PLANES: usize = 3;
const PARTITION_PLOFFSET: usize = 4;
const PARTITION_BLOCK_SIZES: usize = 4 + 1;
......
......@@ -40,13 +40,15 @@ impl Frame {
#[derive(Debug)]
pub struct ReferenceFramesSet {
pub frames: [Option<Rc<Frame>>; (REF_FRAMES as usize)]
pub frames: [Option<Rc<Frame>>; (REF_FRAMES as usize)],
pub loop_filter: [DeblockState; (REF_FRAMES as usize)]
}
impl ReferenceFramesSet {
pub fn new() -> ReferenceFramesSet {
ReferenceFramesSet {
frames: Default::default()
frames: Default::default(),
loop_filter: Default::default()
}
}
}
......@@ -228,6 +230,33 @@ impl FrameState {
}
}
#[derive(Copy, Clone, Debug)]
pub struct DeblockState {
pub levels: [u8; PLANES+1],
pub sharpness: u8,
pub deltas_enabled: bool,
pub delta_updates_enabled: bool,
pub ref_deltas_enabled: bool,
pub ref_deltas: [i8; REF_FRAMES],
pub mode_deltas_enabled: bool,
pub mode_deltas: [i8; 2],
}
impl Default for DeblockState {
fn default() -> Self {
DeblockState {
levels: [0; PLANES+1],
sharpness: 0,
deltas_enabled: false,
delta_updates_enabled: false,
ref_deltas_enabled: false,
ref_deltas: [1, 0, 0, 0, 0, -1, -1, -1],
mode_deltas_enabled: false,
mode_deltas: [0, 0]
}
}
}
// Frame Invariants are invariant inside a frame
#[allow(dead_code)]
#[derive(Debug)]
......@@ -275,6 +304,7 @@ pub struct FrameInvariants {
pub config: EncoderConfig,
pub ref_frames: [usize; INTER_REFS_PER_FRAME],
pub rec_buffer: ReferenceFramesSet,
pub loop_filter: DeblockState
}
impl FrameInvariants {
......@@ -337,7 +367,8 @@ impl FrameInvariants {
cdef_uv_strengths: [0*4+0, 1*4+0, 2*4+1, 3*4+1, 5*4+2, 7*4+3, 10*4+3, 13*4+3],
config,
ref_frames: [0; INTER_REFS_PER_FRAME],
rec_buffer: ReferenceFramesSet::new()
rec_buffer: ReferenceFramesSet::new(),
loop_filter: Default::default()
}
}
......@@ -442,7 +473,7 @@ trait UncompressedHeader {
// End of OBU Headers
fn write_frame_size(&mut self, fi: &FrameInvariants) -> io::Result<()>;
fn write_loop_filter(&mut self) -> io::Result<()>;
fn write_loop_filter(&mut self, fi: &FrameInvariants) -> io::Result<()>;
fn write_frame_cdef(&mut self, seq: &Sequence, fi: &FrameInvariants) -> io::Result<()>;
}
#[allow(unused)]
......@@ -831,7 +862,7 @@ impl<'a> UncompressedHeader for BitWriter<'a, BE> {
self.write_bit(false)?; // delta_q_present_flag: no delta q
// loop filter
self.write_loop_filter()?;
self.write_loop_filter(fi)?;
// cdef
self.write_frame_cdef(seq, fi)?;
// loop restoration
......@@ -921,11 +952,51 @@ impl<'a> UncompressedHeader for BitWriter<'a, BE> {
Ok(())
}
fn write_loop_filter(&mut self) -> io::Result<()> {
self.write(6,0)?; // loop filter level 0
self.write(6,0)?; // loop filter level 1
fn write_loop_filter(&mut self, fi: &FrameInvariants) -> io::Result<()> {
assert!(fi.loop_filter.levels[0] < 64);
self.write(6, fi.loop_filter.levels[0])?; // loop filter level 0
assert!(fi.loop_filter.levels[1] < 64);
self.write(6, fi.loop_filter.levels[1])?; // loop filter level 1
if PLANES > 1 && (fi.loop_filter.levels[0] > 0 || fi.loop_filter.levels[1] > 0) {
assert!(fi.loop_filter.levels[2] < 64);
self.write(6, fi.loop_filter.levels[2])?; // loop filter level 2
assert!(fi.loop_filter.levels[3] < 64);
self.write(6, fi.loop_filter.levels[3])?; // loop filter level 3
}
self.write(3,0)?; // loop filter sharpness
self.write_bit(false) // loop filter deltas enabled
self.write_bit(fi.loop_filter.deltas_enabled)?; // loop filter deltas enabled
if fi.loop_filter.deltas_enabled {
self.write_bit(fi.loop_filter.delta_updates_enabled)?; // deltas updates enabled
if fi.loop_filter.delta_updates_enabled {
// conditionally write ref delta updates
let prev_ref_deltas = if fi.primary_ref_frame == PRIMARY_REF_NONE {
[1, 0, 0, 0, 0, -1, -1, -1]
} else {
fi.rec_buffer.loop_filter[fi.ref_frames[fi.primary_ref_frame as usize]].ref_deltas
};
for i in 0..REF_FRAMES {
let update = fi.loop_filter.ref_deltas[i] != prev_ref_deltas[i];
self.write_bit(update)?;
if update {
self.write_signed(7,fi.loop_filter.ref_deltas[i])?;
}
}
// conditionally write mode delta updates
let prev_mode_deltas = if fi.primary_ref_frame == PRIMARY_REF_NONE {
[0, 0]
} else {
fi.rec_buffer.loop_filter[fi.ref_frames[fi.primary_ref_frame as usize]].mode_deltas
};
for i in 0..2 {
let update = fi.loop_filter.mode_deltas[i] != prev_mode_deltas[i];
self.write_bit(update)?;
if update {
self.write_signed(7,fi.loop_filter.mode_deltas[i])?;
}
}
}
}
Ok(())
}
fn write_frame_cdef(&mut self, seq: &Sequence, fi: &FrameInvariants) -> io::Result<()> {
......@@ -1664,6 +1735,7 @@ pub fn update_rec_buffer(fi: &mut FrameInvariants, fs: FrameState) {
for i in 0..(REF_FRAMES as usize) {
if (fi.refresh_frame_flags & (1 << i)) != 0 {
fi.rec_buffer.frames[i] = Some(Rc::clone(&rfs));
fi.rec_buffer.loop_filter[i] = fi.loop_filter.clone();
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment