rav1e/
recon_intra.rs

1// Copyright (c) 2017-2020, The rav1e contributors. All rights reserved
2//
3// This source code is subject to the terms of the BSD 2 Clause License and
4// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
5// was not distributed with this source code in the LICENSE file, you can
6// obtain it at www.aomedia.org/license/software. If the Alliance for Open
7// Media Patent License 1.0 was not distributed with this source code in the
8// PATENTS file, you can obtain it at www.aomedia.org/license/patent.
9
10#![allow(non_upper_case_globals)]
11#![allow(non_camel_case_types)]
12#![allow(dead_code)]
13
14use crate::context::*;
15use crate::partition::BlockSize::*;
16use crate::partition::*;
17use crate::transform::*;
18
19static has_null: &[u8] = &[];
20
21// Tables to store if the top-right reference pixels are available. The flags
22// are represented with bits, packed into 8-bit integers. E.g., for the 32x32
23// blocks in a 128x128 superblock, the index of the "o" block is 10 (in raster
24// order), so its flag is stored at the 3rd bit of the 2nd entry in the table,
25// i.e. (table[10 / 8] >> (10 % 8)) & 1.
26//       . . . .
27//       . . . .
28//       . . o .
29//       . . . .
30#[rustfmt::skip]
31static has_tr_4x4: &[u8] = &[
32  255, 255, 255, 255, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85,
33  127, 127, 127, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85,
34  255, 127, 255, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85,
35  127, 127, 127, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85,
36  255, 255, 255, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85,
37  127, 127, 127, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85,
38  255, 127, 255, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85,
39  127, 127, 127, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85,
40];
41
42static has_tr_4x8: &[u8] = &[
43  255, 255, 255, 255, 119, 119, 119, 119, 127, 127, 127, 127, 119, 119, 119,
44  119, 255, 127, 255, 127, 119, 119, 119, 119, 127, 127, 127, 127, 119, 119,
45  119, 119, 255, 255, 255, 127, 119, 119, 119, 119, 127, 127, 127, 127, 119,
46  119, 119, 119, 255, 127, 255, 127, 119, 119, 119, 119, 127, 127, 127, 127,
47  119, 119, 119, 119,
48];
49
50#[rustfmt::skip]
51static has_tr_8x4: &[u8] = &[
52  255, 255, 0, 0, 85, 85, 0, 0, 119, 119, 0, 0, 85, 85, 0, 0,
53  127, 127, 0, 0, 85, 85, 0, 0, 119, 119, 0, 0, 85, 85, 0, 0,
54  255, 127, 0, 0, 85, 85, 0, 0, 119, 119, 0, 0, 85, 85, 0, 0,
55  127, 127, 0, 0, 85, 85, 0, 0, 119, 119, 0, 0, 85, 85, 0, 0,
56];
57
58#[rustfmt::skip]
59static has_tr_8x8: &[u8] = &[
60  255, 255, 85, 85, 119, 119, 85, 85, 127, 127, 85, 85, 119, 119, 85, 85,
61  255, 127, 85, 85, 119, 119, 85, 85, 127, 127, 85, 85, 119, 119, 85, 85,
62];
63static has_tr_8x16: &[u8] = &[
64  255, 255, 119, 119, 127, 127, 119, 119, 255, 127, 119, 119, 127, 127, 119,
65  119,
66];
67static has_tr_16x8: &[u8] =
68  &[255, 0, 85, 0, 119, 0, 85, 0, 127, 0, 85, 0, 119, 0, 85, 0];
69static has_tr_16x16: &[u8] = &[255, 85, 119, 85, 127, 85, 119, 85];
70static has_tr_16x32: &[u8] = &[255, 119, 127, 119];
71static has_tr_32x16: &[u8] = &[15, 5, 7, 5];
72static has_tr_32x32: &[u8] = &[95, 87];
73static has_tr_32x64: &[u8] = &[127];
74static has_tr_64x32: &[u8] = &[19];
75static has_tr_64x64: &[u8] = &[7];
76static has_tr_64x128: &[u8] = &[3];
77static has_tr_128x64: &[u8] = &[1];
78static has_tr_128x128: &[u8] = &[1];
79static has_tr_4x16: &[u8] = &[
80  255, 255, 255, 255, 127, 127, 127, 127, 255, 127, 255, 127, 127, 127, 127,
81  127, 255, 255, 255, 127, 127, 127, 127, 127, 255, 127, 255, 127, 127, 127,
82  127, 127,
83];
84static has_tr_16x4: &[u8] = &[
85  255, 0, 0, 0, 85, 0, 0, 0, 119, 0, 0, 0, 85, 0, 0, 0, 127, 0, 0, 0, 85, 0,
86  0, 0, 119, 0, 0, 0, 85, 0, 0, 0,
87];
88static has_tr_8x32: &[u8] = &[255, 255, 127, 127, 255, 127, 127, 127];
89static has_tr_32x8: &[u8] = &[15, 0, 5, 0, 7, 0, 5, 0];
90static has_tr_16x64: &[u8] = &[255, 127];
91static has_tr_64x16: &[u8] = &[3, 1];
92
93static has_tr_tables: &[&[u8]] = &[
94  has_tr_4x4,     // 4x4
95  has_tr_4x8,     // 4x8
96  has_tr_8x4,     // 8x4
97  has_tr_8x8,     // 8x8
98  has_tr_8x16,    // 8x16
99  has_tr_16x8,    // 16x8
100  has_tr_16x16,   // 16x16
101  has_tr_16x32,   // 16x32
102  has_tr_32x16,   // 32x16
103  has_tr_32x32,   // 32x32
104  has_tr_32x64,   // 32x64
105  has_tr_64x32,   // 64x32
106  has_tr_64x64,   // 64x64
107  has_tr_64x128,  // 64x128
108  has_tr_128x64,  // 128x64
109  has_tr_128x128, // 128x128
110  has_tr_4x16,    // 4x16
111  has_tr_16x4,    // 16x4
112  has_tr_8x32,    // 8x32
113  has_tr_32x8,    // 32x8
114  has_tr_16x64,   // 16x64
115  has_tr_64x16,   // 64x16
116];
117
118#[rustfmt::skip]
119static has_tr_vert_8x8: &[u8] = &[
120  255, 255, 0, 0, 119, 119, 0, 0, 127, 127, 0, 0, 119, 119, 0, 0,
121  255, 127, 0, 0, 119, 119, 0, 0, 127, 127, 0, 0, 119, 119, 0, 0,
122];
123static has_tr_vert_16x16: &[u8] = &[255, 0, 119, 0, 127, 0, 119, 0];
124static has_tr_vert_32x32: &[u8] = &[15, 7];
125static has_tr_vert_64x64: &[u8] = &[3];
126
127// The _vert_* tables are like the ordinary tables above, but describe the
128// order we visit square blocks when doing a PARTITION_VERT_A or
129// PARTITION_VERT_B. This is the same order as normal except for on the last
130// split where we go vertically (TL, BL, TR, BR). We treat the rectangular block
131// as a pair of squares, which means that these tables work correctly for both
132// mixed vertical partition types.
133//
134// There are tables for each of the square sizes. Vertical rectangles (like
135// BLOCK_16X32) use their respective "non-vert" table
136static has_tr_vert_tables: &[&[u8]] = &[
137  has_null,          // 4X4
138  has_tr_4x8,        // 4X8
139  has_null,          // 8X4
140  has_tr_vert_8x8,   // 8X8
141  has_tr_8x16,       // 8X16
142  has_null,          // 16X8
143  has_tr_vert_16x16, // 16X16
144  has_tr_16x32,      // 16X32
145  has_null,          // 32X16
146  has_tr_vert_32x32, // 32X32
147  has_tr_32x64,      // 32X64
148  has_null,          // 64X32
149  has_tr_vert_64x64, // 64X64
150  has_tr_64x128,     // 64x128
151  has_null,          // 128x64
152  has_tr_128x128,    // 128x128
153];
154
155// TODO: Enable the case for PARTITION_VERT_A/B once they can be encoded by rav1e.
156pub fn get_has_tr_table(
157  /*partition: PartitionType, */ bsize: BlockSize,
158) -> &'static [u8] {
159  let ret: &[u8];
160  // If this is a mixed vertical partition, look up bsize in orders_vert.
161  /*if partition == PartitionType::PARTITION_VERT_A || partition == PartitionType::PARTITION_VERT_B {
162    debug_assert!(bsize < BlockSize::BLOCK_SIZES);
163    ret = has_tr_vert_tables[bsize as usize];
164  } else */
165  {
166    ret = has_tr_tables[bsize as usize];
167  }
168
169  //debug_assert!(ret != ptr::has_null());
170
171  ret
172}
173
174pub fn has_top_right(
175  bsize: BlockSize, partition_bo: TileBlockOffset, top_available: bool,
176  right_available: bool, tx_size: TxSize, row_off: usize, col_off: usize,
177  ss_x: usize, _ss_y: usize,
178) -> bool {
179  if !top_available || !right_available {
180    return false;
181  };
182
183  let bw_unit = bsize.width_mi();
184  let plane_bw_unit = (bw_unit >> ss_x).max(1);
185  let top_right_count_unit = tx_size.width_mi();
186
187  let mi_col = partition_bo.0.x;
188  let mi_row = partition_bo.0.y;
189
190  if row_off > 0 {
191    // Just need to check if enough pixels on the right.
192    // 128x128 SB is not supported yet by rav1e
193    if bsize.width() > BLOCK_64X64.width() {
194      // Special case: For 128x128 blocks, the transform unit whose
195      // top-right corner is at the center of the block does in fact have
196      // pixels available at its top-right corner.
197      if row_off == BLOCK_64X64.height_mi() >> _ss_y
198        && col_off + top_right_count_unit == BLOCK_64X64.width_mi() >> ss_x
199      {
200        return false;
201      }
202      let plane_bw_unit_64 = BLOCK_64X64.width_mi() >> ss_x;
203      let col_off_64 = col_off % plane_bw_unit_64;
204      return col_off_64 + top_right_count_unit < plane_bw_unit_64;
205    }
206    col_off + top_right_count_unit < plane_bw_unit
207  } else {
208    // All top-right pixels are in the block above, which is already available.
209    if col_off + top_right_count_unit < plane_bw_unit {
210      return true;
211    };
212
213    let bw_in_mi_log2 = bsize.width_log2() - MI_SIZE_LOG2;
214    let bh_in_mi_log2 = bsize.height_log2() - MI_SIZE_LOG2;
215    let sb_mi_size: usize = 16; // 64x64
216    let blk_row_in_sb = (mi_row & (sb_mi_size - 1)) >> bh_in_mi_log2;
217    let blk_col_in_sb = (mi_col & (sb_mi_size - 1)) >> bw_in_mi_log2;
218
219    // Top row of superblock: so top-right pixels are in the top and/or
220    // top-right superblocks, both of which are already available.
221    if blk_row_in_sb == 0 {
222      return true;
223    };
224
225    // Rightmost column of superblock (and not the top row): so top-right pixels
226    // fall in the right superblock, which is not available yet.
227    if ((blk_col_in_sb + 1) << bw_in_mi_log2) >= sb_mi_size {
228      return false;
229    };
230
231    // General case (neither top row nor rightmost column): check if the
232    // top-right block is coded before the current block.
233    let this_blk_index =
234      (blk_row_in_sb << (MAX_MIB_SIZE_LOG2 - bw_in_mi_log2)) + blk_col_in_sb;
235    let idx1 = this_blk_index / 8;
236    let idx2 = this_blk_index % 8;
237    let has_tr_table: &[u8] = get_has_tr_table(/*partition,*/ bsize);
238
239    ((has_tr_table[idx1] >> idx2) & 1) != 0
240  }
241}
242
243// Similar to the has_tr_* tables, but store if the bottom-left reference
244// pixels are available.
245static has_bl_4x4: &[u8] = &[
246  84, 85, 85, 85, 16, 17, 17, 17, 84, 85, 85, 85, 0, 1, 1, 1, 84, 85, 85, 85,
247  16, 17, 17, 17, 84, 85, 85, 85, 0, 0, 1, 0, 84, 85, 85, 85, 16, 17, 17, 17,
248  84, 85, 85, 85, 0, 1, 1, 1, 84, 85, 85, 85, 16, 17, 17, 17, 84, 85, 85, 85,
249  0, 0, 0, 0, 84, 85, 85, 85, 16, 17, 17, 17, 84, 85, 85, 85, 0, 1, 1, 1, 84,
250  85, 85, 85, 16, 17, 17, 17, 84, 85, 85, 85, 0, 0, 1, 0, 84, 85, 85, 85, 16,
251  17, 17, 17, 84, 85, 85, 85, 0, 1, 1, 1, 84, 85, 85, 85, 16, 17, 17, 17, 84,
252  85, 85, 85, 0, 0, 0, 0,
253];
254static has_bl_4x8: &[u8] = &[
255  16, 17, 17, 17, 0, 1, 1, 1, 16, 17, 17, 17, 0, 0, 1, 0, 16, 17, 17, 17, 0,
256  1, 1, 1, 16, 17, 17, 17, 0, 0, 0, 0, 16, 17, 17, 17, 0, 1, 1, 1, 16, 17, 17,
257  17, 0, 0, 1, 0, 16, 17, 17, 17, 0, 1, 1, 1, 16, 17, 17, 17, 0, 0, 0, 0,
258];
259static has_bl_8x4: &[u8] = &[
260  254, 255, 84, 85, 254, 255, 16, 17, 254, 255, 84, 85, 254, 255, 0, 1, 254,
261  255, 84, 85, 254, 255, 16, 17, 254, 255, 84, 85, 254, 255, 0, 0, 254, 255,
262  84, 85, 254, 255, 16, 17, 254, 255, 84, 85, 254, 255, 0, 1, 254, 255, 84,
263  85, 254, 255, 16, 17, 254, 255, 84, 85, 254, 255, 0, 0,
264];
265static has_bl_8x8: &[u8] = &[
266  84, 85, 16, 17, 84, 85, 0, 1, 84, 85, 16, 17, 84, 85, 0, 0, 84, 85, 16, 17,
267  84, 85, 0, 1, 84, 85, 16, 17, 84, 85, 0, 0,
268];
269static has_bl_8x16: &[u8] =
270  &[16, 17, 0, 1, 16, 17, 0, 0, 16, 17, 0, 1, 16, 17, 0, 0];
271static has_bl_16x8: &[u8] =
272  &[254, 84, 254, 16, 254, 84, 254, 0, 254, 84, 254, 16, 254, 84, 254, 0];
273static has_bl_16x16: &[u8] = &[84, 16, 84, 0, 84, 16, 84, 0];
274static has_bl_16x32: &[u8] = &[16, 0, 16, 0];
275static has_bl_32x16: &[u8] = &[78, 14, 78, 14];
276static has_bl_32x32: &[u8] = &[4, 4];
277static has_bl_32x64: &[u8] = &[0];
278static has_bl_64x32: &[u8] = &[34];
279static has_bl_64x64: &[u8] = &[0];
280static has_bl_64x128: &[u8] = &[0];
281static has_bl_128x64: &[u8] = &[0];
282static has_bl_128x128: &[u8] = &[0];
283static has_bl_4x16: &[u8] = &[
284  0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0,
285  1, 1, 1, 0, 0, 0, 0,
286];
287static has_bl_16x4: &[u8] = &[
288  254, 254, 254, 84, 254, 254, 254, 16, 254, 254, 254, 84, 254, 254, 254, 0,
289  254, 254, 254, 84, 254, 254, 254, 16, 254, 254, 254, 84, 254, 254, 254, 0,
290];
291static has_bl_8x32: &[u8] = &[0, 1, 0, 0, 0, 1, 0, 0];
292static has_bl_32x8: &[u8] = &[238, 78, 238, 14, 238, 78, 238, 14];
293static has_bl_16x64: &[u8] = &[0, 0];
294static has_bl_64x16: &[u8] = &[42, 42];
295
296static has_bl_tables: &[&[u8]] = &[
297  has_bl_4x4,     // 4x4
298  has_bl_4x8,     // 4x8
299  has_bl_8x4,     // 8x4
300  has_bl_8x8,     // 8x8
301  has_bl_8x16,    // 8x16
302  has_bl_16x8,    // 16x8
303  has_bl_16x16,   // 16x16
304  has_bl_16x32,   // 16x32
305  has_bl_32x16,   // 32x16
306  has_bl_32x32,   // 32x32
307  has_bl_32x64,   // 32x64
308  has_bl_64x32,   // 64x32
309  has_bl_64x64,   // 64x64
310  has_bl_64x128,  // 64x128
311  has_bl_128x64,  // 128x64
312  has_bl_128x128, // 128x128
313  has_bl_4x16,    // 4x16
314  has_bl_16x4,    // 16x4
315  has_bl_8x32,    // 8x32
316  has_bl_32x8,    // 32x8
317  has_bl_16x64,   // 16x64
318  has_bl_64x16,   // 64x16
319];
320
321#[rustfmt::skip]
322static has_bl_vert_8x8: &[u8] = &[
323  254, 255, 16, 17, 254, 255, 0, 1, 254, 255, 16, 17, 254, 255, 0, 0,
324  254, 255, 16, 17, 254, 255, 0, 1, 254, 255, 16, 17, 254, 255, 0, 0,
325];
326static has_bl_vert_16x16: &[u8] = &[254, 16, 254, 0, 254, 16, 254, 0];
327static has_bl_vert_32x32: &[u8] = &[14, 14];
328static has_bl_vert_64x64: &[u8] = &[2];
329
330// The _vert_* tables are like the ordinary tables above, but describe the
331// order we visit square blocks when doing a PARTITION_VERT_A or
332// PARTITION_VERT_B. This is the same order as normal except for on the last
333// split where we go vertically (TL, BL, TR, BR). We treat the rectangular block
334// as a pair of squares, which means that these tables work correctly for both
335// mixed vertical partition types.
336//
337// There are tables for each of the square sizes. Vertical rectangles (like
338// BLOCK_16X32) use their respective "non-vert" table
339static has_bl_vert_tables: &[&[u8]] = &[
340  has_null,          // 4x4
341  has_bl_4x8,        // 4x8
342  has_null,          // 8x4
343  has_bl_vert_8x8,   // 8x8
344  has_bl_8x16,       // 8x16
345  has_null,          // 16x8
346  has_bl_vert_16x16, // 16x16
347  has_bl_16x32,      // 16x32
348  has_null,          // 32x16
349  has_bl_vert_32x32, // 32x32
350  has_bl_32x64,      // 32x64
351  has_null,          // 64x32
352  has_bl_vert_64x64, // 64x64
353  has_bl_64x128,     // 64x128
354  has_null,          // 128x64
355  has_bl_128x128,    // 128x128
356];
357
358pub fn get_has_bl_table(
359  /*partition: PartitionType, */ bsize: BlockSize,
360) -> &'static [u8] {
361  let ret: &[u8];
362  // If this is a mixed vertical partition, look up bsize in orders_vert.
363  /*if (partition == PARTITION_VERT_A || partition == PARTITION_VERT_B) {
364    //assert(bsize < BLOCK_SIZES);
365    ret = has_bl_vert_tables[bsize as usize];
366  } else*/
367  {
368    ret = has_bl_tables[bsize as usize];
369  }
370  //debug_assert!(ret != ptr::has_null());
371  ret
372}
373
374pub fn has_bottom_left(
375  bsize: BlockSize, partition_bo: TileBlockOffset, bottom_available: bool,
376  left_available: bool, tx_size: TxSize, row_off: usize, col_off: usize,
377  _ss_x: usize, ss_y: usize,
378) -> bool {
379  if !bottom_available || !left_available {
380    return false;
381  };
382
383  // Special case for 128x* blocks, when col_off is half the block width.
384  // This is needed because 128x* superblocks are divided into 64x* blocks in
385  // raster order
386  // 128x128 SB is not supported yet by rav1e
387  if bsize.width() > BLOCK_64X64.width() && col_off > 0 {
388    let plane_bw_unit_64 = BLOCK_64X64.width_mi() >> _ss_x;
389    let col_off_64 = col_off % plane_bw_unit_64;
390    if col_off_64 == 0 {
391      // We are at the left edge of top-right or bottom-right 64x* block.
392      let plane_bh_unit_64 = BLOCK_64X64.height_mi() >> ss_y;
393      let row_off_64 = row_off % plane_bh_unit_64;
394      let plane_bh_unit = (bsize.height_mi() >> ss_y).min(plane_bh_unit_64);
395      // Check if all bottom-left pixels are in the left 64x* block (which is
396      // already coded).
397      return row_off_64 + tx_size.height_mi() < plane_bh_unit;
398    }
399  }
400
401  if col_off > 0 {
402    // Bottom-left pixels are in the bottom-left block, which is not available.
403    false
404  } else {
405    let bh_unit = bsize.height_mi();
406    let plane_bh_unit = (bh_unit >> ss_y).max(1);
407    let bottom_left_count_unit = tx_size.height_mi();
408
409    let mi_col = partition_bo.0.x;
410    let mi_row = partition_bo.0.y;
411
412    // All bottom-left pixels are in the left block, which is already available.
413    if row_off + bottom_left_count_unit < plane_bh_unit {
414      return true;
415    };
416
417    let bw_in_mi_log2 = bsize.width_log2() - MI_SIZE_LOG2;
418    let bh_in_mi_log2 = bsize.height_log2() - MI_SIZE_LOG2;
419    let sb_mi_size: usize = 16; // 64x64
420    let blk_row_in_sb = (mi_row & (sb_mi_size - 1)) >> bh_in_mi_log2;
421    let blk_col_in_sb = (mi_col & (sb_mi_size - 1)) >> bw_in_mi_log2;
422
423    // Leftmost column of superblock: so bottom-left pixels maybe in the left
424    // and/or bottom-left superblocks. But only the left superblock is
425    // available, so check if all required pixels fall in that superblock.
426    if blk_col_in_sb == 0 {
427      let blk_start_row_off = blk_row_in_sb << bh_in_mi_log2 >> ss_y;
428      let row_off_in_sb = blk_start_row_off + row_off;
429      let sb_height_unit = sb_mi_size >> ss_y;
430      return row_off_in_sb + bottom_left_count_unit < sb_height_unit;
431      //return row_off_in_sb + (bottom_left_count_unit << 1) < sb_height_unit;  // Don't it need tx height? again?
432    }
433
434    // Bottom row of superblock (and not the leftmost column): so bottom-left
435    // pixels fall in the bottom superblock, which is not available yet.
436    if ((blk_row_in_sb + 1) << bh_in_mi_log2) >= sb_mi_size {
437      return false;
438    };
439
440    // General case (neither leftmost column nor bottom row): check if the
441    // bottom-left block is coded before the current block.
442    let this_blk_index =
443      (blk_row_in_sb << (MAX_MIB_SIZE_LOG2 - bw_in_mi_log2)) + blk_col_in_sb;
444    let idx1 = this_blk_index / 8;
445    let idx2 = this_blk_index % 8;
446    let has_bl_table: &[u8] = get_has_bl_table(/*partition,*/ bsize);
447
448    ((has_bl_table[idx1] >> idx2) & 1) != 0
449  }
450}