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
14 use crate::context::*;
15 use crate::partition::BlockSize::*;
16 use crate::partition::*;
17 use crate::transform::*;
18
19 static 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]
31 static 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
42 static 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]
51 static 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]
59 static 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 ];
63 static has_tr_8x16: &[u8] = &[
64 255, 255, 119, 119, 127, 127, 119, 119, 255, 127, 119, 119, 127, 127, 119,
65 119,
66 ];
67 static has_tr_16x8: &[u8] =
68 &[255, 0, 85, 0, 119, 0, 85, 0, 127, 0, 85, 0, 119, 0, 85, 0];
69 static has_tr_16x16: &[u8] = &[255, 85, 119, 85, 127, 85, 119, 85];
70 static has_tr_16x32: &[u8] = &[255, 119, 127, 119];
71 static has_tr_32x16: &[u8] = &[15, 5, 7, 5];
72 static has_tr_32x32: &[u8] = &[95, 87];
73 static has_tr_32x64: &[u8] = &[127];
74 static has_tr_64x32: &[u8] = &[19];
75 static has_tr_64x64: &[u8] = &[7];
76 static has_tr_64x128: &[u8] = &[3];
77 static has_tr_128x64: &[u8] = &[1];
78 static has_tr_128x128: &[u8] = &[1];
79 static 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 ];
84 static 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 ];
88 static has_tr_8x32: &[u8] = &[255, 255, 127, 127, 255, 127, 127, 127];
89 static has_tr_32x8: &[u8] = &[15, 0, 5, 0, 7, 0, 5, 0];
90 static has_tr_16x64: &[u8] = &[255, 127];
91 static has_tr_64x16: &[u8] = &[3, 1];
92
93 static 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]
119 static 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 ];
123 static has_tr_vert_16x16: &[u8] = &[255, 0, 119, 0, 127, 0, 119, 0];
124 static has_tr_vert_32x32: &[u8] = &[15, 7];
125 static 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
136 static 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.
get_has_tr_table( bsize: BlockSize, ) -> &'static [u8]156 pub 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
has_top_right( bsize: BlockSize, partition_bo: TileBlockOffset, top_available: bool, right_available: bool, tx_size: TxSize, row_off: usize, col_off: usize, ss_x: usize, _ss_y: usize, ) -> bool174 pub 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.
245 static 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 ];
254 static 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 ];
259 static 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 ];
265 static 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 ];
269 static has_bl_8x16: &[u8] =
270 &[16, 17, 0, 1, 16, 17, 0, 0, 16, 17, 0, 1, 16, 17, 0, 0];
271 static has_bl_16x8: &[u8] =
272 &[254, 84, 254, 16, 254, 84, 254, 0, 254, 84, 254, 16, 254, 84, 254, 0];
273 static has_bl_16x16: &[u8] = &[84, 16, 84, 0, 84, 16, 84, 0];
274 static has_bl_16x32: &[u8] = &[16, 0, 16, 0];
275 static has_bl_32x16: &[u8] = &[78, 14, 78, 14];
276 static has_bl_32x32: &[u8] = &[4, 4];
277 static has_bl_32x64: &[u8] = &[0];
278 static has_bl_64x32: &[u8] = &[34];
279 static has_bl_64x64: &[u8] = &[0];
280 static has_bl_64x128: &[u8] = &[0];
281 static has_bl_128x64: &[u8] = &[0];
282 static has_bl_128x128: &[u8] = &[0];
283 static 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 ];
287 static 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 ];
291 static has_bl_8x32: &[u8] = &[0, 1, 0, 0, 0, 1, 0, 0];
292 static has_bl_32x8: &[u8] = &[238, 78, 238, 14, 238, 78, 238, 14];
293 static has_bl_16x64: &[u8] = &[0, 0];
294 static has_bl_64x16: &[u8] = &[42, 42];
295
296 static 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]
322 static 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 ];
326 static has_bl_vert_16x16: &[u8] = &[254, 16, 254, 0, 254, 16, 254, 0];
327 static has_bl_vert_32x32: &[u8] = &[14, 14];
328 static 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
339 static 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
get_has_bl_table( bsize: BlockSize, ) -> &'static [u8]358 pub 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
has_bottom_left( bsize: BlockSize, partition_bo: TileBlockOffset, bottom_available: bool, left_available: bool, tx_size: TxSize, row_off: usize, col_off: usize, _ss_x: usize, ss_y: usize, ) -> bool374 pub 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 }
451