/rust/registry/src/index.crates.io-6f17d22bba15001f/rav1e-0.7.1/src/partition.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2017-2022, 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_camel_case_types)] |
11 | | #![allow(dead_code)] |
12 | | |
13 | | use self::BlockSize::*; |
14 | | use self::TxSize::*; |
15 | | use crate::context::*; |
16 | | use crate::frame::*; |
17 | | use crate::predict::*; |
18 | | use crate::recon_intra::*; |
19 | | use crate::serialize::{Deserialize, Serialize}; |
20 | | use crate::tiling::*; |
21 | | use crate::transform::TxSize; |
22 | | use crate::util::*; |
23 | | use thiserror::Error; |
24 | | |
25 | | use std::mem::transmute; |
26 | | use std::mem::MaybeUninit; |
27 | | |
28 | | // LAST_FRAME through ALTREF_FRAME correspond to slots 0-6. |
29 | | #[derive(PartialEq, Eq, PartialOrd, Copy, Clone, Debug)] |
30 | | pub enum RefType { |
31 | | INTRA_FRAME = 0, |
32 | | LAST_FRAME = 1, |
33 | | LAST2_FRAME = 2, |
34 | | LAST3_FRAME = 3, |
35 | | GOLDEN_FRAME = 4, |
36 | | BWDREF_FRAME = 5, |
37 | | ALTREF2_FRAME = 6, |
38 | | ALTREF_FRAME = 7, |
39 | | NONE_FRAME = 8, |
40 | | } |
41 | | |
42 | | impl RefType { |
43 | | /// convert to a ref list index, 0-6 (`INTER_REFS_PER_FRAME`) |
44 | | /// |
45 | | /// # Panics |
46 | | /// |
47 | | /// - If the ref type is a None or Intra frame |
48 | | #[inline] |
49 | 0 | pub fn to_index(self) -> usize { |
50 | 0 | match self { |
51 | | NONE_FRAME => { |
52 | 0 | panic!("Tried to get slot of NONE_FRAME"); |
53 | | } |
54 | | INTRA_FRAME => { |
55 | 0 | panic!("Tried to get slot of INTRA_FRAME"); |
56 | | } |
57 | 0 | _ => (self as usize) - 1, |
58 | 0 | } |
59 | 0 | } Unexecuted instantiation: <rav1e::partition::RefType>::to_index Unexecuted instantiation: <rav1e::partition::RefType>::to_index |
60 | | #[inline] |
61 | 0 | pub const fn is_fwd_ref(self) -> bool { |
62 | 0 | (self as usize) < 5 |
63 | 0 | } Unexecuted instantiation: <rav1e::partition::RefType>::is_fwd_ref Unexecuted instantiation: <rav1e::partition::RefType>::is_fwd_ref |
64 | | #[inline] |
65 | 0 | pub const fn is_bwd_ref(self) -> bool { |
66 | 0 | (self as usize) >= 5 |
67 | 0 | } Unexecuted instantiation: <rav1e::partition::RefType>::is_bwd_ref Unexecuted instantiation: <rav1e::partition::RefType>::is_bwd_ref |
68 | | } |
69 | | |
70 | | use self::RefType::*; |
71 | | use std::fmt; |
72 | | use std::fmt::Display; |
73 | | |
74 | | pub const ALL_INTER_REFS: [RefType; 7] = [ |
75 | | LAST_FRAME, |
76 | | LAST2_FRAME, |
77 | | LAST3_FRAME, |
78 | | GOLDEN_FRAME, |
79 | | BWDREF_FRAME, |
80 | | ALTREF2_FRAME, |
81 | | ALTREF_FRAME, |
82 | | ]; |
83 | | |
84 | | pub const LAST_LAST2_FRAMES: usize = 0; // { LAST_FRAME, LAST2_FRAME } |
85 | | pub const LAST_LAST3_FRAMES: usize = 1; // { LAST_FRAME, LAST3_FRAME } |
86 | | pub const LAST_GOLDEN_FRAMES: usize = 2; // { LAST_FRAME, GOLDEN_FRAME } |
87 | | pub const BWDREF_ALTREF_FRAMES: usize = 3; // { BWDREF_FRAME, ALTREF_FRAME } |
88 | | pub const LAST2_LAST3_FRAMES: usize = 4; // { LAST2_FRAME, LAST3_FRAME } |
89 | | pub const LAST2_GOLDEN_FRAMES: usize = 5; // { LAST2_FRAME, GOLDEN_FRAME } |
90 | | pub const LAST3_GOLDEN_FRAMES: usize = 6; // { LAST3_FRAME, GOLDEN_FRAME } |
91 | | pub const BWDREF_ALTREF2_FRAMES: usize = 7; // { BWDREF_FRAME, ALTREF2_FRAME } |
92 | | pub const ALTREF2_ALTREF_FRAMES: usize = 8; // { ALTREF2_FRAME, ALTREF_FRAME } |
93 | | pub const TOTAL_UNIDIR_COMP_REFS: usize = 9; |
94 | | |
95 | | // NOTE: UNIDIR_COMP_REFS is the number of uni-directional reference pairs |
96 | | // that are explicitly signaled. |
97 | | pub const UNIDIR_COMP_REFS: usize = BWDREF_ALTREF_FRAMES + 1; |
98 | | |
99 | | pub const FWD_REFS: usize = 4; |
100 | | pub const BWD_REFS: usize = 3; |
101 | | pub const SINGLE_REFS: usize = 7; |
102 | | pub const TOTAL_REFS_PER_FRAME: usize = 8; |
103 | | pub const INTER_REFS_PER_FRAME: usize = 7; |
104 | | pub const TOTAL_COMP_REFS: usize = |
105 | | FWD_REFS * BWD_REFS + TOTAL_UNIDIR_COMP_REFS; |
106 | | |
107 | | pub const REF_FRAMES_LOG2: usize = 3; |
108 | | pub const REF_FRAMES: usize = 1 << REF_FRAMES_LOG2; |
109 | | |
110 | | pub const REF_CONTEXTS: usize = 3; |
111 | | pub const MVREF_ROW_COLS: usize = 3; |
112 | | |
113 | | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Debug)] |
114 | | pub enum PartitionType { |
115 | | PARTITION_NONE, |
116 | | PARTITION_HORZ, |
117 | | PARTITION_VERT, |
118 | | PARTITION_SPLIT, |
119 | | PARTITION_HORZ_A, // HORZ split and the top partition is split again |
120 | | PARTITION_HORZ_B, // HORZ split and the bottom partition is split again |
121 | | PARTITION_VERT_A, // VERT split and the left partition is split again |
122 | | PARTITION_VERT_B, // VERT split and the right partition is split again |
123 | | PARTITION_HORZ_4, // 4:1 horizontal partition |
124 | | PARTITION_VERT_4, // 4:1 vertical partition |
125 | | PARTITION_INVALID, |
126 | | } |
127 | | |
128 | | #[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)] |
129 | | pub enum BlockSize { |
130 | | BLOCK_4X4, |
131 | | BLOCK_4X8, |
132 | | BLOCK_8X4, |
133 | | BLOCK_8X8, |
134 | | BLOCK_8X16, |
135 | | BLOCK_16X8, |
136 | | BLOCK_16X16, |
137 | | BLOCK_16X32, |
138 | | BLOCK_32X16, |
139 | | BLOCK_32X32, |
140 | | BLOCK_32X64, |
141 | | BLOCK_64X32, |
142 | | BLOCK_64X64, |
143 | | BLOCK_64X128, |
144 | | BLOCK_128X64, |
145 | | BLOCK_128X128, |
146 | | BLOCK_4X16, |
147 | | BLOCK_16X4, |
148 | | BLOCK_8X32, |
149 | | BLOCK_32X8, |
150 | | BLOCK_16X64, |
151 | | BLOCK_64X16, |
152 | | } |
153 | | |
154 | | #[derive(Debug, Error, Copy, Clone, Eq, PartialEq)] |
155 | | pub struct InvalidBlockSize; |
156 | | |
157 | | impl Display for InvalidBlockSize { |
158 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
159 | 0 | f.write_str("invalid block size") |
160 | 0 | } |
161 | | } |
162 | | |
163 | | impl PartialOrd for BlockSize { |
164 | | #[inline(always)] |
165 | 0 | fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { |
166 | | use std::cmp::Ordering::{Equal, Greater, Less}; |
167 | | match ( |
168 | 0 | self.width().cmp(&other.width()), |
169 | 0 | self.height().cmp(&other.height()), |
170 | | ) { |
171 | 0 | (Greater, Less) | (Less, Greater) => None, |
172 | 0 | (Equal, Equal) => Some(Equal), |
173 | 0 | (Greater, _) | (_, Greater) => Some(Greater), |
174 | 0 | (Less, _) | (_, Less) => Some(Less), |
175 | | } |
176 | 0 | } |
177 | | } |
178 | | |
179 | | #[cfg(test)] |
180 | | impl Default for BlockSize { |
181 | | fn default() -> Self { |
182 | | BlockSize::BLOCK_64X64 |
183 | | } |
184 | | } |
185 | | |
186 | | impl BlockSize { |
187 | | pub const BLOCK_SIZES_ALL: usize = 22; |
188 | | pub const BLOCK_SIZES: usize = BlockSize::BLOCK_SIZES_ALL - 6; // BLOCK_SIZES_ALL minus 4:1 non-squares, six of them |
189 | | |
190 | | #[inline] |
191 | | /// # Errors |
192 | | /// |
193 | | /// - Returns `InvalidBlockSize` if the given `w` and `h` do not produce |
194 | | /// a valid block size. |
195 | 0 | pub fn from_width_and_height_opt( |
196 | 0 | w: usize, h: usize, |
197 | 0 | ) -> Result<BlockSize, InvalidBlockSize> { |
198 | 0 | match (w, h) { |
199 | 0 | (4, 4) => Ok(BLOCK_4X4), |
200 | 0 | (4, 8) => Ok(BLOCK_4X8), |
201 | 0 | (4, 16) => Ok(BLOCK_4X16), |
202 | 0 | (8, 4) => Ok(BLOCK_8X4), |
203 | 0 | (8, 8) => Ok(BLOCK_8X8), |
204 | 0 | (8, 16) => Ok(BLOCK_8X16), |
205 | 0 | (8, 32) => Ok(BLOCK_8X32), |
206 | 0 | (16, 4) => Ok(BLOCK_16X4), |
207 | 0 | (16, 8) => Ok(BLOCK_16X8), |
208 | 0 | (16, 16) => Ok(BLOCK_16X16), |
209 | 0 | (16, 32) => Ok(BLOCK_16X32), |
210 | 0 | (16, 64) => Ok(BLOCK_16X64), |
211 | 0 | (32, 8) => Ok(BLOCK_32X8), |
212 | 0 | (32, 16) => Ok(BLOCK_32X16), |
213 | 0 | (32, 32) => Ok(BLOCK_32X32), |
214 | 0 | (32, 64) => Ok(BLOCK_32X64), |
215 | 0 | (64, 16) => Ok(BLOCK_64X16), |
216 | 0 | (64, 32) => Ok(BLOCK_64X32), |
217 | 0 | (64, 64) => Ok(BLOCK_64X64), |
218 | 0 | (64, 128) => Ok(BLOCK_64X128), |
219 | 0 | (128, 64) => Ok(BLOCK_128X64), |
220 | 0 | (128, 128) => Ok(BLOCK_128X128), |
221 | 0 | _ => Err(InvalidBlockSize), |
222 | | } |
223 | 0 | } |
224 | | |
225 | | /// # Panics |
226 | | /// |
227 | | /// - If the given `w` and `h` do not produce a valid block size. |
228 | 0 | pub fn from_width_and_height(w: usize, h: usize) -> BlockSize { |
229 | 0 | Self::from_width_and_height_opt(w, h).unwrap() |
230 | 0 | } |
231 | | |
232 | | #[inline] |
233 | 0 | pub fn cfl_allowed(self) -> bool { |
234 | 0 | // TODO: fix me when enabling EXT_PARTITION_TYPES |
235 | 0 | self <= BlockSize::BLOCK_32X32 |
236 | 0 | } Unexecuted instantiation: <rav1e::partition::BlockSize>::cfl_allowed Unexecuted instantiation: <rav1e::partition::BlockSize>::cfl_allowed |
237 | | |
238 | | #[inline] |
239 | 0 | pub const fn width(self) -> usize { |
240 | 0 | 1 << self.width_log2() |
241 | 0 | } Unexecuted instantiation: <rav1e::partition::BlockSize>::width Unexecuted instantiation: <rav1e::partition::BlockSize>::width |
242 | | |
243 | | /// width * height |
244 | | #[inline] |
245 | 0 | pub const fn area(self) -> usize { |
246 | 0 | self.width() * self.height() |
247 | 0 | } Unexecuted instantiation: <rav1e::partition::BlockSize>::area Unexecuted instantiation: <rav1e::partition::BlockSize>::area |
248 | | |
249 | | #[inline] |
250 | 0 | pub const fn width_log2(self) -> usize { |
251 | 0 | match self { |
252 | 0 | BLOCK_4X4 | BLOCK_4X8 | BLOCK_4X16 => 2, |
253 | 0 | BLOCK_8X4 | BLOCK_8X8 | BLOCK_8X16 | BLOCK_8X32 => 3, |
254 | 0 | BLOCK_16X4 | BLOCK_16X8 | BLOCK_16X16 | BLOCK_16X32 | BLOCK_16X64 => 4, |
255 | 0 | BLOCK_32X8 | BLOCK_32X16 | BLOCK_32X32 | BLOCK_32X64 => 5, |
256 | 0 | BLOCK_64X16 | BLOCK_64X32 | BLOCK_64X64 | BLOCK_64X128 => 6, |
257 | 0 | BLOCK_128X64 | BLOCK_128X128 => 7, |
258 | | } |
259 | 0 | } Unexecuted instantiation: <rav1e::partition::BlockSize>::width_log2 Unexecuted instantiation: <rav1e::partition::BlockSize>::width_log2 |
260 | | |
261 | | #[inline] |
262 | 0 | pub const fn width_mi_log2(self) -> usize { |
263 | 0 | self.width_log2() - 2 |
264 | 0 | } |
265 | | |
266 | | #[inline] |
267 | 0 | pub const fn width_mi(self) -> usize { |
268 | 0 | self.width() >> MI_SIZE_LOG2 |
269 | 0 | } Unexecuted instantiation: <rav1e::partition::BlockSize>::width_mi Unexecuted instantiation: <rav1e::partition::BlockSize>::width_mi |
270 | | |
271 | | #[inline] |
272 | 0 | pub fn width_imp_b(self) -> usize { |
273 | 0 | (self.width() >> (IMPORTANCE_BLOCK_TO_BLOCK_SHIFT + BLOCK_TO_PLANE_SHIFT)) |
274 | 0 | .max(1) |
275 | 0 | } Unexecuted instantiation: <rav1e::partition::BlockSize>::width_imp_b Unexecuted instantiation: <rav1e::partition::BlockSize>::width_imp_b |
276 | | |
277 | | #[inline] |
278 | 0 | pub const fn height(self) -> usize { |
279 | 0 | 1 << self.height_log2() |
280 | 0 | } Unexecuted instantiation: <rav1e::partition::BlockSize>::height Unexecuted instantiation: <rav1e::partition::BlockSize>::height |
281 | | |
282 | | #[inline] |
283 | 0 | pub const fn height_log2(self) -> usize { |
284 | 0 | match self { |
285 | 0 | BLOCK_4X4 | BLOCK_8X4 | BLOCK_16X4 => 2, |
286 | 0 | BLOCK_4X8 | BLOCK_8X8 | BLOCK_16X8 | BLOCK_32X8 => 3, |
287 | 0 | BLOCK_4X16 | BLOCK_8X16 | BLOCK_16X16 | BLOCK_32X16 | BLOCK_64X16 => 4, |
288 | 0 | BLOCK_8X32 | BLOCK_16X32 | BLOCK_32X32 | BLOCK_64X32 => 5, |
289 | 0 | BLOCK_16X64 | BLOCK_32X64 | BLOCK_64X64 | BLOCK_128X64 => 6, |
290 | 0 | BLOCK_64X128 | BLOCK_128X128 => 7, |
291 | | } |
292 | 0 | } Unexecuted instantiation: <rav1e::partition::BlockSize>::height_log2 Unexecuted instantiation: <rav1e::partition::BlockSize>::height_log2 |
293 | | |
294 | | #[inline] |
295 | 0 | pub const fn height_mi_log2(self) -> usize { |
296 | 0 | self.height_log2() - 2 |
297 | 0 | } |
298 | | |
299 | | #[inline] |
300 | 0 | pub const fn height_mi(self) -> usize { |
301 | 0 | self.height() >> MI_SIZE_LOG2 |
302 | 0 | } Unexecuted instantiation: <rav1e::partition::BlockSize>::height_mi Unexecuted instantiation: <rav1e::partition::BlockSize>::height_mi |
303 | | |
304 | | #[inline] |
305 | 0 | pub fn height_imp_b(self) -> usize { |
306 | 0 | (self.height() >> (IMPORTANCE_BLOCK_TO_BLOCK_SHIFT + BLOCK_TO_PLANE_SHIFT)) |
307 | 0 | .max(1) |
308 | 0 | } Unexecuted instantiation: <rav1e::partition::BlockSize>::height_imp_b Unexecuted instantiation: <rav1e::partition::BlockSize>::height_imp_b |
309 | | |
310 | | #[inline] |
311 | 0 | pub const fn tx_size(self) -> TxSize { |
312 | 0 | match self { |
313 | 0 | BLOCK_4X4 => TX_4X4, |
314 | 0 | BLOCK_4X8 => TX_4X8, |
315 | 0 | BLOCK_8X4 => TX_8X4, |
316 | 0 | BLOCK_8X8 => TX_8X8, |
317 | 0 | BLOCK_8X16 => TX_8X16, |
318 | 0 | BLOCK_16X8 => TX_16X8, |
319 | 0 | BLOCK_16X16 => TX_16X16, |
320 | 0 | BLOCK_16X32 => TX_16X32, |
321 | 0 | BLOCK_32X16 => TX_32X16, |
322 | 0 | BLOCK_32X32 => TX_32X32, |
323 | 0 | BLOCK_32X64 => TX_32X64, |
324 | 0 | BLOCK_64X32 => TX_64X32, |
325 | 0 | BLOCK_4X16 => TX_4X16, |
326 | 0 | BLOCK_16X4 => TX_16X4, |
327 | 0 | BLOCK_8X32 => TX_8X32, |
328 | 0 | BLOCK_32X8 => TX_32X8, |
329 | 0 | BLOCK_16X64 => TX_16X64, |
330 | 0 | BLOCK_64X16 => TX_64X16, |
331 | 0 | _ => TX_64X64, |
332 | | } |
333 | 0 | } Unexecuted instantiation: <rav1e::partition::BlockSize>::tx_size Unexecuted instantiation: <rav1e::partition::BlockSize>::tx_size |
334 | | |
335 | | /// Source: `Subsampled_Size` (AV1 specification section 5.11.38) |
336 | | /// |
337 | | /// # Errors |
338 | | /// |
339 | | /// - Returns `InvalidBlockSize` if the given block size cannot |
340 | | /// be subsampled in the requested way. |
341 | | #[inline] |
342 | 0 | pub const fn subsampled_size( |
343 | 0 | self, xdec: usize, ydec: usize, |
344 | 0 | ) -> Result<BlockSize, InvalidBlockSize> { |
345 | 0 | Ok(match (xdec, ydec) { |
346 | 0 | (0, 0) /* 4:4:4 */ => self, |
347 | 0 | (1, 0) /* 4:2:2 */ => match self { |
348 | 0 | BLOCK_4X4 | BLOCK_8X4 => BLOCK_4X4, |
349 | 0 | BLOCK_8X8 => BLOCK_4X8, |
350 | 0 | BLOCK_16X4 => BLOCK_8X4, |
351 | 0 | BLOCK_16X8 => BLOCK_8X8, |
352 | 0 | BLOCK_16X16 => BLOCK_8X16, |
353 | 0 | BLOCK_32X8 => BLOCK_16X8, |
354 | 0 | BLOCK_32X16 => BLOCK_16X16, |
355 | 0 | BLOCK_32X32 => BLOCK_16X32, |
356 | 0 | BLOCK_64X16 => BLOCK_32X16, |
357 | 0 | BLOCK_64X32 => BLOCK_32X32, |
358 | 0 | BLOCK_64X64 => BLOCK_32X64, |
359 | 0 | BLOCK_128X64 => BLOCK_64X64, |
360 | 0 | BLOCK_128X128 => BLOCK_64X128, |
361 | 0 | _ => return Err(InvalidBlockSize), |
362 | | }, |
363 | 0 | (1, 1) /* 4:2:0 */ => match self { |
364 | 0 | BLOCK_4X4 | BLOCK_4X8 | BLOCK_8X4 | BLOCK_8X8 => BLOCK_4X4, |
365 | 0 | BLOCK_4X16 | BLOCK_8X16 => BLOCK_4X8, |
366 | 0 | BLOCK_8X32 => BLOCK_4X16, |
367 | 0 | BLOCK_16X4 | BLOCK_16X8 => BLOCK_8X4, |
368 | 0 | BLOCK_16X16 => BLOCK_8X8, |
369 | 0 | BLOCK_16X32 => BLOCK_8X16, |
370 | 0 | BLOCK_16X64 => BLOCK_8X32, |
371 | 0 | BLOCK_32X8 => BLOCK_16X4, |
372 | 0 | BLOCK_32X16 => BLOCK_16X8, |
373 | 0 | BLOCK_32X32 => BLOCK_16X16, |
374 | 0 | BLOCK_32X64 => BLOCK_16X32, |
375 | 0 | BLOCK_64X16 => BLOCK_32X8, |
376 | 0 | BLOCK_64X32 => BLOCK_32X16, |
377 | 0 | BLOCK_64X64 => BLOCK_32X32, |
378 | 0 | BLOCK_64X128 => BLOCK_32X64, |
379 | 0 | BLOCK_128X64 => BLOCK_64X32, |
380 | 0 | BLOCK_128X128 => BLOCK_64X64, |
381 | | }, |
382 | 0 | _ => return Err(InvalidBlockSize), |
383 | | }) |
384 | 0 | } Unexecuted instantiation: <rav1e::partition::BlockSize>::subsampled_size Unexecuted instantiation: <rav1e::partition::BlockSize>::subsampled_size |
385 | | |
386 | | /// # Panics |
387 | | /// |
388 | | /// Will panic if the subsampling is not possible |
389 | | #[inline] |
390 | 0 | pub fn largest_chroma_tx_size(self, xdec: usize, ydec: usize) -> TxSize { |
391 | 0 | let plane_bsize = self |
392 | 0 | .subsampled_size(xdec, ydec) |
393 | 0 | .expect("invalid block size for this subsampling mode"); |
394 | 0 |
|
395 | 0 | let chroma_tx_size = max_txsize_rect_lookup[plane_bsize as usize]; |
396 | 0 |
|
397 | 0 | av1_get_coded_tx_size(chroma_tx_size) |
398 | 0 | } Unexecuted instantiation: <rav1e::partition::BlockSize>::largest_chroma_tx_size Unexecuted instantiation: <rav1e::partition::BlockSize>::largest_chroma_tx_size |
399 | | |
400 | | #[inline] |
401 | 0 | pub const fn is_sqr(self) -> bool { |
402 | 0 | self.width_log2() == self.height_log2() |
403 | 0 | } Unexecuted instantiation: <rav1e::partition::BlockSize>::is_sqr Unexecuted instantiation: <rav1e::partition::BlockSize>::is_sqr |
404 | | |
405 | | #[inline] |
406 | 0 | pub const fn is_sub8x8(self, xdec: usize, ydec: usize) -> bool { |
407 | 0 | xdec != 0 && self.width_log2() == 2 || ydec != 0 && self.height_log2() == 2 |
408 | 0 | } Unexecuted instantiation: <rav1e::partition::BlockSize>::is_sub8x8 Unexecuted instantiation: <rav1e::partition::BlockSize>::is_sub8x8 |
409 | | |
410 | | #[inline] |
411 | 0 | pub const fn sub8x8_offset( |
412 | 0 | self, xdec: usize, ydec: usize, |
413 | 0 | ) -> (isize, isize) { |
414 | 0 | let offset_x = if xdec != 0 && self.width_log2() == 2 { -1 } else { 0 }; |
415 | 0 | let offset_y = if ydec != 0 && self.height_log2() == 2 { -1 } else { 0 }; |
416 | | |
417 | 0 | (offset_x, offset_y) |
418 | 0 | } Unexecuted instantiation: <rav1e::partition::BlockSize>::sub8x8_offset Unexecuted instantiation: <rav1e::partition::BlockSize>::sub8x8_offset |
419 | | |
420 | | /// # Errors |
421 | | /// |
422 | | /// - Returns `InvalidBlockSize` if the block size cannot be split |
423 | | /// in the requested way. |
424 | 0 | pub const fn subsize( |
425 | 0 | self, partition: PartitionType, |
426 | 0 | ) -> Result<BlockSize, InvalidBlockSize> { |
427 | | use PartitionType::*; |
428 | | |
429 | 0 | Ok(match partition { |
430 | 0 | PARTITION_NONE => self, |
431 | 0 | PARTITION_SPLIT => match self { |
432 | 0 | BLOCK_8X8 => BLOCK_4X4, |
433 | 0 | BLOCK_16X16 => BLOCK_8X8, |
434 | 0 | BLOCK_32X32 => BLOCK_16X16, |
435 | 0 | BLOCK_64X64 => BLOCK_32X32, |
436 | 0 | BLOCK_128X128 => BLOCK_64X64, |
437 | 0 | _ => return Err(InvalidBlockSize), |
438 | | }, |
439 | 0 | PARTITION_HORZ | PARTITION_HORZ_A | PARTITION_HORZ_B => match self { |
440 | 0 | BLOCK_8X8 => BLOCK_8X4, |
441 | 0 | BLOCK_16X16 => BLOCK_16X8, |
442 | 0 | BLOCK_32X32 => BLOCK_32X16, |
443 | 0 | BLOCK_64X64 => BLOCK_64X32, |
444 | 0 | BLOCK_128X128 => BLOCK_128X64, |
445 | 0 | _ => return Err(InvalidBlockSize), |
446 | | }, |
447 | 0 | PARTITION_VERT | PARTITION_VERT_A | PARTITION_VERT_B => match self { |
448 | 0 | BLOCK_8X8 => BLOCK_4X8, |
449 | 0 | BLOCK_16X16 => BLOCK_8X16, |
450 | 0 | BLOCK_32X32 => BLOCK_16X32, |
451 | 0 | BLOCK_64X64 => BLOCK_32X64, |
452 | 0 | BLOCK_128X128 => BLOCK_64X128, |
453 | 0 | _ => return Err(InvalidBlockSize), |
454 | | }, |
455 | 0 | PARTITION_HORZ_4 => match self { |
456 | 0 | BLOCK_16X16 => BLOCK_16X4, |
457 | 0 | BLOCK_32X32 => BLOCK_32X8, |
458 | 0 | BLOCK_64X64 => BLOCK_64X16, |
459 | 0 | _ => return Err(InvalidBlockSize), |
460 | | }, |
461 | 0 | PARTITION_VERT_4 => match self { |
462 | 0 | BLOCK_16X16 => BLOCK_4X16, |
463 | 0 | BLOCK_32X32 => BLOCK_8X32, |
464 | 0 | BLOCK_64X64 => BLOCK_16X64, |
465 | 0 | _ => return Err(InvalidBlockSize), |
466 | | }, |
467 | 0 | _ => return Err(InvalidBlockSize), |
468 | | }) |
469 | 0 | } |
470 | | |
471 | 0 | pub const fn is_rect_tx_allowed(self) -> bool { |
472 | 0 | !matches!( |
473 | 0 | self, |
474 | | BLOCK_4X4 |
475 | | | BLOCK_8X8 |
476 | | | BLOCK_16X16 |
477 | | | BLOCK_32X32 |
478 | | | BLOCK_64X64 |
479 | | | BLOCK_64X128 |
480 | | | BLOCK_128X64 |
481 | | | BLOCK_128X128 |
482 | | ) |
483 | 0 | } |
484 | | } |
485 | | |
486 | | impl fmt::Display for BlockSize { |
487 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { |
488 | 0 | write!( |
489 | 0 | f, |
490 | 0 | "{}", |
491 | 0 | match self { |
492 | 0 | BlockSize::BLOCK_4X4 => "4x4", |
493 | 0 | BlockSize::BLOCK_4X8 => "4x8", |
494 | 0 | BlockSize::BLOCK_8X4 => "8x4", |
495 | 0 | BlockSize::BLOCK_8X8 => "8x8", |
496 | 0 | BlockSize::BLOCK_8X16 => "8x16", |
497 | 0 | BlockSize::BLOCK_16X8 => "16x8", |
498 | 0 | BlockSize::BLOCK_16X16 => "16x16", |
499 | 0 | BlockSize::BLOCK_16X32 => "16x32", |
500 | 0 | BlockSize::BLOCK_32X16 => "32x16", |
501 | 0 | BlockSize::BLOCK_32X32 => "32x32", |
502 | 0 | BlockSize::BLOCK_32X64 => "32x64", |
503 | 0 | BlockSize::BLOCK_64X32 => "64x32", |
504 | 0 | BlockSize::BLOCK_64X64 => "64x64", |
505 | 0 | BlockSize::BLOCK_64X128 => "64x128", |
506 | 0 | BlockSize::BLOCK_128X64 => "128x64", |
507 | 0 | BlockSize::BLOCK_128X128 => "128x128", |
508 | 0 | BlockSize::BLOCK_4X16 => "4x16", |
509 | 0 | BlockSize::BLOCK_16X4 => "16x4", |
510 | 0 | BlockSize::BLOCK_8X32 => "8x32", |
511 | 0 | BlockSize::BLOCK_32X8 => "32x8", |
512 | 0 | BlockSize::BLOCK_16X64 => "16x64", |
513 | 0 | BlockSize::BLOCK_64X16 => "64x16", |
514 | | } |
515 | | ) |
516 | 0 | } |
517 | | } |
518 | | |
519 | | pub const NEWMV_MODE_CONTEXTS: usize = 7; |
520 | | pub const GLOBALMV_MODE_CONTEXTS: usize = 2; |
521 | | pub const REFMV_MODE_CONTEXTS: usize = 6; |
522 | | pub const INTER_COMPOUND_MODES: usize = 8; |
523 | | |
524 | | pub const REFMV_OFFSET: usize = 4; |
525 | | pub const GLOBALMV_OFFSET: usize = 3; |
526 | | pub const NEWMV_CTX_MASK: usize = (1 << GLOBALMV_OFFSET) - 1; |
527 | | pub const GLOBALMV_CTX_MASK: usize = |
528 | | (1 << (REFMV_OFFSET - GLOBALMV_OFFSET)) - 1; |
529 | | pub const REFMV_CTX_MASK: usize = (1 << (8 - REFMV_OFFSET)) - 1; |
530 | | |
531 | | pub static RAV1E_PARTITION_TYPES: &[PartitionType] = &[ |
532 | | PartitionType::PARTITION_NONE, |
533 | | PartitionType::PARTITION_HORZ, |
534 | | PartitionType::PARTITION_VERT, |
535 | | PartitionType::PARTITION_SPLIT, |
536 | | ]; |
537 | | |
538 | | #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)] |
539 | | pub enum GlobalMVMode { |
540 | | IDENTITY = 0, // identity transformation, 0-parameter |
541 | | TRANSLATION = 1, // translational motion 2-parameter |
542 | | ROTZOOM = 2, // simplified affine with rotation + zoom only, 4-parameter |
543 | | AFFINE = 3, // affine, 6-parameter |
544 | | } |
545 | | |
546 | | #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)] |
547 | | pub enum MvSubpelPrecision { |
548 | | MV_SUBPEL_NONE = -1, |
549 | | MV_SUBPEL_LOW_PRECISION = 0, |
550 | | MV_SUBPEL_HIGH_PRECISION, |
551 | | } |
552 | | |
553 | | /* Symbols for coding which components are zero jointly */ |
554 | | pub const MV_JOINTS: usize = 4; |
555 | | |
556 | | #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)] |
557 | | pub enum MvJointType { |
558 | | MV_JOINT_ZERO = 0, /* Zero vector */ |
559 | | MV_JOINT_HNZVZ = 1, /* Vert zero, hor nonzero */ |
560 | | MV_JOINT_HZVNZ = 2, /* Hor zero, vert nonzero */ |
561 | | MV_JOINT_HNZVNZ = 3, /* Both components nonzero */ |
562 | | } |
563 | | |
564 | 0 | fn supersample_chroma_bsize( |
565 | 0 | bsize: BlockSize, ss_x: usize, ss_y: usize, |
566 | 0 | ) -> BlockSize { |
567 | 0 | debug_assert!(ss_x < 2); |
568 | 0 | debug_assert!(ss_y < 2); |
569 | | |
570 | 0 | match bsize { |
571 | 0 | BLOCK_4X4 => match (ss_x, ss_y) { |
572 | 0 | (1, 1) => BLOCK_8X8, |
573 | 0 | (1, 0) => BLOCK_8X4, |
574 | 0 | (0, 1) => BLOCK_4X8, |
575 | 0 | _ => bsize, |
576 | | }, |
577 | 0 | BLOCK_4X8 => match (ss_x, ss_y) { |
578 | 0 | (1, 1) => BLOCK_8X8, |
579 | 0 | (1, 0) => BLOCK_8X8, |
580 | 0 | (0, 1) => BLOCK_4X8, |
581 | 0 | _ => bsize, |
582 | | }, |
583 | 0 | BLOCK_8X4 => match (ss_x, ss_y) { |
584 | 0 | (1, 1) => BLOCK_8X8, |
585 | 0 | (1, 0) => BLOCK_8X4, |
586 | 0 | (0, 1) => BLOCK_8X8, |
587 | 0 | _ => bsize, |
588 | | }, |
589 | 0 | BLOCK_4X16 => match (ss_x, ss_y) { |
590 | 0 | (1, 1) => BLOCK_8X16, |
591 | 0 | (1, 0) => BLOCK_8X16, |
592 | 0 | (0, 1) => BLOCK_4X16, |
593 | 0 | _ => bsize, |
594 | | }, |
595 | 0 | BLOCK_16X4 => match (ss_x, ss_y) { |
596 | 0 | (1, 1) => BLOCK_16X8, |
597 | 0 | (1, 0) => BLOCK_16X4, |
598 | 0 | (0, 1) => BLOCK_16X8, |
599 | 0 | _ => bsize, |
600 | | }, |
601 | 0 | _ => bsize, |
602 | | } |
603 | 0 | } |
604 | | |
605 | | type IntraEdgeBuffer<T> = Aligned<[MaybeUninit<T>; 4 * MAX_TX_SIZE + 1]>; |
606 | | |
607 | | #[cfg(any(test, feature = "bench"))] |
608 | | type IntraEdgeMock<T> = Aligned<[T; 4 * MAX_TX_SIZE + 1]>; |
609 | | |
610 | | pub struct IntraEdge<'a, T: Pixel>(&'a [T], &'a [T], &'a [T]); |
611 | | |
612 | | impl<'a, T: Pixel> IntraEdge<'a, T> { |
613 | 0 | fn new( |
614 | 0 | edge_buf: &'a mut IntraEdgeBuffer<T>, init_left: usize, init_above: usize, |
615 | 0 | ) -> Self { |
616 | 0 | // SAFETY: Initialized in `get_intra_edges`. |
617 | 0 | let left = unsafe { |
618 | 0 | let begin_left = 2 * MAX_TX_SIZE - init_left; |
619 | 0 | let end_above = 2 * MAX_TX_SIZE + 1 + init_above; |
620 | 0 | slice_assume_init_mut(&mut edge_buf.data[begin_left..end_above]) |
621 | 0 | }; |
622 | 0 | let (left, top_left) = left.split_at(init_left); |
623 | 0 | let (top_left, above) = top_left.split_at(1); |
624 | 0 | Self(left, top_left, above) |
625 | 0 | } Unexecuted instantiation: <rav1e::partition::IntraEdge<u16>>::new Unexecuted instantiation: <rav1e::partition::IntraEdge<u8>>::new |
626 | | |
627 | 0 | pub const fn as_slices(&self) -> (&'a [T], &'a [T], &'a [T]) { |
628 | 0 | (self.0, self.1, self.2) |
629 | 0 | } Unexecuted instantiation: <rav1e::partition::IntraEdge<u16>>::as_slices Unexecuted instantiation: <rav1e::partition::IntraEdge<u8>>::as_slices |
630 | | |
631 | 0 | pub const fn top_left_ptr(&self) -> *const T { |
632 | 0 | self.1.as_ptr() |
633 | 0 | } |
634 | | |
635 | | #[cfg(any(test, feature = "bench"))] |
636 | | pub fn mock(edge_buf: &'a IntraEdgeMock<T>) -> Self { |
637 | | let left = &edge_buf.data[..]; |
638 | | let (left, top_left) = left.split_at(2 * MAX_TX_SIZE); |
639 | | let (top_left, above) = top_left.split_at(1); |
640 | | Self(left, top_left, above) |
641 | | } |
642 | | } |
643 | | |
644 | 0 | pub fn get_intra_edges<'a, T: Pixel>( |
645 | 0 | edge_buf: &'a mut IntraEdgeBuffer<T>, |
646 | 0 | dst: &PlaneRegion<'_, T>, |
647 | 0 | partition_bo: TileBlockOffset, // partition bo, BlockOffset |
648 | 0 | bx: usize, |
649 | 0 | by: usize, |
650 | 0 | partition_size: BlockSize, // partition size, BlockSize |
651 | 0 | po: PlaneOffset, |
652 | 0 | tx_size: TxSize, |
653 | 0 | bit_depth: usize, |
654 | 0 | opt_mode: Option<PredictionMode>, |
655 | 0 | enable_intra_edge_filter: bool, |
656 | 0 | intra_param: IntraParam, |
657 | 0 | ) -> IntraEdge<'a, T> { |
658 | 0 | let mut init_left: usize = 0; |
659 | 0 | let mut init_above: usize = 0; |
660 | 0 |
|
661 | 0 | let plane_cfg = &dst.plane_cfg; |
662 | 0 |
|
663 | 0 | let base = 128u16 << (bit_depth - 8); |
664 | 0 |
|
665 | 0 | { |
666 | 0 | // left pixels are ordered from bottom to top and right-aligned |
667 | 0 | let (left, not_left) = edge_buf.data.split_at_mut(2 * MAX_TX_SIZE); |
668 | 0 | let (top_left, above) = not_left.split_at_mut(1); |
669 | 0 |
|
670 | 0 | let x = po.x as usize; |
671 | 0 | let y = po.y as usize; |
672 | 0 |
|
673 | 0 | let mut needs_left = true; |
674 | 0 | let mut needs_topleft = true; |
675 | 0 | let mut needs_top = true; |
676 | 0 | let mut needs_topright = true; |
677 | 0 | let mut needs_bottomleft = true; |
678 | 0 | let mut needs_topleft_filter = false; |
679 | | |
680 | 0 | if let Some(mut mode) = opt_mode { |
681 | 0 | mode = match mode { |
682 | 0 | PredictionMode::PAETH_PRED => match (x, y) { |
683 | 0 | (0, 0) => PredictionMode::DC_PRED, |
684 | 0 | (0, _) => PredictionMode::V_PRED, |
685 | 0 | (_, 0) => PredictionMode::H_PRED, |
686 | 0 | _ => PredictionMode::PAETH_PRED, |
687 | | }, |
688 | 0 | _ => mode, |
689 | | }; |
690 | | |
691 | 0 | let p_angle = intra_mode_to_angle(mode) |
692 | 0 | + match intra_param { |
693 | 0 | IntraParam::AngleDelta(val) => (val * ANGLE_STEP) as isize, |
694 | 0 | _ => 0, |
695 | | }; |
696 | | |
697 | 0 | let dc_or_cfl = |
698 | 0 | mode == PredictionMode::DC_PRED || mode == PredictionMode::UV_CFL_PRED; |
699 | | |
700 | 0 | needs_left = (!dc_or_cfl || x != 0) || (p_angle > 90 && p_angle != 180); |
701 | 0 | needs_topleft = mode == PredictionMode::PAETH_PRED |
702 | 0 | || (mode.is_directional() && p_angle != 90 && p_angle != 180); |
703 | 0 | needs_top = (!dc_or_cfl || y != 0) || (p_angle != 90 && p_angle < 180); |
704 | 0 | needs_topright = mode.is_directional() && p_angle < 90; |
705 | 0 | needs_bottomleft = mode.is_directional() && p_angle > 180; |
706 | | needs_topleft_filter = |
707 | 0 | enable_intra_edge_filter && p_angle > 90 && p_angle < 180; |
708 | 0 | } |
709 | | |
710 | 0 | let rect_w = |
711 | 0 | dst.rect().width.min(dst.plane_cfg.width - dst.rect().x as usize); |
712 | 0 | let rect_h = |
713 | 0 | dst.rect().height.min(dst.plane_cfg.height - dst.rect().y as usize); |
714 | 0 |
|
715 | 0 | // Needs left |
716 | 0 | if needs_left { |
717 | 0 | let txh = if y + tx_size.height() > rect_h { |
718 | 0 | rect_h - y |
719 | | } else { |
720 | 0 | tx_size.height() |
721 | | }; |
722 | 0 | if x != 0 { |
723 | 0 | for i in 0..txh { |
724 | 0 | debug_assert!(y + i < rect_h); |
725 | 0 | left[2 * MAX_TX_SIZE - 1 - i].write(dst[y + i][x - 1]); |
726 | | } |
727 | 0 | if txh < tx_size.height() { |
728 | 0 | let val = dst[y + txh - 1][x - 1]; |
729 | 0 | for i in txh..tx_size.height() { |
730 | 0 | left[2 * MAX_TX_SIZE - 1 - i].write(val); |
731 | 0 | } |
732 | 0 | } |
733 | | } else { |
734 | 0 | let val = if y != 0 { dst[y - 1][0] } else { T::cast_from(base + 1) }; |
735 | 0 | for v in left[2 * MAX_TX_SIZE - tx_size.height()..].iter_mut() { |
736 | 0 | v.write(val); |
737 | 0 | } |
738 | | } |
739 | 0 | init_left += tx_size.height(); |
740 | 0 | } |
741 | | |
742 | | // Needs top |
743 | 0 | if needs_top { |
744 | 0 | let txw = if x + tx_size.width() > rect_w { |
745 | 0 | rect_w - x |
746 | | } else { |
747 | 0 | tx_size.width() |
748 | | }; |
749 | 0 | if y != 0 { |
750 | 0 | above[..txw].copy_from_slice( |
751 | 0 | // SAFETY: &[T] and &[MaybeUninit<T>] have the same layout |
752 | 0 | unsafe { |
753 | 0 | transmute::<&[T], &[MaybeUninit<T>]>(&dst[y - 1][x..x + txw]) |
754 | 0 | }, |
755 | 0 | ); |
756 | 0 | if txw < tx_size.width() { |
757 | 0 | let val = dst[y - 1][x + txw - 1]; |
758 | 0 | for i in txw..tx_size.width() { |
759 | 0 | above[i].write(val); |
760 | 0 | } |
761 | 0 | } |
762 | | } else { |
763 | 0 | let val = if x != 0 { dst[0][x - 1] } else { T::cast_from(base - 1) }; |
764 | 0 | for v in above[..tx_size.width()].iter_mut() { |
765 | 0 | v.write(val); |
766 | 0 | } |
767 | | } |
768 | 0 | init_above += tx_size.width(); |
769 | 0 | } |
770 | | |
771 | 0 | let bx4 = bx * (tx_size.width() >> MI_SIZE_LOG2); // bx,by are in tx block indices |
772 | 0 | let by4 = by * (tx_size.height() >> MI_SIZE_LOG2); |
773 | | |
774 | 0 | let have_top = by4 != 0 |
775 | 0 | || if plane_cfg.ydec != 0 { |
776 | 0 | partition_bo.0.y > 1 |
777 | | } else { |
778 | 0 | partition_bo.0.y > 0 |
779 | | }; |
780 | 0 | let have_left = bx4 != 0 |
781 | 0 | || if plane_cfg.xdec != 0 { |
782 | 0 | partition_bo.0.x > 1 |
783 | | } else { |
784 | 0 | partition_bo.0.x > 0 |
785 | | }; |
786 | | |
787 | 0 | let right_available = x + tx_size.width() < rect_w; |
788 | 0 | let bottom_available = y + tx_size.height() < rect_h; |
789 | 0 |
|
790 | 0 | let scaled_partition_size = |
791 | 0 | supersample_chroma_bsize(partition_size, plane_cfg.xdec, plane_cfg.ydec); |
792 | 0 |
|
793 | 0 | // Needs top right |
794 | 0 | if needs_topright { |
795 | 0 | debug_assert!(plane_cfg.xdec <= 1 && plane_cfg.ydec <= 1); |
796 | | |
797 | 0 | let num_avail = if y != 0 |
798 | 0 | && has_top_right( |
799 | 0 | scaled_partition_size, |
800 | 0 | partition_bo, |
801 | 0 | have_top, |
802 | 0 | right_available, |
803 | 0 | tx_size, |
804 | 0 | by4, |
805 | 0 | bx4, |
806 | 0 | plane_cfg.xdec, |
807 | 0 | plane_cfg.ydec, |
808 | 0 | ) { |
809 | 0 | tx_size.width().min(rect_w - x - tx_size.width()) |
810 | | } else { |
811 | 0 | 0 |
812 | | }; |
813 | 0 | if num_avail > 0 { |
814 | 0 | above[tx_size.width()..][..num_avail].copy_from_slice( |
815 | 0 | // SAFETY: &[T] and &[MaybeUninit<T>] have the same layout |
816 | 0 | unsafe { |
817 | 0 | transmute::<&[T], &[MaybeUninit<T>]>( |
818 | 0 | &dst[y - 1][x + tx_size.width()..][..num_avail], |
819 | 0 | ) |
820 | 0 | }, |
821 | 0 | ); |
822 | 0 | } |
823 | 0 | if num_avail < tx_size.height() { |
824 | 0 | let val = above[tx_size.width() + num_avail - 1]; |
825 | 0 | for v in above |
826 | 0 | [tx_size.width() + num_avail..tx_size.width() + tx_size.height()] |
827 | 0 | .iter_mut() |
828 | 0 | { |
829 | 0 | *v = val; |
830 | 0 | } |
831 | 0 | } |
832 | 0 | init_above += tx_size.height(); |
833 | 0 | } |
834 | | |
835 | | // SAFETY: The blocks above have initialized the first `init_above` items. |
836 | 0 | let above = unsafe { slice_assume_init_mut(&mut above[..init_above]) }; |
837 | 0 |
|
838 | 0 | // Needs bottom left |
839 | 0 | if needs_bottomleft { |
840 | 0 | debug_assert!(plane_cfg.xdec <= 1 && plane_cfg.ydec <= 1); |
841 | | |
842 | 0 | let num_avail = if x != 0 |
843 | 0 | && has_bottom_left( |
844 | 0 | scaled_partition_size, |
845 | 0 | partition_bo, |
846 | 0 | bottom_available, |
847 | 0 | have_left, |
848 | 0 | tx_size, |
849 | 0 | by4, |
850 | 0 | bx4, |
851 | 0 | plane_cfg.xdec, |
852 | 0 | plane_cfg.ydec, |
853 | 0 | ) { |
854 | 0 | tx_size.height().min(rect_h - y - tx_size.height()) |
855 | | } else { |
856 | 0 | 0 |
857 | | }; |
858 | 0 | if num_avail > 0 { |
859 | 0 | for i in 0..num_avail { |
860 | 0 | left[2 * MAX_TX_SIZE - tx_size.height() - 1 - i] |
861 | 0 | .write(dst[y + tx_size.height() + i][x - 1]); |
862 | 0 | } |
863 | 0 | } |
864 | 0 | if num_avail < tx_size.width() { |
865 | 0 | let val = left[2 * MAX_TX_SIZE - tx_size.height() - num_avail]; |
866 | 0 | for v in left[(2 * MAX_TX_SIZE - tx_size.height() - tx_size.width()) |
867 | 0 | ..(2 * MAX_TX_SIZE - tx_size.height() - num_avail)] |
868 | 0 | .iter_mut() |
869 | 0 | { |
870 | 0 | *v = val; |
871 | 0 | } |
872 | 0 | } |
873 | 0 | init_left += tx_size.width(); |
874 | 0 | } |
875 | | |
876 | | // SAFETY: The blocks above have initialized last `init_left` items. |
877 | 0 | let left = unsafe { |
878 | 0 | slice_assume_init_mut(&mut left[2 * MAX_TX_SIZE - init_left..]) |
879 | 0 | }; |
880 | 0 |
|
881 | 0 | // Needs top-left |
882 | 0 | if needs_topleft { |
883 | 0 | let top_left = top_left[0].write(match (x, y) { |
884 | 0 | (0, 0) => T::cast_from(base), |
885 | 0 | (_, 0) => dst[0][x - 1], |
886 | 0 | (0, _) => dst[y - 1][0], |
887 | 0 | _ => dst[y - 1][x - 1], |
888 | | }); |
889 | | |
890 | 0 | let (w, h) = (tx_size.width(), tx_size.height()); |
891 | 0 | if needs_topleft_filter && w + h >= 24 { |
892 | 0 | let (l, a, tl): (u32, u32, u32) = |
893 | 0 | (left[left.len() - 1].into(), above[0].into(), (*top_left).into()); |
894 | 0 | let s = l * 5 + tl * 6 + a * 5; |
895 | 0 |
|
896 | 0 | *top_left = T::cast_from((s + (1 << 3)) >> 4); |
897 | 0 | } |
898 | 0 | } else { |
899 | 0 | top_left[0].write(T::cast_from(base)); |
900 | 0 | } |
901 | | } |
902 | 0 | IntraEdge::new(edge_buf, init_left, init_above) |
903 | 0 | } Unexecuted instantiation: rav1e::partition::get_intra_edges::<u16> Unexecuted instantiation: rav1e::partition::get_intra_edges::<u8> |
904 | | |
905 | 0 | pub fn has_tr(bo: TileBlockOffset, bsize: BlockSize) -> bool { |
906 | 0 | let sb_mi_size = BLOCK_64X64.width_mi(); /* Assume 64x64 for now */ |
907 | 0 | let mask_row = bo.0.y & LOCAL_BLOCK_MASK; |
908 | 0 | let mask_col = bo.0.x & LOCAL_BLOCK_MASK; |
909 | 0 | let target_n4_w = bsize.width_mi(); |
910 | 0 | let target_n4_h = bsize.height_mi(); |
911 | 0 |
|
912 | 0 | let mut bs = target_n4_w.max(target_n4_h); |
913 | 0 |
|
914 | 0 | if bs > BLOCK_64X64.width_mi() { |
915 | 0 | return false; |
916 | 0 | } |
917 | | |
918 | 0 | let mut has_tr = !((mask_row & bs) != 0 && (mask_col & bs) != 0); |
919 | | |
920 | | /* TODO: assert its a power of two */ |
921 | | |
922 | 0 | while bs < sb_mi_size { |
923 | 0 | if (mask_col & bs) != 0 { |
924 | 0 | if (mask_col & (2 * bs) != 0) && (mask_row & (2 * bs) != 0) { |
925 | 0 | has_tr = false; |
926 | 0 | break; |
927 | 0 | } |
928 | | } else { |
929 | 0 | break; |
930 | | } |
931 | 0 | bs <<= 1; |
932 | | } |
933 | | |
934 | | /* The left hand of two vertical rectangles always has a top right (as the |
935 | | * block above will have been decoded) */ |
936 | 0 | if (target_n4_w < target_n4_h) && (bo.0.x & target_n4_w) == 0 { |
937 | 0 | has_tr = true; |
938 | 0 | } |
939 | | |
940 | | /* The bottom of two horizontal rectangles never has a top right (as the block |
941 | | * to the right won't have been decoded) */ |
942 | 0 | if (target_n4_w > target_n4_h) && (bo.0.y & target_n4_h) != 0 { |
943 | 0 | has_tr = false; |
944 | 0 | } |
945 | | |
946 | | /* The bottom left square of a Vertical A (in the old format) does |
947 | | * not have a top right as it is decoded before the right hand |
948 | | * rectangle of the partition */ |
949 | | /* |
950 | | if blk.partition == PartitionType::PARTITION_VERT_A { |
951 | | if blk.n4_w == blk.n4_h { |
952 | | if (mask_row & bs) != 0 { |
953 | | has_tr = false; |
954 | | } |
955 | | } |
956 | | } |
957 | | */ |
958 | | |
959 | 0 | has_tr |
960 | 0 | } |
961 | | |
962 | 0 | pub fn has_bl(bo: TileBlockOffset, bsize: BlockSize) -> bool { |
963 | 0 | let sb_mi_size = BLOCK_64X64.width_mi(); /* Assume 64x64 for now */ |
964 | 0 | let mask_row = bo.0.y & LOCAL_BLOCK_MASK; |
965 | 0 | let mask_col = bo.0.x & LOCAL_BLOCK_MASK; |
966 | 0 | let target_n4_w = bsize.width_mi(); |
967 | 0 | let target_n4_h = bsize.height_mi(); |
968 | 0 |
|
969 | 0 | let mut bs = target_n4_w.max(target_n4_h); |
970 | 0 |
|
971 | 0 | if bs > BLOCK_64X64.width_mi() { |
972 | 0 | return false; |
973 | 0 | } |
974 | | |
975 | 0 | let mut has_bl = |
976 | 0 | (mask_row & bs) == 0 && (mask_col & bs) == 0 && bs < sb_mi_size; |
977 | | |
978 | | /* TODO: assert its a power of two */ |
979 | | |
980 | 0 | while 2 * bs < sb_mi_size { |
981 | 0 | if (mask_col & bs) == 0 { |
982 | 0 | if (mask_col & (2 * bs) == 0) && (mask_row & (2 * bs) == 0) { |
983 | 0 | has_bl = true; |
984 | 0 | break; |
985 | 0 | } |
986 | | } else { |
987 | 0 | break; |
988 | | } |
989 | 0 | bs <<= 1; |
990 | | } |
991 | | |
992 | | /* The right hand of two vertical rectangles never has a bottom left (as the |
993 | | * block below won't have been decoded) */ |
994 | 0 | if (target_n4_w < target_n4_h) && (bo.0.x & target_n4_w) != 0 { |
995 | 0 | has_bl = false; |
996 | 0 | } |
997 | | |
998 | | /* The top of two horizontal rectangles always has a bottom left (as the block |
999 | | * to the left will have been decoded) */ |
1000 | 0 | if (target_n4_w > target_n4_h) && (bo.0.y & target_n4_h) == 0 { |
1001 | 0 | has_bl = true; |
1002 | 0 | } |
1003 | | |
1004 | | /* The bottom left square of a Vertical A (in the old format) does |
1005 | | * not have a top right as it is decoded before the right hand |
1006 | | * rectangle of the partition */ |
1007 | | /* |
1008 | | if blk.partition == PartitionType::PARTITION_VERT_A { |
1009 | | if blk.n4_w == blk.n4_h { |
1010 | | if (mask_row & bs) != 0 { |
1011 | | has_tr = false; |
1012 | | } |
1013 | | } |
1014 | | } |
1015 | | */ |
1016 | | |
1017 | 0 | has_bl |
1018 | 0 | } |
1019 | | |
1020 | | #[cfg(test)] |
1021 | | mod tests { |
1022 | | use crate::partition::BlockSize::*; |
1023 | | use crate::partition::{BlockSize, InvalidBlockSize}; |
1024 | | |
1025 | | #[test] |
1026 | | fn from_wh_matches_naive() { |
1027 | | fn from_wh_opt_naive( |
1028 | | w: usize, h: usize, |
1029 | | ) -> Result<BlockSize, InvalidBlockSize> { |
1030 | | match (w, h) { |
1031 | | (4, 4) => Ok(BLOCK_4X4), |
1032 | | (4, 8) => Ok(BLOCK_4X8), |
1033 | | (8, 4) => Ok(BLOCK_8X4), |
1034 | | (8, 8) => Ok(BLOCK_8X8), |
1035 | | (8, 16) => Ok(BLOCK_8X16), |
1036 | | (16, 8) => Ok(BLOCK_16X8), |
1037 | | (16, 16) => Ok(BLOCK_16X16), |
1038 | | (16, 32) => Ok(BLOCK_16X32), |
1039 | | (32, 16) => Ok(BLOCK_32X16), |
1040 | | (32, 32) => Ok(BLOCK_32X32), |
1041 | | (32, 64) => Ok(BLOCK_32X64), |
1042 | | (64, 32) => Ok(BLOCK_64X32), |
1043 | | (64, 64) => Ok(BLOCK_64X64), |
1044 | | (64, 128) => Ok(BLOCK_64X128), |
1045 | | (128, 64) => Ok(BLOCK_128X64), |
1046 | | (128, 128) => Ok(BLOCK_128X128), |
1047 | | (4, 16) => Ok(BLOCK_4X16), |
1048 | | (16, 4) => Ok(BLOCK_16X4), |
1049 | | (8, 32) => Ok(BLOCK_8X32), |
1050 | | (32, 8) => Ok(BLOCK_32X8), |
1051 | | (16, 64) => Ok(BLOCK_16X64), |
1052 | | (64, 16) => Ok(BLOCK_64X16), |
1053 | | _ => Err(InvalidBlockSize), |
1054 | | } |
1055 | | } |
1056 | | |
1057 | | for w in 0..256 { |
1058 | | for h in 0..256 { |
1059 | | let a = BlockSize::from_width_and_height_opt(w, h); |
1060 | | let b = from_wh_opt_naive(w, h); |
1061 | | |
1062 | | assert_eq!(a, b); |
1063 | | } |
1064 | | } |
1065 | | } |
1066 | | } |