Commit 6cca47f3 authored by Monty's avatar Monty Committed by Thomas Daede
Browse files

Write RU-level restoration filter paramters

This also implements initial infrastructure for tracking RUs of any legal size
relative to superblocks
parent 7cdd3a5f
......@@ -52,8 +52,7 @@ fn write_b_bench(b: &mut Bencher, tx_size: TxSize, qindex: usize) {
let bc = BlockContext::new(fi.sb_width * 16, fi.sb_height * 16);
let mut fs = FrameState::new(&fi, Default::default());
// For now, restoration unit size is locked to superblock size.
let rc = RestorationContext::new(fi.sb_width, fi.sb_height);
let mut cw = ContextWriter::new(fc, bc, rc);
let mut cw = ContextWriter::new(fc, bc);
let tx_type = TxType::DCT_DCT;
......
......@@ -19,12 +19,12 @@
use ec::Writer;
use encoder::{FrameInvariants, ReferenceMode};
use entropymode::*;
use lrf::{WIENER_TAPS_MID, SGR_XQD_MID};
use partition::*;
use partition::BlockSize::*;
use partition::PredictionMode::*;
use partition::TxSize::*;
use partition::TxType::*;
use partition::*;
use lrf::*;
use plane::*;
use scan_order::*;
use token_cdfs::*;
......@@ -717,6 +717,9 @@ pub struct CDFContext {
deblock_delta_multi_cdf: [[u16; DELTA_LF_PROBS + 1 + 1]; FRAME_LF_COUNT],
deblock_delta_cdf: [u16; DELTA_LF_PROBS + 1 + 1],
spatial_segmentation_cdfs: [[u16; 8 + 1]; 3],
lrf_switchable_cdf: [u16; 3+1],
lrf_sgrproj_cdf: [u16; 2+1],
lrf_wiener_cdf: [u16; 2+1],
// lv_map
txb_skip_cdf: [[[u16; 3]; TXB_SKIP_CONTEXTS]; TxSize::TX_SIZES],
......@@ -775,6 +778,9 @@ impl CDFContext {
deblock_delta_multi_cdf: default_delta_lf_multi_cdf,
deblock_delta_cdf: default_delta_lf_cdf,
spatial_segmentation_cdfs: default_spatial_pred_seg_tree_cdf,
lrf_switchable_cdf: default_switchable_restore_cdf,
lrf_sgrproj_cdf: default_sgrproj_restore_cdf,
lrf_wiener_cdf: default_wiener_restore_cdf,
// lv_map
txb_skip_cdf: av1_default_txb_skip_cdfs[qctx],
......@@ -850,6 +856,9 @@ impl CDFContext {
reset_2d!(self.deblock_delta_multi_cdf);
reset_1d!(self.deblock_delta_cdf);
reset_2d!(self.spatial_segmentation_cdfs);
reset_1d!(self.lrf_switchable_cdf);
reset_1d!(self.lrf_sgrproj_cdf);
reset_1d!(self.lrf_wiener_cdf);
reset_1d!(self.nmv_context.joints_cdf);
for i in 0..2 {
......@@ -951,6 +960,18 @@ impl CDFContext {
self.spatial_segmentation_cdfs.first().unwrap().as_ptr() as usize;
let spatial_segmentation_cdfs_end =
spatial_segmentation_cdfs_start + size_of_val(&self.spatial_segmentation_cdfs);
let lrf_switchable_cdf_start =
self.lrf_switchable_cdf.as_ptr() as usize;
let lrf_switchable_cdf_end =
lrf_switchable_cdf_start + size_of_val(&self.lrf_switchable_cdf);
let lrf_sgrproj_cdf_start =
self.lrf_sgrproj_cdf.as_ptr() as usize;
let lrf_sgrproj_cdf_end =
lrf_sgrproj_cdf_start + size_of_val(&self.lrf_sgrproj_cdf);
let lrf_wiener_cdf_start =
self.lrf_wiener_cdf.as_ptr() as usize;
let lrf_wiener_cdf_end =
lrf_wiener_cdf_start + size_of_val(&self.lrf_wiener_cdf);
let txb_skip_cdf_start =
self.txb_skip_cdf.first().unwrap().as_ptr() as usize;
......@@ -1024,6 +1045,9 @@ impl CDFContext {
("deblock_delta_multi_cdf", deblock_delta_multi_cdf_start, deblock_delta_multi_cdf_end),
("deblock_delta_cdf", deblock_delta_cdf_start, deblock_delta_cdf_end),
("spatial_segmentation_cdfs", spatial_segmentation_cdfs_start, spatial_segmentation_cdfs_end),
("lrf_switchable_cdf", lrf_switchable_cdf_start, lrf_switchable_cdf_end),
("lrf_sgrproj_cdf", lrf_sgrproj_cdf_start, lrf_sgrproj_cdf_end),
("lrf_wiener_cdf", lrf_wiener_cdf_start, lrf_wiener_cdf_end),
("txb_skip_cdf", txb_skip_cdf_start, txb_skip_cdf_end),
("dc_sign_cdf", dc_sign_cdf_start, dc_sign_cdf_end),
("eob_extra_cdf", eob_extra_cdf_start, eob_extra_cdf_end),
......@@ -1672,53 +1696,6 @@ impl BlockContext {
}
}
#[derive(Copy, Clone)]
pub enum RestorationFilter {
None,
Wiener { coeffs: [[i8; 2]; 3] },
Sgr { xqd: [i8; 2] },
}
impl RestorationFilter {
pub fn default() -> RestorationFilter {
RestorationFilter::None
}
}
#[derive(Copy, Clone)]
pub struct RestorationUnit {
pub params: RestorationFilter,
}
impl RestorationUnit {
pub fn default() -> RestorationUnit {
RestorationUnit {
params: RestorationFilter::default()
}
}
}
#[derive(Clone, Default)]
pub struct RestorationContext {
pub cols: usize,
pub rows: usize,
pub wiener_ref: [[[i8; 3]; 2]; PLANES],
pub sgr_ref: [[i8; 2]; PLANES],
pub units: Vec<Vec<Vec<RestorationUnit>>>
}
impl RestorationContext {
pub fn new(cols: usize, rows: usize) -> RestorationContext {
RestorationContext {
cols,
rows,
wiener_ref: [[WIENER_TAPS_MID; 2]; PLANES],
sgr_ref: [SGR_XQD_MID; PLANES],
units: vec![vec![vec![RestorationUnit::default(); cols]; rows]; PLANES]
}
}
}
#[derive(Copy, Clone, PartialEq)]
pub enum CFLSign {
CFL_SIGN_ZERO = 0,
......@@ -1828,18 +1805,16 @@ pub struct ContextWriterCheckpoint {
pub struct ContextWriter {
pub bc: BlockContext,
pub fc: CDFContext,
pub rc: RestorationContext,
#[cfg(debug)]
fc_map: Option<FieldMap> // For debugging purposes
}
impl ContextWriter {
pub fn new(fc: CDFContext, bc: BlockContext, rc: RestorationContext) -> Self {
pub fn new(fc: CDFContext, bc: BlockContext) -> Self {
#[allow(unused_mut)]
let mut cw = ContextWriter {
fc,
bc,
rc,
#[cfg(debug)]
fc_map: Default::default()
};
......@@ -3075,6 +3050,91 @@ impl ContextWriter {
symbol_with_update!(self, w, coded_id as u32, &mut self.fc.spatial_segmentation_cdfs[cdf_index as usize]);
}
pub fn write_lrf(&mut self, w: &mut dyn Writer, fi: &FrameInvariants, rs: &mut RestorationState,
sbo: &SuperBlockOffset) {
if !fi.allow_intrabc { // TODO: also disallow if lossless
for pli in 0..PLANES {
let code;
let rp = &mut rs.plane[pli];
{
let ru = &mut rp.restoration_unit_as_mut(sbo);
code = !ru.coded;
ru.coded = true;
}
if code {
match rp.restoration_unit_as_mut(sbo).filter {
RestorationFilter::None => {
match rp.lrf_type {
RESTORE_WIENER => {
symbol_with_update!(self, w, 0, &mut self.fc.lrf_wiener_cdf);
}
RESTORE_SGRPROJ => {
symbol_with_update!(self, w, 0, &mut self.fc.lrf_sgrproj_cdf);
}
RESTORE_SWITCHABLE => {
symbol_with_update!(self, w, RESTORE_NONE as u32, &mut self.fc.lrf_switchable_cdf);
}
RESTORE_NONE => {}
_ => unreachable!()
}
}
RestorationFilter::Sgrproj{set, xqd} => {
match rs.lrf_type[pli] {
RESTORE_SGRPROJ => {
symbol_with_update!(self, w, 1, &mut self.fc.lrf_sgrproj_cdf);
}
RESTORE_SWITCHABLE => {
symbol_with_update!(self, w, RESTORE_SGRPROJ as u32, &mut self.fc.lrf_switchable_cdf);
}
_ => unreachable!()
}
w.literal(SGRPROJ_PARAMS_BITS, set as u32);
for i in 0..2 {
let r = SGRPROJ_PARAMS_RADIUS[set as usize][i];
let min = SGRPROJ_XQD_MIN[i] as i32;
let max = SGRPROJ_XQD_MAX[i] as i32;
if r>0 {
w.write_signed_subexp_with_ref(xqd[i] as i32, min, max+1, SGRPROJ_PRJ_SUBEXP_K,
rp.sgrproj_ref[i] as i32);
rp.sgrproj_ref[i] = xqd[i];
} else {
// Nothing written, just update the reference
if i==0 {
rp.sgrproj_ref[0] = 0;
} else {
rp.sgrproj_ref[1] =
clamp((1 << SGRPROJ_PRJ_BITS) - rp.sgrproj_ref[0], min as i8, max as i8);
}
}
}
}
RestorationFilter::Wiener{coeffs} => {
match rs.lrf_type[pli] {
RESTORE_WIENER => {
symbol_with_update!(self, w, 1, &mut self.fc.lrf_wiener_cdf);
}
RESTORE_SWITCHABLE => {
symbol_with_update!(self, w, RESTORE_WIENER as u32, &mut self.fc.lrf_switchable_cdf);
}
_ => unreachable!()
}
for pass in 0..2 {
let first_coeff = if pli==0 {0} else {1};
for i in first_coeff..3 {
let min = WIENER_TAPS_MIN[i] as i32;
let max = WIENER_TAPS_MAX[i] as i32;
w.write_signed_subexp_with_ref(coeffs[pass][i] as i32, min, max+1, (i+1) as u8,
rp.wiener_ref[pass][i] as i32);
rp.wiener_ref[pass][i] = coeffs[pass][i];
}
}
}
}
}
}
}
}
pub fn write_cdef(&mut self, w: &mut dyn Writer, strength_index: u8, bits: u8) {
w.literal(bits, strength_index as u32);
}
......
......@@ -17,6 +17,7 @@ use bitstream_io::{BitWriter, BigEndian};
use std;
use std::io;
use util::ILog;
use util::msb;
pub const OD_BITRES: u8 = 3;
const EC_PROB_SHIFT: u32 = 6;
......@@ -43,6 +44,16 @@ pub trait Writer {
fn literal(&mut self, bits: u8, s: u32);
/// Write passed level as a golomb code
fn write_golomb(&mut self, level: u16);
/// Write a value v in [0, n-1] quasi-uniformly
fn write_quniform(&mut self, n: u32, v: u32);
/// Write symbol v in [0, n-1] with parameter k as finite subexponential
fn write_subexp(&mut self, n: u32, k: u8, v: u32);
/// Write symbol v in [0, n-1] with parameter k as finite
/// subexponential based on a reference ref also in [0, n-1].
fn write_unsigned_subexp_with_ref(&mut self, v: u32, mx: u32, k: u8, r: u32);
/// Write symbol v in [-(n-1), n-1] with parameter k as finite
/// subexponential based on a reference ref also in [-(n-1), n-1].
fn write_signed_subexp_with_ref(&mut self, v: i32, low: i32, high: i32, k: u8, r: i32);
/// Return current length of range-coded bitstream in integer bits
fn tell(&mut self) -> u32;
/// Return currrent length of range-coded bitstream in fractional
......@@ -344,6 +355,9 @@ impl<S> WriterBase<S> {
}
}
}
fn recenter(r: u32, v: u32) -> u32 {
if v > (r << 1) {v} else if v >= r {v - r << 1} else {(r - v << 1) - 1}
}
#[cfg(debug)]
fn print_backtrace(&self, s: u32) {
......@@ -513,6 +527,70 @@ where
self.bit((x >> i) & 0x01);
}
}
/// Write a value v in [0, n-1] quasi-uniformly
/// n: size of interval
/// v: value to encode
fn write_quniform(&mut self, n: u32, v: u32) {
if n > 1 {
let l = msb(n as i32) as u8 + 1;
let m = (1 << l) - n;
if v < m {
self.literal(l-1, v);
} else {
self.literal(l-1, m + (v-m >> 1));
self.literal(1, (v-m) & 1);
}
}
}
/// Write symbol v in [0, n-1] with parameter k as finite subexponential
/// n: size of interval
/// k: 'parameter'
/// v: value to encode
fn write_subexp(&mut self, n: u32, k: u8, v: u32) {
let mut i = 0;
let mut mk = 0;
loop {
let b = if i != 0 {k + i - 1} else {k};
let a = 1 << b;
if n <= mk + 3 * a {
self.write_quniform(n - mk, v - mk);
break;
} else {
let t = v >= mk + a;
self.bool(t, 16384);
if t {
i += 1;
mk += a;
} else {
self.literal(b, v - mk);
break;
}
}
}
}
/// Write symbol v in [0, n-1] with parameter k as finite
/// subexponential based on a reference ref also in [0, n-1].
/// v: value to encode
/// n: size of interval
/// k: 'parameter'
/// r: reference
fn write_unsigned_subexp_with_ref(&mut self, v: u32, n: u32, k: u8, r: u32) {
if (r << 1) <= n {
self.write_subexp(n, k, Self::recenter(r, v));
} else {
self.write_subexp(n, k, Self::recenter(n-1-r, n-1-v));
}
}
/// Write symbol v in [-(n-1), n-1] with parameter k as finite
/// subexponential based on a reference ref also in [-(n-1), n-1].
/// v: value to encode
/// n: size of interval
/// k: 'parameter'
/// r: reference
fn write_signed_subexp_with_ref(&mut self, v: i32, low: i32, high: i32, k: u8, r: i32) {
self.write_unsigned_subexp_with_ref((v - low) as u32, (high - low) as u32, k, (r - low) as u32);
}
/// Returns the number of bits "used" by the encoded symbols so far.
/// This same number can be computed in either the encoder or the
/// decoder, and is suitable for making coding decisions. The value
......
......@@ -575,7 +575,6 @@ pub struct FrameInvariants {
pub cdef_bits: u8,
pub cdef_y_strengths: [u8; 8],
pub cdef_uv_strengths: [u8; 8],
pub lrf_types: [u8; PLANES],
pub delta_q_present: bool,
pub config: EncoderConfig,
pub ref_frames: [u8; INTER_REFS_PER_FRAME],
......@@ -647,7 +646,6 @@ impl FrameInvariants {
cdef_bits: 3,
cdef_y_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],
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],
lrf_types: [RESTORE_NONE, RESTORE_NONE, RESTORE_NONE],
delta_q_present: false,
config,
ref_frames: [0; INTER_REFS_PER_FRAME],
......@@ -901,7 +899,8 @@ trait UncompressedHeader {
-> io::Result<()>;
fn write_sequence_header_obu(&mut self, seq: &mut Sequence, fi: &FrameInvariants)
-> io::Result<()>;
fn write_frame_header_obu(&mut self, seq: &Sequence, fi: &FrameInvariants, fs: &FrameState)
fn write_frame_header_obu(&mut self, seq: &Sequence, fi: &FrameInvariants, fs: &FrameState,
rs: &RestorationState)
-> io::Result<()>;
fn write_sequence_header(&mut self, seq: &mut Sequence, fi: &FrameInvariants)
-> io::Result<()>;
......@@ -912,7 +911,7 @@ trait UncompressedHeader {
fn write_deblock_filter_a(&mut self, fi: &FrameInvariants, fs: &FrameState) -> io::Result<()>;
fn write_deblock_filter_b(&mut self, fi: &FrameInvariants, fs: &FrameState) -> io::Result<()>;
fn write_frame_cdef(&mut self, seq: &Sequence, fi: &FrameInvariants) -> io::Result<()>;
fn write_frame_lrf(&mut self, seq: &Sequence, fi: &FrameInvariants) -> io::Result<()>;
fn write_frame_lrf(&mut self, seq: &Sequence, fi: &FrameInvariants, rs: &RestorationState) -> io::Result<()>;
fn write_segment_data(&mut self, fi: &FrameInvariants, fs: &FrameState) -> io::Result<()>;
fn write_delta_q(&mut self, delta_q: i8) -> io::Result<()>;
}
......@@ -1088,7 +1087,8 @@ impl<W: io::Write> UncompressedHeader for BitWriter<W, BigEndian> {
}
#[allow(unused)]
fn write_frame_header_obu(&mut self, seq: &Sequence, fi: &FrameInvariants, fs: &FrameState)
fn write_frame_header_obu(&mut self, seq: &Sequence, fi: &FrameInvariants, fs: &FrameState,
rs: &RestorationState)
-> io::Result<()> {
if seq.reduced_still_picture_hdr {
assert!(fi.show_existing_frame);
......@@ -1337,7 +1337,7 @@ impl<W: io::Write> UncompressedHeader for BitWriter<W, BigEndian> {
self.write_frame_cdef(seq, fi)?;
// loop restoration
self.write_frame_lrf(seq,fi)?;
self.write_frame_lrf(seq, fi, rs)?;
self.write_bit(false)?; // tx mode == TX_MODE_SELECT ?
......@@ -1497,34 +1497,30 @@ impl<W: io::Write> UncompressedHeader for BitWriter<W, BigEndian> {
Ok(())
}
fn write_frame_lrf(&mut self, seq: &Sequence, fi: &FrameInvariants) -> io::Result<()> {
fn write_frame_lrf(&mut self, seq: &Sequence, fi: &FrameInvariants,
rs: &RestorationState) -> io::Result<()> {
if seq.enable_restoration && !fi.allow_intrabc { // && !self.lossless
let mut use_lrf = false;
let mut use_chroma_lrf = false;
for i in 0..PLANES {
self.write(2,fi.lrf_types[i])?; // filter type by plane
if fi.lrf_types[i] != RESTORE_NONE {
self.write(2,rs.lrf_type[i])?; // filter type by plane
if rs.lrf_type[i] != RESTORE_NONE {
use_lrf = true;
if i > 0 { use_chroma_lrf = true; }
}
}
if use_lrf {
// At present, we're locked to a restoration unit size equal to superblock size.
// Signal as such.
if seq.use_128x128_superblock {
self.write(1,0)?; // do not double the restoration unit from 128x128
} else {
self.write(1,0)?; // do not double the restoration unit from 64x64
// The Y shift value written here indicates shift up from superblock size
if !seq.use_128x128_superblock {
self.write(1, if rs.unit_size[0] > 64 {1} else {0})?;
}
if rs.unit_size[0] > 64 {
self.write(1, if rs.unit_size[0] > 128 {1} else {0})?;
}
if use_chroma_lrf {
// until we're able to support restoration units larger than
// the chroma superblock size, we can't perform LRF for
// anything other than 4:4:4 and 4:2:0
assert!(seq.chroma_sampling == ChromaSampling::Cs444 ||
seq.chroma_sampling == ChromaSampling::Cs420);
if seq.chroma_sampling == ChromaSampling::Cs420 {
self.write(1,1)?; // halve the chroma restoration unit in both directions
self.write(1, if rs.unit_size[0] > rs.unit_size[1] {1} else {0})?;
}
}
}
......@@ -1615,13 +1611,14 @@ fn aom_uleb_encode(mut value: u64, coded_value: &mut [u8]) -> usize {
}
fn write_obus(packet: &mut dyn io::Write, sequence: &mut Sequence,
fi: &mut FrameInvariants, fs: &FrameState) -> io::Result<()> {
fi: &mut FrameInvariants, fs: &FrameState, rs: &RestorationState)
-> io::Result<()> {
//let mut uch = BitWriter::endian(packet, BigEndian);
let obu_extension = 0 as u32;
let mut buf1 = Vec::new();
{
let mut bw1 = BitWriter::endian(&mut buf1, BigEndian);
let mut bw1 = BitWriter::endian(&mut buf1, BigEndian);
bw1.write_obu_header(OBU_Type::OBU_TEMPORAL_DELIMITER, obu_extension)?;
bw1.write(8,0)?; // size of payload == 0, one byte
}
......@@ -1664,7 +1661,7 @@ fn write_obus(packet: &mut dyn io::Write, sequence: &mut Sequence,
let mut buf2 = Vec::new();
{
let mut bw2 = BitWriter::endian(&mut buf2, BigEndian);
bw2.write_frame_header_obu(sequence, fi, fs)?;
bw2.write_frame_header_obu(sequence, fi, fs, rs)?;
}
{
......@@ -2571,7 +2568,8 @@ fn encode_partition_topdown(seq: &Sequence, fi: &FrameInvariants, fs: &mut Frame
}
}
fn encode_tile(sequence: &mut Sequence, fi: &FrameInvariants, fs: &mut FrameState, bit_depth: usize) -> Vec<u8> {
fn encode_tile(sequence: &mut Sequence, fi: &FrameInvariants, fs: &mut FrameState,
rs: &mut RestorationState, bit_depth: usize) -> Vec<u8> {
let mut w = WriterEncoder::new();
let fc = if fi.primary_ref_frame == PRIMARY_REF_NONE {
......@@ -2585,8 +2583,7 @@ fn encode_tile(sequence: &mut Sequence, fi: &FrameInvariants, fs: &mut FrameStat
let bc = BlockContext::new(fi.w_in_b, fi.h_in_b);
// For now, restoration unit size is locked to superblock size.
let rc = RestorationContext::new(fi.sb_width, fi.sb_height);
let mut cw = ContextWriter::new(fc, bc, rc);
let mut cw = ContextWriter::new(fc, bc);
// initial coarse ME loop
let mut frame_pmvs = Vec::new();
......@@ -2685,6 +2682,8 @@ fn encode_tile(sequence: &mut Sequence, fi: &FrameInvariants, fs: &mut FrameStat
// loop restoration must be decided last but coded before anything else
if sequence.enable_restoration {
rs.lrf_optimize_superblock(&sbo, fi, fs, &mut cw, bit_depth);
cw.write_lrf(&mut w, fi, rs, &sbo);
}
// Once loop restoration is coded, we can replay the initial block bits
......@@ -2703,9 +2702,19 @@ fn encode_tile(sequence: &mut Sequence, fi: &FrameInvariants, fs: &mut FrameStat
if fs.deblock.levels[0] != 0 || fs.deblock.levels[1] != 0 {
deblock_filter_frame(fs, &mut cw.bc, bit_depth);
}
/* TODO: Don't apply if lossless */
if sequence.enable_cdef {
{
// Until the loop filters are pipelined, we'll need to keep
// around a copy of both the pre- and post-cdef frame.
let pre_cdef_frame = fs.rec.clone();
/* TODO: Don't apply if lossless */
if sequence.enable_cdef {
cdef_filter_frame(fi, &mut fs.rec, &mut cw.bc, bit_depth);
}
/* TODO: Don't apply if lossless */
if sequence.enable_restoration {
rs.lrf_filter_frame(fs, &pre_cdef_frame, &cw.bc, bit_depth);
}
}
fs.cdfs = cw.fc;
......@@ -2730,9 +2739,10 @@ fn write_tile_group_header(tile_start_and_end_present_flag: bool) ->
pub fn encode_frame(sequence: &mut Sequence, fi: &mut FrameInvariants, fs: &mut FrameState) -> Vec<u8> {
let mut packet = Vec::new();
let mut rs = RestorationState::new(sequence, &fs.input);
if fi.show_existing_frame {
//write_uncompressed_header(&mut packet, sequence, fi).unwrap();
write_obus(&mut packet, sequence, fi, fs).unwrap();
write_obus(&mut packet, sequence, fi, fs, &rs).unwrap();
match fi.rec_buffer.frames[fi.frame_to_show_map_idx as usize] {
Some(ref rec) => for p in 0..3 {
fs.rec.planes[p].data.copy_from_slice(rec.frame.planes[p].data.as_slice());
......@@ -2763,10 +2773,10 @@ pub fn encode_frame(sequence: &mut Sequence, fi: &mut FrameInvariants, fs: &mut
segmentation_optimize(fi, fs);
let tile = encode_tile(sequence, fi, fs, bit_depth); // actually tile group
let tile = encode_tile(sequence, fi, fs, &mut rs, bit_depth); // actually tile group
//write_uncompressed_header(&mut packet, sequence, fi).unwrap();
write_obus(&mut packet, sequence, fi, fs).unwrap();
write_obus(&mut packet, sequence, fi, fs, &rs).unwrap();
let mut buf1 = Vec::new();
{
let mut bw1 = BitWriter::endian(&mut buf1, BigEndian);
......
......@@ -9,6 +9,19 @@
#![allow(safe_extern_statics)]
use encoder::Frame;
use encoder::FrameState;
use encoder::FrameInvariants;
use context::BlockContext;
use context::ContextWriter;
use context::SuperBlockOffset;
use context::PLANES;
use encoder::Sequence;
use plane::PlaneConfig;
use std::cmp;
pub const RESTORATION_TILESIZE_MAX: usize = 256;
pub const RESTORE_NONE: u8 = 0;
pub const RESTORE_SWITCHABLE: u8 = 1;
pub const RESTORE_WIENER: u8 = 2;
......@@ -17,7 +30,163 @@ pub const RESTORE_SGRPROJ: u8 = 3;
pub const WIENER_TAPS_MIN: [i8; 3] = [ -5, -23, -17 ];
pub const WIENER_TAPS_MID: [i8; 3] = [ 3, -7, 15 ];
pub const WIENER_TAPS_MAX: [i8; 3] = [ 10, 8, 46 ];
pub const WIENER_TAPS_K: [i8; 3] = [ 1, 2, 3 ];
pub const SGRPROJ_XQD_MIN: [i8; 2] = [ -96, -32 ];
pub const SGRPROJ_XQD_MID: [i8; 2] = [ -32, 31 ];
pub const SGRPROJ_XQD_MAX: [i8; 2] = [ 31, 95 ];
pub const SGRPROJ_PRJ_SUBEXP_K: u8 = 4;
pub const SGRPROJ_PRJ_BITS: u8 = 7;
pub const SGRPROJ_PARAMS_BITS: u8 = 4;
pub const SGRPROJ_PARAMS_RADIUS: [[u8; 2]; 1 << SGRPROJ_PARAMS_BITS] = [
[2, 1], [2, 1], [2, 1], [2, 1],
[2, 1], [2, 1], [2, 1], [2, 1],
[2, 1], [2, 1], [0, 1], [0, 1],
[0, 1], [0, 1], [2, 0], [2, 0],
];
pub const SGRPROJ_PARAMS_EPS: [[u8; 2]; 1 << SGRPROJ_PARAMS_BITS] = [
[12, 4], [15, 6], [18, 8], [21, 9],
[24, 10], [29, 11], [36, 12], [45, 13],
[56, 14], [68, 15], [ 0, 5], [ 0, 8],
[ 0, 11], [ 0, 14], [30, 0], [75, 0],
];
#[derive(Copy, Clone)]
pub enum RestorationFilter {
None,
Wiener { coeffs: [[i8; 3]; 2] },
Sgrproj { set: i8,
xqd: [i8; 2] },
}
impl