diff --git a/.travis.yml b/.travis.yml index 0a6c06accb..dfd43e4ac2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,7 +51,7 @@ jobs: - cargo install cargo-kcov - kcov --version - RUSTFLAGS="-C link-dead-code" cargo build --features=decode_test,quick_test --tests --verbose - - cargo kcov -v --coveralls --no-clean-rebuild -- --verify --exclude-pattern=$HOME/.cargo,aom_build,.h,test + - travis_wait cargo kcov -v --coveralls --no-clean-rebuild -- --verify --exclude-pattern=$HOME/.cargo,aom_build,.h,test - name: "Tests" script: cargo test --verbose --release --features=decode_test -- --ignored - name: "Bench" diff --git a/src/context.rs b/src/context.rs index 3ba2ba7914..93a12b55d2 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1227,6 +1227,15 @@ impl BlockOffset { } } + /// Convert to plane offset without decimation + #[inline] + pub fn to_luma_plane_offset(self) -> PlaneOffset { + PlaneOffset { + x: (self.x as isize) << BLOCK_TO_PLANE_SHIFT, + y: (self.y as isize) << BLOCK_TO_PLANE_SHIFT, + } + } + pub fn y_in_sb(self) -> usize { self.y % MAX_MIB_SIZE } @@ -1251,10 +1260,10 @@ pub struct Block { pub mv: [MotionVector; 2], pub neighbors_ref_counts: [usize; TOTAL_REFS_PER_FRAME], pub cdef_index: u8, + pub bsize: BlockSize, pub n4_w: usize, /* block width in the unit of mode_info */ pub n4_h: usize, /* block height in the unit of mode_info */ - pub tx_w: usize, /* transform width in the unit of mode_info */ - pub tx_h: usize, /* transform height in the unit of mode_info */ + pub txsize: TxSize, // The block-level deblock_deltas are left-shifted by // fi.deblock.block_delta_shift and added to the frame-configured // deltas @@ -1272,10 +1281,10 @@ impl Block { mv: [ MotionVector::default(); 2], neighbors_ref_counts: [0; TOTAL_REFS_PER_FRAME], cdef_index: 0, + bsize: BLOCK_64X64, n4_w: BLOCK_64X64.width_mi(), n4_h: BLOCK_64X64.height_mi(), - tx_w: TX_64X64.width_mi(), - tx_h: TX_64X64.height_mi(), + txsize: TX_64X64, deblock_deltas: [0, 0, 0, 0], segmentation_idx: 0, } @@ -1539,13 +1548,11 @@ impl BlockContext { pub fn set_block_size(&mut self, bo: BlockOffset, bsize: BlockSize) { let n4_w = bsize.width_mi(); let n4_h = bsize.height_mi(); - self.for_each(bo, bsize, |block| { block.n4_w = n4_w; block.n4_h = n4_h } ); + self.for_each(bo, bsize, |block| { block.bsize = bsize; block.n4_w = n4_w; block.n4_h = n4_h } ); } - pub fn set_tx_size(&mut self, bo: BlockOffset, bsize: BlockSize, txsize: TxSize) { - let tx_w = txsize.width_mi(); - let tx_h = txsize.height_mi(); - self.for_each(bo, bsize, |block| { block.tx_w = tx_w; block.tx_h = tx_h } ); + pub fn set_tx_size(&mut self, bo: BlockOffset, bsize: BlockSize, tx_size: TxSize) { + self.for_each(bo, bsize, |block| { block.txsize = tx_size } ); } pub fn get_mode(&mut self, bo: BlockOffset) -> PredictionMode { diff --git a/src/deblock.rs b/src/deblock.rs index ca764efc3c..4219e32b31 100644 --- a/src/deblock.rs +++ b/src/deblock.rs @@ -126,15 +126,19 @@ fn deblock_size( { 0 } else { - let (tx_size, prev_tx_size) = if vertical { - (cmp::max(block.tx_w >> xdec, 1), cmp::max(prev_block.tx_w >> xdec, 1)) + let (txsize, prev_txsize) = if pli==0 { + (block.txsize, prev_block.txsize) } else { - (cmp::max(block.tx_h >> ydec, 1), cmp::max(prev_block.tx_h >> ydec, 1)) + (block.bsize.largest_uv_tx_size(xdec, ydec), prev_block.bsize.largest_uv_tx_size(xdec, ydec)) + }; + let (tx_n, prev_tx_n) = if vertical { + (cmp::max(txsize.width_mi(), 1), cmp::max(prev_txsize.width_mi(), 1)) + } else { + (cmp::max(txsize.height_mi(), 1), cmp::max(prev_txsize.height_mi(), 1)) }; - cmp::min( if pli == 0 { 14 } else { 6 }, - cmp::min(tx_size, prev_tx_size) << MI_SIZE_LOG2 + cmp::min(tx_n, prev_tx_n) << MI_SIZE_LOG2 ) } } @@ -1023,10 +1027,11 @@ fn sse_size14( fn filter_v_edge( deblock: &DeblockState, bc: &BlockContext, bo: BlockOffset, p: &mut Plane, - pli: usize, bd: usize + pli: usize, bd: usize, xdec: usize, ydec: usize ) { let block = bc.at(bo); - let tx_edge = bo.x & (block.tx_w - 1) == 0; + let txsize = if pli==0 { block.txsize } else { block.bsize.largest_uv_tx_size(xdec, ydec) }; + let tx_edge = bo.x >> xdec & (txsize.width_mi() - 1) == 0; if tx_edge { let prev_block = deblock_left(bc, bo, p); let block_edge = bo.x & (block.n4_w - 1) == 0; @@ -1060,10 +1065,11 @@ fn filter_v_edge( fn sse_v_edge( bc: &BlockContext, bo: BlockOffset, rec_plane: &Plane, src_plane: &Plane, - tally: &mut [i64; MAX_LOOP_FILTER + 2], pli: usize, bd: usize + tally: &mut [i64; MAX_LOOP_FILTER + 2], pli: usize, bd: usize, xdec: usize, ydec: usize ) { let block = bc.at(bo); - let tx_edge = bo.x & (block.tx_w - 1) == 0; + let txsize = if pli==0 { block.txsize } else { block.bsize.largest_uv_tx_size(xdec, ydec) }; + let tx_edge = bo.x >> xdec & (txsize.width_mi() - 1) == 0; if tx_edge { let prev_block = deblock_left(bc, bo, rec_plane); let block_edge = bo.x & (block.n4_w - 1) == 0; @@ -1126,10 +1132,11 @@ fn sse_v_edge( fn filter_h_edge( deblock: &DeblockState, bc: &BlockContext, bo: BlockOffset, p: &mut Plane, - pli: usize, bd: usize + pli: usize, bd: usize, xdec: usize, ydec: usize ) { let block = bc.at(bo); - let tx_edge = bo.y & (block.tx_h - 1) == 0; + let txsize = if pli==0 { block.txsize } else { block.bsize.largest_uv_tx_size(xdec, ydec) }; + let tx_edge = bo.y >> ydec & (txsize.height_mi() - 1) == 0; if tx_edge { let prev_block = deblock_up(bc, bo, p); let block_edge = bo.y & (block.n4_h - 1) == 0; @@ -1163,10 +1170,11 @@ fn filter_h_edge( fn sse_h_edge( bc: &BlockContext, bo: BlockOffset, rec_plane: &Plane, src_plane: &Plane, - tally: &mut [i64; MAX_LOOP_FILTER + 2], pli: usize, bd: usize + tally: &mut [i64; MAX_LOOP_FILTER + 2], pli: usize, bd: usize, xdec: usize, ydec: usize ) { let block = bc.at(bo); - let tx_edge = bo.y & (block.tx_h - 1) == 0; + let txsize = if pli==0 { block.txsize } else { block.bsize.largest_uv_tx_size(xdec, ydec) }; + let tx_edge = bo.y >> ydec & (txsize.height_mi() - 1) == 0; if tx_edge { let prev_block = deblock_up(bc, bo, rec_plane); let block_edge = bo.y & (block.n4_h - 1) == 0; @@ -1256,7 +1264,7 @@ pub fn deblock_plane( // edge). Unroll to avoid corner-cases. if bc.rows > 0 { for x in (1 << xdec..bc.cols).step_by(1 << xdec) { - filter_v_edge(deblock, bc, BlockOffset { x, y: 0 }, p, pli, bd); + filter_v_edge(deblock, bc, BlockOffset { x, y: 0 }, p, pli, bd, xdec, ydec); } if bc.rows > 1 << ydec { for x in (1 << xdec..bc.cols).step_by(1 << xdec) { @@ -1266,7 +1274,9 @@ pub fn deblock_plane( BlockOffset { x, y: 1 << ydec }, p, pli, - bd + bd, + xdec, + ydec ); } } @@ -1277,19 +1287,21 @@ pub fn deblock_plane( for y in ((2 << ydec)..bc.rows).step_by(1 << ydec) { // Check for vertical edge at first MI block boundary on this row if 1 << xdec < bc.cols { - filter_v_edge(deblock, bc, BlockOffset { x: 1 << xdec, y }, p, pli, bd); + filter_v_edge(deblock, bc, BlockOffset { x: 1 << xdec, y }, p, pli, bd, xdec, ydec); } // run the rest of the row with both vertical and horizontal edge filtering. // Horizontal lags vertical edge by one row and two columns. for x in (2 << xdec..bc.cols).step_by(1 << xdec) { - filter_v_edge(deblock, bc, BlockOffset { x, y }, p, pli, bd); + filter_v_edge(deblock, bc, BlockOffset { x, y }, p, pli, bd, xdec, ydec); filter_h_edge( deblock, bc, BlockOffset { x: x - (2 << xdec), y: y - (1 << ydec) }, p, pli, - bd + bd, + xdec, + ydec ); } // ..and the last two horizontal edges for the row @@ -1300,7 +1312,9 @@ pub fn deblock_plane( BlockOffset { x: bc.cols - (2 << xdec), y: y - (1 << ydec) }, p, pli, - bd + bd, + xdec, + ydec ); if bc.cols - (1 << xdec) > 0 { filter_h_edge( @@ -1309,7 +1323,9 @@ pub fn deblock_plane( BlockOffset { x: bc.cols - (1 << xdec), y: y - (1 << ydec) }, p, pli, - bd + bd, + xdec, + ydec ); } } @@ -1324,7 +1340,9 @@ pub fn deblock_plane( BlockOffset { x, y: bc.rows - (1 << ydec) }, p, pli, - bd + bd, + xdec, + ydec ); } } @@ -1341,7 +1359,7 @@ fn sse_plane( // No horizontal edge filtering along top of frame for x in (1 << xdec..bc.cols).step_by(1 << xdec) { - sse_v_edge(bc, BlockOffset { x, y: 0 }, rec, src, v_sse, pli, bd); + sse_v_edge(bc, BlockOffset { x, y: 0 }, rec, src, v_sse, pli, bd, xdec, ydec); } // Unlike actual filtering, we're counting horizontal and vertical @@ -1349,10 +1367,10 @@ fn sse_plane( // behind vertical. for y in (1 << ydec..bc.rows).step_by(1 << ydec) { // No vertical filtering along left edge of frame - sse_h_edge(bc, BlockOffset { x: 0, y }, rec, src, h_sse, pli, bd); + sse_h_edge(bc, BlockOffset { x: 0, y }, rec, src, h_sse, pli, bd, xdec, ydec); for x in (1 << xdec..bc.cols).step_by(1 << xdec) { - sse_v_edge(bc, BlockOffset { x, y }, rec, src, v_sse, pli, bd); - sse_h_edge(bc, BlockOffset { x, y }, rec, src, h_sse, pli, bd); + sse_v_edge(bc, BlockOffset { x, y }, rec, src, v_sse, pli, bd, xdec, ydec); + sse_h_edge(bc, BlockOffset { x, y }, rec, src, h_sse, pli, bd, xdec, ydec); } } } diff --git a/src/encoder.rs b/src/encoder.rs index 87ee7c1476..760073576d 100644 --- a/src/encoder.rs +++ b/src/encoder.rs @@ -2176,11 +2176,6 @@ fn encode_tile(fi: &FrameInvariants, fs: &mut FrameState) -> Vec /* TODO: Don't apply if lossless */ deblock_filter_optimize(fi, fs, &mut cw.bc); - // NOTE(yushin): Temporarilly, disable deblocking-filter - // because it causes mismatch btw encoder and decoder when transform partition is enabled. - fs.deblock.levels[0] = 0; - fs.deblock.levels[1] = 0; - if fs.deblock.levels[0] != 0 || fs.deblock.levels[1] != 0 { deblock_filter_frame(fs, &mut cw.bc, fi.sequence.bit_depth); } diff --git a/src/me.rs b/src/me.rs index 91163989dc..2f43271289 100644 --- a/src/me.rs +++ b/src/me.rs @@ -337,7 +337,7 @@ pub fn get_subset_predictors( pub trait MotionEstimation { fn full_pixel_me( - fi: &FrameInvariants, fs: &FrameState, rec: &Arc>, po: PlaneOffset, + fi: &FrameInvariants, fs: &FrameState, rec: &Arc>, bo: BlockOffset, lambda: u32, cmv: MotionVector, pmv: [MotionVector; 2], mvx_min: isize, mvx_max: isize, mvy_min: isize, mvy_max: isize, @@ -346,7 +346,7 @@ pub trait MotionEstimation { ); fn sub_pixel_me( - fi: &FrameInvariants, fs: &FrameState, rec: &Arc>, po: PlaneOffset, + fi: &FrameInvariants, fs: &FrameState, rec: &Arc>, bo: BlockOffset, lambda: u32, pmv: [MotionVector; 2], mvx_min: isize, mvx_max: isize, mvy_min: isize, mvy_max: isize, blk_w: usize, blk_h: usize, best_mv: &mut MotionVector, @@ -362,10 +362,6 @@ pub trait MotionEstimation { match fi.rec_buffer.frames[fi.ref_frames[ref_frame - LAST_FRAME] as usize] { Some(ref rec) => { - let po = PlaneOffset { - x: (bo.x as isize) << BLOCK_TO_PLANE_SHIFT, - y: (bo.y as isize) << BLOCK_TO_PLANE_SHIFT - }; let blk_w = bsize.width(); let blk_h = bsize.height(); let (mvx_min, mvx_max, mvy_min, mvy_max) = @@ -379,12 +375,12 @@ pub trait MotionEstimation { let mut lowest_cost = std::u64::MAX; let mut best_mv = MotionVector::default(); - Self::full_pixel_me(fi, fs, rec, po, bo, lambda, cmv, pmv, + Self::full_pixel_me(fi, fs, rec, bo, lambda, cmv, pmv, mvx_min, mvx_max, mvy_min, mvy_max, blk_w, blk_h, &mut best_mv, &mut lowest_cost, ref_frame); let tmp_plane = Plane::new(blk_w, blk_h, 0, 0, 0, 0); - Self::sub_pixel_me(fi, fs, rec, po, bo, lambda, pmv, + Self::sub_pixel_me(fi, fs, rec, bo, lambda, pmv, mvx_min, mvx_max, mvy_min, mvy_max, blk_w, blk_h, &mut best_mv, &mut lowest_cost, ref_frame, tmp_plane, bsize); @@ -452,7 +448,7 @@ pub struct FullSearch {} impl MotionEstimation for DiamondSearch { fn full_pixel_me( fi: &FrameInvariants, fs: &FrameState, rec: &Arc>, - po: PlaneOffset, bo: BlockOffset, lambda: u32, + bo: BlockOffset, lambda: u32, cmv: MotionVector, pmv: [MotionVector; 2], mvx_min: isize, mvx_max: isize, mvy_min: isize, mvy_max: isize, blk_w: usize, blk_h: usize, best_mv: &mut MotionVector, lowest_cost: &mut u64, ref_frame: usize @@ -464,7 +460,7 @@ impl MotionEstimation for DiamondSearch { diamond_me_search( fi, - po, + bo.to_luma_plane_offset(), &fs.input.planes[0], &rec.frame.planes[0], &predictors, @@ -486,7 +482,7 @@ impl MotionEstimation for DiamondSearch { fn sub_pixel_me( fi: &FrameInvariants, fs: &FrameState, rec: &Arc>, - po: PlaneOffset, _bo: BlockOffset, lambda: u32, + bo: BlockOffset, lambda: u32, pmv: [MotionVector; 2], mvx_min: isize, mvx_max: isize, mvy_min: isize, mvy_max: isize, blk_w: usize, blk_h: usize, best_mv: &mut MotionVector, lowest_cost: &mut u64, ref_frame: usize, @@ -496,7 +492,7 @@ impl MotionEstimation for DiamondSearch { let predictors = vec![*best_mv]; diamond_me_search( fi, - po, + bo.to_luma_plane_offset(), &fs.input.planes[0], &rec.frame.planes[0], &predictors, @@ -558,11 +554,12 @@ impl MotionEstimation for DiamondSearch { impl MotionEstimation for FullSearch { fn full_pixel_me( fi: &FrameInvariants, fs: &FrameState, rec: &Arc>, - po: PlaneOffset, _bo: BlockOffset, lambda: u32, + bo: BlockOffset, lambda: u32, cmv: MotionVector, pmv: [MotionVector; 2], mvx_min: isize, mvx_max: isize, mvy_min: isize, mvy_max: isize, blk_w: usize, blk_h: usize, best_mv: &mut MotionVector, lowest_cost: &mut u64, _ref_frame: usize ) { + let po = bo.to_luma_plane_offset(); let range = 16; let x_lo = po.x + ((-range + (cmv.col / 8) as isize).max(mvx_min / 8).min(mvx_max / 8)); @@ -595,7 +592,7 @@ impl MotionEstimation for FullSearch { fn sub_pixel_me( fi: &FrameInvariants, fs: &FrameState, _rec: &Arc>, - po: PlaneOffset, _bo: BlockOffset, lambda: u32, + bo: BlockOffset, lambda: u32, pmv: [MotionVector; 2], mvx_min: isize, mvx_max: isize, mvy_min: isize, mvy_max: isize, _blk_w: usize, _blk_h: usize, best_mv: &mut MotionVector, lowest_cost: &mut u64, ref_frame: usize, @@ -606,7 +603,7 @@ impl MotionEstimation for FullSearch { fi, fs, bsize, - po, + bo.to_luma_plane_offset(), lambda, ref_frame, pmv,