Unverified Commit ea20e4eb authored by Monty Montgomery's avatar Monty Montgomery Committed by GitHub
Browse files

Cdef montywork (#391)

* Enable writing/using all possible CDEF setups

No RDO as yet-- this patch implements setting up, passing and
utilizing full cdef information

* Do not write CDEF frame or block data when cdef is disabled

This also requires passing Sequence structure deeper into RDO loop than before.
parent ce108dd6
......@@ -193,18 +193,7 @@ fn adjust_strength(strength: i32, var: i32) -> i32 {
pub fn cdef_frame(fi: &FrameInvariants, rec: &mut Frame, bc: &mut BlockContext) {
let bit_depth = 8;
let coeff_shift = bit_depth - 8;
let cdef_pri_y_strength = (fi.cdef_y_strength / CDEF_SEC_STRENGTHS) as i32;
let mut cdef_sec_y_strength = (fi.cdef_y_strength % CDEF_SEC_STRENGTHS) as i32;
let cdef_pri_uv_strength = (fi.cdef_uv_strength / CDEF_SEC_STRENGTHS) as i32;
let mut cdef_sec_uv_strength = (fi.cdef_uv_strength % CDEF_SEC_STRENGTHS) as i32;
if cdef_sec_y_strength == 3 {
cdef_sec_y_strength += 1;
}
if cdef_sec_uv_strength == 3 {
cdef_sec_uv_strength += 1;
}
let cdef_pri_damping = fi.cdef_damping as i32;
let cdef_sec_damping = cdef_pri_damping as i32;
let cdef_damping = fi.cdef_damping as i32;
// Each filter block is 64x64, except right and/or bottom for non-multiple-of-64 sizes.
// FIXME: 128x128 SB support will break this, we need FilterBlockOffset etc.
......@@ -263,62 +252,75 @@ pub fn cdef_frame(fi: &FrameInvariants, rec: &mut Frame, bc: &mut BlockContext)
for fby in 0..fb_height {
for fbx in 0..fb_width {
let sbo = SuperBlockOffset { x: fbx, y: fby };
// Each direction block is 8x8 in y, potentially smaller if subsampled in chroma
for by in 0..8 {
for bx in 0..8 {
let block_offset = sbo.block_offset(bx, by);
if block_offset.x < bc.cols && block_offset.y < bc.rows {
let mut dir = 0;
let mut var: i32 = 0;
let skip = bc.at(&block_offset).skip;
for p in 0..3 {
let mut rec_plane = &mut rec.planes[p];
let mut cdef_plane = &mut cdef_frame.planes[p];
let xdec = cdef_plane.cfg.xdec;
let ydec = cdef_plane.cfg.ydec;
let rec_stride = rec_plane.cfg.stride;
let rec_po = sbo.plane_offset(&rec_plane.cfg);
let mut rec_slice = &mut rec_plane.mut_slice(&rec_po);
let cdef_stride = cdef_plane.cfg.stride;
let cdef_po = sbo.plane_offset(&cdef_plane.cfg);
let cdef_slice = &cdef_plane.mut_slice(&cdef_po);
let mut local_pri_strength = 0;
let mut local_sec_strength = 0;
let mut local_pri_damping:i32 = cdef_pri_damping + coeff_shift;
let mut local_sec_damping:i32 = cdef_sec_damping + coeff_shift;
let mut local_dir:usize = 0;
if !skip {
if !skip {
let mut dir = 0;
let mut var: i32 = 0;
let cdef_index = bc.at(&block_offset).cdef_index;
let cdef_y_strength = fi.cdef_y_strengths[cdef_index as usize];
let cdef_uv_strength = fi.cdef_uv_strengths[cdef_index as usize];
let cdef_pri_y_strength = (cdef_y_strength / CDEF_SEC_STRENGTHS) as i32;
let mut cdef_sec_y_strength = (cdef_y_strength % CDEF_SEC_STRENGTHS) as i32;
let cdef_pri_uv_strength = (cdef_uv_strength / CDEF_SEC_STRENGTHS) as i32;
let mut cdef_sec_uv_strength = (cdef_uv_strength % CDEF_SEC_STRENGTHS) as i32;
if cdef_sec_y_strength == 3 {
cdef_sec_y_strength += 1;
}
if cdef_sec_uv_strength == 3 {
cdef_sec_uv_strength += 1;
}
for p in 0..3 {
let mut rec_plane = &mut rec.planes[p];
let mut cdef_plane = &mut cdef_frame.planes[p];
let xdec = cdef_plane.cfg.xdec;
let ydec = cdef_plane.cfg.ydec;
let rec_stride = rec_plane.cfg.stride;
let rec_po = sbo.plane_offset(&rec_plane.cfg);
let mut rec_slice = &mut rec_plane.mut_slice(&rec_po);
let cdef_stride = cdef_plane.cfg.stride;
let cdef_po = sbo.plane_offset(&cdef_plane.cfg);
let cdef_slice = &cdef_plane.mut_slice(&cdef_po);
let mut local_pri_strength;
let mut local_sec_strength;
let mut local_damping: i32 = cdef_damping + coeff_shift;
let mut local_dir: usize;
if p==0 {
dir = cdef_find_dir(cdef_slice.offset((8*bx>>xdec)+2,(8*by>>ydec)+2),
cdef_stride, &mut var, coeff_shift);
local_pri_strength = adjust_strength(cdef_pri_y_strength << coeff_shift, var);
local_sec_strength = cdef_sec_y_strength << coeff_shift;
local_dir = if cdef_pri_y_strength != 0 {dir as usize} else {0};
} else {
} else {
local_pri_strength = cdef_pri_uv_strength << coeff_shift;
local_sec_strength = cdef_sec_uv_strength << coeff_shift;
local_pri_damping -= 1;
local_sec_damping -= 1;
local_damping -= 1;
local_dir = if cdef_pri_uv_strength != 0 {dir as usize} else {0};
}
}
let mut xsize = (fi.padded_w as i32 - 8*bx as i32 >> xdec as i32) - rec_po.x as i32;
let mut ysize = (fi.padded_h as i32 - 8*by as i32 >> ydec as i32) - rec_po.y as i32;
if xsize > (8>>xdec) {
xsize = 8 >> xdec;
}
if ysize > (8>>ydec) {
ysize = 8 >> ydec;
}
if xsize > 0 && ysize > 0 {
cdef_filter_block(rec_slice.offset_as_mutable(8*bx>>xdec,8*by>>ydec), rec_stride as i32,
cdef_slice.offset(8*bx>>xdec,8*by>>ydec), cdef_stride as i32,
local_pri_strength, local_sec_strength, local_dir,
local_pri_damping, local_sec_damping,
xsize, ysize,
coeff_shift as i32);
let mut xsize = (fi.padded_w as i32 - 8*bx as i32 >> xdec as i32) - rec_po.x as i32;
let mut ysize = (fi.padded_h as i32 - 8*by as i32 >> ydec as i32) - rec_po.y as i32;
if xsize > (8>>xdec) {
xsize = 8 >> xdec;
}
if ysize > (8>>ydec) {
ysize = 8 >> ydec;
}
if xsize > 0 && ysize > 0 {
cdef_filter_block(rec_slice.offset_as_mutable(8*bx>>xdec,8*by>>ydec), rec_stride as i32,
cdef_slice.offset(8*bx>>xdec,8*by>>ydec), cdef_stride as i32,
local_pri_strength, local_sec_strength, local_dir,
local_damping, local_damping,
xsize, ysize,
coeff_shift as i32);
}
}
}
}
......
......@@ -1160,7 +1160,8 @@ pub struct Block {
pub mode: PredictionMode,
pub bsize: BlockSize,
pub partition: PartitionType,
pub skip: bool
pub skip: bool,
pub cdef_index: u8
}
impl Block {
......@@ -1169,7 +1170,8 @@ impl Block {
mode: PredictionMode::DC_PRED,
bsize: BlockSize::BLOCK_64X64,
partition: PartitionType::PARTITION_NONE,
skip: false
skip: false,
cdef_index: 0
}
}
pub fn is_inter(&self) -> bool {
......@@ -1186,6 +1188,7 @@ pub struct TXB_CTX {
pub struct BlockContext {
pub cols: usize,
pub rows: usize,
pub cdef_coded: bool,
above_partition_context: Vec<u8>,
left_partition_context: [u8; MAX_MIB_SIZE],
above_coeff_context: [Vec<u8>; PLANES],
......@@ -1201,6 +1204,7 @@ impl BlockContext {
BlockContext {
cols,
rows,
cdef_coded: false,
above_partition_context: vec![0; aligned_cols],
left_partition_context: [0; MAX_MIB_SIZE],
above_coeff_context: [
......@@ -1217,6 +1221,7 @@ impl BlockContext {
BlockContext {
cols: self.cols,
rows: self.rows,
cdef_coded: self.cdef_coded,
above_partition_context: self.above_partition_context.clone(),
left_partition_context: self.left_partition_context,
above_coeff_context: self.above_coeff_context.clone(),
......@@ -1228,6 +1233,7 @@ impl BlockContext {
pub fn rollback(&mut self, checkpoint: &BlockContext) {
self.cols = checkpoint.cols;
self.rows = checkpoint.rows;
self.cdef_coded = checkpoint.cdef_coded;
self.above_partition_context = checkpoint.above_partition_context.clone();
self.left_partition_context = checkpoint.left_partition_context;
self.above_coeff_context = checkpoint.above_coeff_context.clone();
......@@ -1421,6 +1427,17 @@ impl BlockContext {
}
}
pub fn set_cdef(&mut self, bo: &BlockOffset, bsize: BlockSize, cdef_index: u8) {
let bw = bsize.width_mi();
let bh = bsize.height_mi();
for y in 0..bh {
for x in 0..bw {
self.blocks[bo.y + y as usize][bo.x + x as usize].cdef_index = cdef_index;
}
}
}
// The mode info data structure has a one element border above and to the
// left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0.
......@@ -1818,6 +1835,20 @@ impl ContextWriter {
let ctx = self.bc.skip_context(bo);
symbol!(self, skip as u32, &mut self.fc.skip_cdfs[ctx]);
}
pub fn write_block_cdef(&mut self, bo: &BlockOffset, skip: bool, strength_index: u8, bits: u8) {
// Starting a new superblock-- we have to keep track as we don't code
// a cdef strength until the first non-skip block
let block_mask = (1<<SUPERBLOCK_TO_BLOCK_SHIFT) - 1;
if (bo.x & block_mask) == 0 && (bo.y & block_mask) == 0 {
self.bc.cdef_coded = false;
}
if !self.bc.cdef_coded && !skip {
self.bc.cdef_coded = true;
self.w.literal(bits, strength_index as u32);
}
}
pub fn write_is_inter(&mut self, bo: &BlockOffset, is_inter: bool) {
let ctx = self.bc.intra_inter_context(bo);
symbol!(self, is_inter as u32, &mut self.fc.intra_inter_cdfs[ctx]);
......
......@@ -333,10 +333,17 @@ impl Writer {
self.cdf(s, &cdf[..nsymbs]);
Writer::update_cdf(cdf, s);
}
pub fn bit(&mut self, bit: u16) {
self.enc.od_ec_encode_bool_q15(bit == 1, 16384);
}
pub fn literal(&mut self, bits: u8, s: u32) {
for bit in (0..bits).rev() {
self.enc.od_ec_encode_bool_q15((1 & (s >> bit)) == 1, 16384);
}
}
pub fn write_golomb(&mut self, level: u16) {
let x = level + 1;
let mut i = x;
......
......@@ -292,8 +292,8 @@ pub struct FrameInvariants {
pub allow_warped_motion: bool,
pub cdef_damping: u8,
pub cdef_bits: u8,
pub cdef_y_strength: u8,
pub cdef_uv_strength: u8,
pub cdef_y_strengths: [u8; 8],
pub cdef_uv_strengths: [u8; 8],
pub config: EncoderConfig,
}
......@@ -344,9 +344,9 @@ impl FrameInvariants {
disable_frame_end_update_cdf: true,
allow_warped_motion: true,
cdef_damping: 3,
cdef_bits: 0,
cdef_y_strength: 7*4+3,
cdef_uv_strength: 7*4+3,
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],
config,
}
}
......@@ -564,7 +564,7 @@ trait UncompressedHeader {
fn write_bitdepth_colorspace_sampling(&mut self) -> Result<(), std::io::Error>;
fn write_frame_setup(&mut self) -> Result<(), std::io::Error>;
fn write_loop_filter(&mut self) -> Result<(), std::io::Error>;
fn write_cdef(&mut self, fi: &FrameInvariants) -> Result<(), std::io::Error>;
fn write_frame_cdef(&mut self, seq: &Sequence, fi: &FrameInvariants) -> Result<(), std::io::Error>;
}
#[allow(unused)]
const OP_POINTS_IDC_BITS:usize = 12;
......@@ -977,7 +977,7 @@ impl<'a> UncompressedHeader for BitWriter<'a, BE> {
// loop filter
self.write_loop_filter()?;
// cdef
self.write_cdef(fi)?;
self.write_frame_cdef(seq, fi)?;
// loop restoration
// If seq.enable_restoration is false, don't signal about loop restoration
if seq.enable_restoration {
......@@ -1099,17 +1099,19 @@ impl<'a> UncompressedHeader for BitWriter<'a, BE> {
self.write(3,0)?; // loop filter sharpness
self.write_bit(false) // loop filter deltas enabled
}
fn write_cdef(&mut self, fi: &FrameInvariants) -> Result<(), std::io::Error> {
assert!(fi.cdef_damping >= 3);
assert!(fi.cdef_damping <= 6);
self.write(2, fi.cdef_damping - 3)?;
assert!(fi.cdef_bits == 0); // temporary limitation
self.write(2,fi.cdef_bits)?; // cdef bits
for _ in 0..1 {
assert!(fi.cdef_y_strength<64);
assert!(fi.cdef_uv_strength<64);
self.write(6,fi.cdef_y_strength)?; // cdef y strength
self.write(6,fi.cdef_uv_strength)?; // cdef uv strength
fn write_frame_cdef(&mut self, seq: &Sequence, fi: &FrameInvariants) -> Result<(), std::io::Error> {
if seq.enable_cdef {
assert!(fi.cdef_damping >= 3);
assert!(fi.cdef_damping <= 6);
self.write(2, fi.cdef_damping - 3)?;
assert!(fi.cdef_bits < 4);
self.write(2,fi.cdef_bits)?; // cdef bits
for i in 0..(1<<fi.cdef_bits) {
assert!(fi.cdef_y_strengths[i]<64);
assert!(fi.cdef_uv_strengths[i]<64);
self.write(6,fi.cdef_y_strengths[i])?; // cdef y strength
self.write(6,fi.cdef_uv_strengths[i])?; // cdef uv strength
}
}
Ok(())
}
......@@ -1245,7 +1247,7 @@ fn write_obus(packet: &mut Write, sequence: &mut Sequence,
let write_frame_header = fi.num_tg > 1 || fi.show_existing_frame;
let mut buf2 = Vec::new();
{
write_uncompressed_header(&mut buf2, fi)?;
write_uncompressed_header(&mut buf2, sequence, fi)?;
}
let obu_payload_size = buf2.len() as u64;
{
......@@ -1274,7 +1276,8 @@ fn write_obus(packet: &mut Write, sequence: &mut Sequence,
}
fn write_uncompressed_header(packet: &mut Write,
fi: &FrameInvariants) -> Result<(), std::io::Error> {
seq: &Sequence,
fi: &FrameInvariants) -> Result<(), std::io::Error> {
let mut bw = BitWriter::<BE>::new(packet);
if fi.show_existing_frame {
bw.write_bit(true)?; // show_existing_frame=1
......@@ -1329,7 +1332,7 @@ fn write_uncompressed_header(packet: &mut Write,
bw.write_bit(false)?; // no qm
bw.write_bit(false)?; // segmentation off
bw.write_bit(false)?; // no delta q
bw.write_cdef(fi)?;
bw.write_frame_cdef(seq, fi)?;
bw.write(6,0)?; // no y, u or v loop restoration
bw.write_bit(false)?; // tx mode select
......@@ -1437,13 +1440,17 @@ pub fn encode_tx_block(fi: &FrameInvariants, fs: &mut FrameState, cw: &mut Conte
inverse_transform_add(&rcoeffs.array, &mut rec.mut_slice(po).as_mut_slice(), stride, tx_size, tx_type);
}
fn encode_block(fi: &FrameInvariants, fs: &mut FrameState, cw: &mut ContextWriter,
fn encode_block(seq: &Sequence, fi: &FrameInvariants, fs: &mut FrameState, cw: &mut ContextWriter,
luma_mode: PredictionMode, chroma_mode: PredictionMode,
bsize: BlockSize, bo: &BlockOffset, skip: bool) {
bsize: BlockSize, bo: &BlockOffset, skip: bool, cdef_index: u8) {
let is_inter = luma_mode >= PredictionMode::NEARESTMV;
cw.bc.set_skip(bo, bsize, skip);
cw.write_skip(bo, skip);
if seq.enable_cdef {
cw.bc.set_cdef(bo, bsize, cdef_index);
cw.write_block_cdef(bo, skip, cdef_index, fi.cdef_bits);
}
if fi.frame_type == FrameType::INTER {
cw.write_is_inter(bo, is_inter);
......@@ -1575,8 +1582,8 @@ pub fn write_tx_blocks(fi: &FrameInvariants, fs: &mut FrameState, cw: &mut Conte
}
}
fn encode_partition_bottomup(fi: &FrameInvariants, fs: &mut FrameState, cw: &mut ContextWriter,
bsize: BlockSize, bo: &BlockOffset) -> f64 {
fn encode_partition_bottomup(seq: &Sequence, fi: &FrameInvariants, fs: &mut FrameState, cw: &mut ContextWriter,
bsize: BlockSize, bo: &BlockOffset) -> f64 {
let mut rd_cost = std::f64::MAX;
if bo.x >= cw.bc.cols || bo.y >= cw.bc.rows {
......@@ -1606,6 +1613,7 @@ bsize: BlockSize, bo: &BlockOffset) -> f64 {
let mut subsize: BlockSize;
let checkpoint = cw.checkpoint();
let cdef_index = 5; // The hardwired cdef index is temporary
// Code the whole block
if !must_split {
......@@ -1614,13 +1622,12 @@ bsize: BlockSize, bo: &BlockOffset) -> f64 {
if bsize >= BlockSize::BLOCK_8X8 {
cw.write_partition(bo, partition, bsize);
}
let mode_decision = rdo_mode_decision(fi, fs, cw, bsize, bo).part_modes[0].clone();
let mode_decision = rdo_mode_decision(seq, fi, fs, cw, bsize, bo, cdef_index).part_modes[0].clone();
let (mode_luma, mode_chroma) = (mode_decision.pred_mode_luma, mode_decision.pred_mode_chroma);
let skip = mode_decision.skip;
rd_cost = mode_decision.rd_cost;
encode_block(fi, fs, cw, mode_luma, mode_chroma, bsize, bo, skip);
encode_block(seq, fi, fs, cw, mode_luma, mode_chroma, bsize, bo, skip, cdef_index);
best_decision = mode_decision;
}
......@@ -1638,10 +1645,10 @@ bsize: BlockSize, bo: &BlockOffset) -> f64 {
cw.write_partition(bo, partition, bsize);
}
rd_cost = encode_partition_bottomup(fi, fs, cw, subsize, bo);
rd_cost += encode_partition_bottomup(fi, fs, cw, subsize, &BlockOffset { x: bo.x + hbs as usize, y: bo.y });
rd_cost += encode_partition_bottomup(fi, fs, cw, subsize, &BlockOffset { x: bo.x, y: bo.y + hbs as usize });
rd_cost += encode_partition_bottomup(fi, fs, cw, subsize, &BlockOffset { x: bo.x + hbs as usize, y: bo.y + hbs as usize });
rd_cost = encode_partition_bottomup(seq, fi, fs, cw, subsize, bo);
rd_cost += encode_partition_bottomup(seq, fi, fs, cw, subsize, &BlockOffset { x: bo.x + hbs as usize, y: bo.y });
rd_cost += encode_partition_bottomup(seq, fi, fs, cw, subsize, &BlockOffset { x: bo.x, y: bo.y + hbs as usize });
rd_cost += encode_partition_bottomup(seq, fi, fs, cw, subsize, &BlockOffset { x: bo.x + hbs as usize, y: bo.y + hbs as usize });
// Recode the full block if it is more efficient
if !must_split && nosplit_rd_cost < rd_cost {
......@@ -1656,7 +1663,7 @@ bsize: BlockSize, bo: &BlockOffset) -> f64 {
// FIXME: redundant block re-encode
let (mode_luma, mode_chroma) = (best_decision.pred_mode_luma, best_decision.pred_mode_chroma);
let skip = best_decision.skip;
encode_block(fi, fs, cw, mode_luma, mode_chroma, bsize, bo, skip);
encode_block(seq, fi, fs, cw, mode_luma, mode_chroma, bsize, bo, skip, cdef_index);
}
}
......@@ -1670,7 +1677,7 @@ bsize: BlockSize, bo: &BlockOffset) -> f64 {
rd_cost
}
fn encode_partition_topdown(fi: &FrameInvariants, fs: &mut FrameState, cw: &mut ContextWriter,
fn encode_partition_topdown(seq: &Sequence, fi: &FrameInvariants, fs: &mut FrameState, cw: &mut ContextWriter,
bsize: BlockSize, bo: &BlockOffset, block_output: &Option<RDOOutput>) {
if bo.x >= cw.bc.cols || bo.y >= cw.bc.rows {
......@@ -1690,13 +1697,14 @@ fn encode_partition_topdown(fi: &FrameInvariants, fs: &mut FrameState, cw: &mut
part_modes: std::vec::Vec::new()
});
let partition: PartitionType;
let cdef_index = 5; // The hardwired cdef index is temporary
if must_split {
// Oversized blocks are split automatically
partition = PartitionType::PARTITION_SPLIT;
} else if bsize > fi.min_partition_size {
// Blocks of sizes within the supported range are subjected to a partitioning decision
rdo_output = rdo_partition_decision(fi, fs, cw, bsize, bo, &rdo_output);
rdo_output = rdo_partition_decision(seq, fi, fs, cw, bsize, bo, &rdo_output, cdef_index);
partition = rdo_output.part_type;
} else {
// Blocks of sizes below the supported range are encoded directly
......@@ -1721,14 +1729,14 @@ fn encode_partition_topdown(fi: &FrameInvariants, fs: &mut FrameState, cw: &mut
rdo_output.part_modes[0].clone()
} else {
// Make a prediction mode decision for blocks encoded with no rdo_partition_decision call (e.g. edges)
rdo_mode_decision(fi, fs, cw, bsize, bo).part_modes[0].clone()
rdo_mode_decision(seq, fi, fs, cw, bsize, bo, cdef_index).part_modes[0].clone()
};
let (mode_luma, mode_chroma) = (part_decision.pred_mode_luma, part_decision.pred_mode_chroma);
let skip = part_decision.skip;
// FIXME: every final block that has gone through the RDO decision process is encoded twice
encode_block(fi, fs, cw, mode_luma, mode_chroma, bsize, bo, skip);
encode_block(seq, fi, fs, cw, mode_luma, mode_chroma, bsize, bo, skip, cdef_index);
},
PartitionType::PARTITION_SPLIT => {
if rdo_output.part_modes.len() >= 4 {
......@@ -1739,7 +1747,7 @@ fn encode_partition_topdown(fi: &FrameInvariants, fs: &mut FrameState, cw: &mut
let offset = mode.bo.clone();
// Each block is subjected to a new splitting decision
encode_partition_topdown(fi, fs, cw, subsize, &offset,
encode_partition_topdown(seq, fi, fs, cw, subsize, &offset,
&Some(RDOOutput {
rd_cost: mode.rd_cost,
part_type: PartitionType::PARTITION_NONE,
......@@ -1747,10 +1755,10 @@ fn encode_partition_topdown(fi: &FrameInvariants, fs: &mut FrameState, cw: &mut
}
}
else {
encode_partition_topdown(fi, fs, cw, subsize, bo, &None);
encode_partition_topdown(fi, fs, cw, subsize, &BlockOffset{x: bo.x + hbs as usize, y: bo.y}, &None);
encode_partition_topdown(fi, fs, cw, subsize, &BlockOffset{x: bo.x, y: bo.y + hbs as usize}, &None);
encode_partition_topdown(fi, fs, cw, subsize, &BlockOffset{x: bo.x + hbs as usize, y: bo.y + hbs as usize}, &None);
encode_partition_topdown(seq, fi, fs, cw, subsize, bo, &None);
encode_partition_topdown(seq, fi, fs, cw, subsize, &BlockOffset{x: bo.x + hbs as usize, y: bo.y}, &None);
encode_partition_topdown(seq, fi, fs, cw, subsize, &BlockOffset{x: bo.x, y: bo.y + hbs as usize}, &None);
encode_partition_topdown(seq, fi, fs, cw, subsize, &BlockOffset{x: bo.x + hbs as usize, y: bo.y + hbs as usize}, &None);
}
},
_ => { assert!(false); },
......@@ -1762,7 +1770,7 @@ fn encode_partition_topdown(fi: &FrameInvariants, fs: &mut FrameState, cw: &mut
}
}
fn encode_tile(fi: &FrameInvariants, fs: &mut FrameState) -> Vec<u8> {
fn encode_tile(sequence: &mut Sequence, fi: &FrameInvariants, fs: &mut FrameState) -> Vec<u8> {
let w = ec::Writer::new();
let fc = CDFContext::new(fi.config.quantizer as u8);
let bc = BlockContext::new(fi.w_in_b, fi.h_in_b);
......@@ -1777,15 +1785,17 @@ fn encode_tile(fi: &FrameInvariants, fs: &mut FrameState) -> Vec<u8> {
// Encode SuperBlock
if fi.config.speed == 0 {
encode_partition_bottomup(fi, fs, &mut cw, BlockSize::BLOCK_64X64, &bo);
encode_partition_bottomup(sequence, fi, fs, &mut cw, BlockSize::BLOCK_64X64, &bo);
}
else {
encode_partition_topdown(fi, fs, &mut cw, BlockSize::BLOCK_64X64, &bo, &None);
encode_partition_topdown(sequence, fi, fs, &mut cw, BlockSize::BLOCK_64X64, &bo, &None);
}
}
}
/* TODO: Don't apply if lossless */
cdef_frame(fi, &mut fs.rec, &mut cw.bc);
if sequence.enable_cdef {
cdef_frame(fi, &mut fs.rec, &mut cw.bc);
}
let mut h = cw.w.done();
h.push(0); // superframe anti emulation
h
......@@ -1815,7 +1825,7 @@ fn encode_frame(sequence: &mut Sequence, fi: &mut FrameInvariants, fs: &mut Fram
None => (),
}
} else {
let tile = encode_tile(fi, fs); // actually tile group
let tile = encode_tile(sequence, fi, fs); // actually tile group
let obu_payload_size = tile.len() as u64;
let mut buf1 = Vec::new();
{
......
......@@ -27,6 +27,7 @@ use FrameInvariants;
use FrameState;
use FrameType;
use Tune;
use Sequence;
#[derive(Clone)]
pub struct RDOOutput {
......@@ -162,8 +163,8 @@ fn compute_rd_cost(
// RDO-based mode decision
pub fn rdo_mode_decision(
fi: &FrameInvariants, fs: &mut FrameState, cw: &mut ContextWriter,
bsize: BlockSize, bo: &BlockOffset
seq: &Sequence, fi: &FrameInvariants, fs: &mut FrameState, cw: &mut ContextWriter,
bsize: BlockSize, bo: &BlockOffset, cdef_index: u8
) -> RDOOutput {
let mut best_mode_luma = PredictionMode::DC_PRED;
let mut best_mode_chroma = PredictionMode::DC_PRED;
......@@ -211,7 +212,7 @@ pub fn rdo_mode_decision(
if is_chroma_block && fi.config.speed <= 3 {
// Find the best chroma prediction mode for the current luma prediction mode
for &chroma_mode in RAV1E_INTRA_MODES {
encode_block(fi, fs, cw, luma_mode, chroma_mode, bsize, bo, skip);
encode_block(seq, fi, fs, cw, luma_mode, chroma_mode, bsize, bo, skip, cdef_index);
let cost = cw.w.tell_frac() - tell;
let rd = compute_rd_cost(
......@@ -237,7 +238,7 @@ pub fn rdo_mode_decision(
cw.rollback(&checkpoint);
}
} else {
encode_block(fi, fs, cw, luma_mode, luma_mode, bsize, bo, skip);
encode_block(seq, fi, fs, cw, luma_mode, luma_mode, bsize, bo, skip, cdef_index);
let cost = cw.w.tell_frac() - tell;
let rd = compute_rd_cost(
......@@ -347,8 +348,8 @@ pub fn rdo_tx_type_decision(
// RDO-based single level partitioning decision
pub fn rdo_partition_decision(
fi: &FrameInvariants, fs: &mut FrameState, cw: &mut ContextWriter,
bsize: BlockSize, bo: &BlockOffset, cached_block: &RDOOutput
seq: &Sequence, fi: &FrameInvariants, fs: &mut FrameState, cw: &mut ContextWriter,
bsize: BlockSize, bo: &BlockOffset, cached_block: &RDOOutput, cdef_index: u8
) -> RDOOutput {
let max_rd = std::f64::MAX;
......@@ -376,7 +377,7 @@ pub fn rdo_partition_decision(
let mode_decision = cached_block
.part_modes
.get(0)
.unwrap_or(&rdo_mode_decision(fi, fs, cw, bsize, bo).part_modes[0])
.unwrap_or(&rdo_mode_decision(seq, fi, fs, cw, bsize, bo, cdef_index).part_modes[0])
.clone();
child_modes.push(mode_decision);
}
......@@ -391,26 +392,26 @@ pub fn rdo_partition_decision(
let hbs = bs >> 1; // Half the block size in blocks
let offset = BlockOffset { x: bo.x, y: bo.y };
let mode_decision = rdo_mode_decision(fi, fs, cw, subsize, &offset)
let mode_decision = rdo_mode_decision(seq, fi, fs, cw, subsize, &offset, cdef_index)
.part_modes[0]
.clone();
child_modes.push(mode_decision);
let offset = BlockOffset { x: bo.x + hbs as usize, y: bo.y };
let mode_decision = rdo_mode_decision(fi, fs, cw, subsize, &offset)
let mode_decision = rdo_mode_decision(seq, fi, fs, cw, subsize, &offset, cdef_index)
.part_modes[0]
.clone();
child_modes.push(mode_decision);
let offset