Skip to content
Permalink
Browse files

Fix DC_PRED and CFL_PRED at tile boundaries

A BlockRegion only knows its absolute offset, not its offset relative to
the tile.

In predict_intra_inner(), pass the whole region for the tile and the
block offset relative to the tile.

Signed-off-by: Romain Vimont <rom1v@videolabs.io>
  • Loading branch information...
barrbrain authored and tdaede committed Apr 18, 2019
1 parent 6dc9bb0 commit 855b6d06cd2c321d50b7bab8a339c98833502bf3
Showing with 33 additions and 30 deletions.
  1. +1 −1 src/encoder.rs
  2. +26 −23 src/partition.rs
  3. +6 −6 src/rdo.rs
@@ -1026,7 +1026,7 @@ pub fn encode_tx_block<T: Pixel>(
if mode.is_intra() {
let bit_depth = fi.sequence.bit_depth;
let edge_buf = get_intra_edges(&rec.as_const(), po, tx_size, bit_depth, Some(mode));
mode.predict_intra(&mut rec.subregion_mut(area), tx_size, bit_depth, &ac, alpha, &edge_buf);
mode.predict_intra(rec, tile_bo, tx_size, bit_depth, &ac, alpha, &edge_buf);
}

if skip { return (false, -1); }
@@ -1009,65 +1009,68 @@ pub fn get_intra_edges<T: Pixel>(

impl PredictionMode {
pub fn predict_intra<T: Pixel>(
self, dst: &mut PlaneRegionMut<'_, T>, tx_size: TxSize, bit_depth: usize,
self, dst: &mut PlaneRegionMut<'_, T>, bo: BlockOffset, tx_size: TxSize, bit_depth: usize,
ac: &[i16], alpha: i16, edge_buf: &AlignedArray<[T; 4 * MAX_TX_SIZE + 1]>
) {
assert!(self.is_intra());

match tx_size {
TxSize::TX_4X4 =>
self.predict_intra_inner::<Block4x4, _>(dst, bit_depth, ac, alpha, edge_buf),
self.predict_intra_inner::<Block4x4, _>(dst, bo, bit_depth, ac, alpha, edge_buf),
TxSize::TX_8X8 =>
self.predict_intra_inner::<Block8x8, _>(dst, bit_depth, ac, alpha, edge_buf),
self.predict_intra_inner::<Block8x8, _>(dst, bo, bit_depth, ac, alpha, edge_buf),
TxSize::TX_16X16 =>
self.predict_intra_inner::<Block16x16, _>(dst, bit_depth, ac, alpha, edge_buf),
self.predict_intra_inner::<Block16x16, _>(dst, bo, bit_depth, ac, alpha, edge_buf),
TxSize::TX_32X32 =>
self.predict_intra_inner::<Block32x32, _>(dst, bit_depth, ac, alpha, edge_buf),
self.predict_intra_inner::<Block32x32, _>(dst, bo, bit_depth, ac, alpha, edge_buf),
TxSize::TX_64X64 =>
self.predict_intra_inner::<Block64x64, _>(dst, bit_depth, ac, alpha, edge_buf),
self.predict_intra_inner::<Block64x64, _>(dst, bo, bit_depth, ac, alpha, edge_buf),

TxSize::TX_4X8 =>
self.predict_intra_inner::<Block4x8, _>(dst, bit_depth, ac, alpha, edge_buf),
self.predict_intra_inner::<Block4x8, _>(dst, bo, bit_depth, ac, alpha, edge_buf),
TxSize::TX_8X4 =>
self.predict_intra_inner::<Block8x4, _>(dst, bit_depth, ac, alpha, edge_buf),
self.predict_intra_inner::<Block8x4, _>(dst, bo, bit_depth, ac, alpha, edge_buf),
TxSize::TX_8X16 =>
self.predict_intra_inner::<Block8x16, _>(dst, bit_depth, ac, alpha, edge_buf),
self.predict_intra_inner::<Block8x16, _>(dst, bo, bit_depth, ac, alpha, edge_buf),
TxSize::TX_16X8 =>
self.predict_intra_inner::<Block16x8, _>(dst, bit_depth, ac, alpha, edge_buf),
self.predict_intra_inner::<Block16x8, _>(dst, bo, bit_depth, ac, alpha, edge_buf),
TxSize::TX_16X32 =>
self.predict_intra_inner::<Block16x32, _>(dst, bit_depth, ac, alpha, edge_buf),
self.predict_intra_inner::<Block16x32, _>(dst, bo, bit_depth, ac, alpha, edge_buf),
TxSize::TX_32X16 =>
self.predict_intra_inner::<Block32x16, _>(dst, bit_depth, ac, alpha, edge_buf),
self.predict_intra_inner::<Block32x16, _>(dst, bo, bit_depth, ac, alpha, edge_buf),
TxSize::TX_32X64 =>
self.predict_intra_inner::<Block32x64, _>(dst, bit_depth, ac, alpha, edge_buf),
self.predict_intra_inner::<Block32x64, _>(dst, bo, bit_depth, ac, alpha, edge_buf),
TxSize::TX_64X32 =>
self.predict_intra_inner::<Block64x32, _>(dst, bit_depth, ac, alpha, edge_buf),
self.predict_intra_inner::<Block64x32, _>(dst, bo, bit_depth, ac, alpha, edge_buf),

TxSize::TX_4X16 =>
self.predict_intra_inner::<Block4x16, _>(dst, bit_depth, ac, alpha, edge_buf),
self.predict_intra_inner::<Block4x16, _>(dst, bo, bit_depth, ac, alpha, edge_buf),
TxSize::TX_16X4 =>
self.predict_intra_inner::<Block16x4, _>(dst, bit_depth, ac, alpha, edge_buf),
self.predict_intra_inner::<Block16x4, _>(dst, bo, bit_depth, ac, alpha, edge_buf),
TxSize::TX_8X32 =>
self.predict_intra_inner::<Block8x32, _>(dst, bit_depth, ac, alpha, edge_buf),
self.predict_intra_inner::<Block8x32, _>(dst, bo, bit_depth, ac, alpha, edge_buf),
TxSize::TX_32X8 =>
self.predict_intra_inner::<Block32x8, _>(dst, bit_depth, ac, alpha, edge_buf),
self.predict_intra_inner::<Block32x8, _>(dst, bo, bit_depth, ac, alpha, edge_buf),
TxSize::TX_16X64 =>
self.predict_intra_inner::<Block16x64, _>(dst, bit_depth, ac, alpha, edge_buf),
self.predict_intra_inner::<Block16x64, _>(dst, bo, bit_depth, ac, alpha, edge_buf),
TxSize::TX_64X16 =>
self.predict_intra_inner::<Block64x16, _>(dst, bit_depth, ac, alpha, edge_buf),
self.predict_intra_inner::<Block64x16, _>(dst, bo, bit_depth, ac, alpha, edge_buf),
}
}

#[inline(always)]
fn predict_intra_inner<B: Intra<T>, T: Pixel>(
self, dst: &mut PlaneRegionMut<'_, T>, bit_depth: usize, ac: &[i16],
alpha: i16, edge_buf: &AlignedArray<[T; 4 * MAX_TX_SIZE + 1]>
self, dst: &mut PlaneRegionMut<'_, T>, tile_bo: BlockOffset,
bit_depth: usize, ac: &[i16], alpha: i16,
edge_buf: &AlignedArray<[T; 4 * MAX_TX_SIZE + 1]>
) {
// left pixels are order from bottom to top and right-aligned
let (left, not_left) = edge_buf.array.split_at(2*MAX_TX_SIZE);
let (top_left, above) = not_left.split_at(1);

let &Rect { x, y, .. } = dst.rect();
let BlockOffset { x, y, .. } = tile_bo;
let area = Area::BlockStartingAt { bo: tile_bo };
let dst = &mut dst.subregion_mut(area);

let mode: PredictionMode = match self {
PredictionMode::PAETH_PRED => match (x, y) {
@@ -734,9 +734,9 @@ pub fn rdo_mode_decision<T: Pixel>(
.iter()
.map(|&luma_mode| {
let rec = &mut ts.rec.planes[0];
let mut rec_region = rec.subregion_mut(Area::BlockStartingAt { bo: tile_bo });
luma_mode.predict_intra(
&mut rec_region,
rec,
tile_bo,
tx_size,
fi.sequence.bit_depth,
&[0i16; 2],
@@ -745,7 +745,7 @@ pub fn rdo_mode_decision<T: Pixel>(
);

let plane_org = ts.input_tile.planes[0].subregion(Area::BlockStartingAt { bo: tile_bo });
let plane_ref = rec_region.as_const();
let plane_ref = rec.subregion(Area::BlockStartingAt { bo: tile_bo });

(
luma_mode,
@@ -914,9 +914,9 @@ pub fn rdo_cfl_alpha<T: Pixel>(
Some(PredictionMode::UV_CFL_PRED)
);

let mut rec_region = rec.subregion_mut(Area::BlockStartingAt { bo: tile_bo });
PredictionMode::UV_CFL_PRED.predict_intra(
&mut rec_region,
rec,
tile_bo,
uv_tx_size,
bit_depth,
&ac.array,
@@ -925,7 +925,7 @@ pub fn rdo_cfl_alpha<T: Pixel>(
);
sse_wxh(
&input.subregion(Area::BlockStartingAt { bo: tile_bo }),
&rec_region.as_const(),
&rec.subregion(Area::BlockStartingAt { bo: tile_bo }),
uv_tx_size.width(),
uv_tx_size.height()
)

0 comments on commit 855b6d0

Please sign in to comment.
You can’t perform that action at this time.