1use std::{
2 fmt,
3 fmt::Display,
4 ops::{Index, IndexMut},
5};
6
7use thiserror::Error;
8use v_frame::plane::PlaneOffset;
9
10use crate::data::{
11 plane::PlaneBlockOffset,
12 superblock::{MI_SIZE_LOG2, SB_SIZE_LOG2},
13};
14
15pub const MAX_TX_SIZE: usize = 64;
16pub const BLOCK_TO_PLANE_SHIFT: usize = MI_SIZE_LOG2;
17pub const MIB_SIZE_LOG2: usize = SB_SIZE_LOG2 - MI_SIZE_LOG2;
18
19#[derive(Debug, Copy, Clone, PartialEq, Eq)]
20#[cfg_attr(test, derive(Default))]
21#[allow(non_camel_case_types)]
22pub enum BlockSize {
23 BLOCK_4X4,
24 BLOCK_4X8,
25 BLOCK_8X4,
26 BLOCK_8X8,
27 BLOCK_8X16,
28 BLOCK_16X8,
29 BLOCK_16X16,
30 BLOCK_16X32,
31 BLOCK_32X16,
32 BLOCK_32X32,
33 BLOCK_32X64,
34 BLOCK_64X32,
35 #[cfg_attr(test, default)]
36 BLOCK_64X64,
37 BLOCK_64X128,
38 BLOCK_128X64,
39 BLOCK_128X128,
40 BLOCK_4X16,
41 BLOCK_16X4,
42 BLOCK_8X32,
43 BLOCK_32X8,
44 BLOCK_16X64,
45 BLOCK_64X16,
46}
47
48impl BlockSize {
49 pub fn from_width_and_height_opt(w: usize, h: usize) -> Result<BlockSize, InvalidBlockSize> {
54 use crate::data::block::BlockSize::*;
55
56 match (w, h) {
57 (4, 4) => Ok(BLOCK_4X4),
58 (4, 8) => Ok(BLOCK_4X8),
59 (4, 16) => Ok(BLOCK_4X16),
60 (8, 4) => Ok(BLOCK_8X4),
61 (8, 8) => Ok(BLOCK_8X8),
62 (8, 16) => Ok(BLOCK_8X16),
63 (8, 32) => Ok(BLOCK_8X32),
64 (16, 4) => Ok(BLOCK_16X4),
65 (16, 8) => Ok(BLOCK_16X8),
66 (16, 16) => Ok(BLOCK_16X16),
67 (16, 32) => Ok(BLOCK_16X32),
68 (16, 64) => Ok(BLOCK_16X64),
69 (32, 8) => Ok(BLOCK_32X8),
70 (32, 16) => Ok(BLOCK_32X16),
71 (32, 32) => Ok(BLOCK_32X32),
72 (32, 64) => Ok(BLOCK_32X64),
73 (64, 16) => Ok(BLOCK_64X16),
74 (64, 32) => Ok(BLOCK_64X32),
75 (64, 64) => Ok(BLOCK_64X64),
76 (64, 128) => Ok(BLOCK_64X128),
77 (128, 64) => Ok(BLOCK_128X64),
78 (128, 128) => Ok(BLOCK_128X128),
79 _ => Err(InvalidBlockSize),
80 }
81 }
82
83 pub fn from_width_and_height(w: usize, h: usize) -> BlockSize {
87 Self::from_width_and_height_opt(w, h).unwrap()
88 }
89
90 pub const fn width(self) -> usize {
91 1 << self.width_log2()
92 }
93
94 pub const fn width_log2(self) -> usize {
95 use crate::data::block::BlockSize::*;
96
97 match self {
98 BLOCK_4X4 | BLOCK_4X8 | BLOCK_4X16 => 2,
99 BLOCK_8X4 | BLOCK_8X8 | BLOCK_8X16 | BLOCK_8X32 => 3,
100 BLOCK_16X4 | BLOCK_16X8 | BLOCK_16X16 | BLOCK_16X32 | BLOCK_16X64 => 4,
101 BLOCK_32X8 | BLOCK_32X16 | BLOCK_32X32 | BLOCK_32X64 => 5,
102 BLOCK_64X16 | BLOCK_64X32 | BLOCK_64X64 | BLOCK_64X128 => 6,
103 BLOCK_128X64 | BLOCK_128X128 => 7,
104 }
105 }
106
107 pub const fn height(self) -> usize {
108 1 << self.height_log2()
109 }
110
111 pub const fn height_log2(self) -> usize {
112 use crate::data::block::BlockSize::*;
113
114 match self {
115 BLOCK_4X4 | BLOCK_8X4 | BLOCK_16X4 => 2,
116 BLOCK_4X8 | BLOCK_8X8 | BLOCK_16X8 | BLOCK_32X8 => 3,
117 BLOCK_4X16 | BLOCK_8X16 | BLOCK_16X16 | BLOCK_32X16 | BLOCK_64X16 => 4,
118 BLOCK_8X32 | BLOCK_16X32 | BLOCK_32X32 | BLOCK_64X32 => 5,
119 BLOCK_16X64 | BLOCK_32X64 | BLOCK_64X64 | BLOCK_128X64 => 6,
120 BLOCK_64X128 | BLOCK_128X128 => 7,
121 }
122 }
123
124 pub const fn tx_size(self) -> TxSize {
125 use crate::data::block::{BlockSize::*, TxSize::*};
126
127 match self {
128 BLOCK_4X4 => TX_4X4,
129 BLOCK_4X8 => TX_4X8,
130 BLOCK_8X4 => TX_8X4,
131 BLOCK_8X8 => TX_8X8,
132 BLOCK_8X16 => TX_8X16,
133 BLOCK_16X8 => TX_16X8,
134 BLOCK_16X16 => TX_16X16,
135 BLOCK_16X32 => TX_16X32,
136 BLOCK_32X16 => TX_32X16,
137 BLOCK_32X32 => TX_32X32,
138 BLOCK_32X64 => TX_32X64,
139 BLOCK_64X32 => TX_64X32,
140 BLOCK_4X16 => TX_4X16,
141 BLOCK_16X4 => TX_16X4,
142 BLOCK_8X32 => TX_8X32,
143 BLOCK_32X8 => TX_32X8,
144 BLOCK_16X64 => TX_16X64,
145 BLOCK_64X16 => TX_64X16,
146 _ => TX_64X64,
147 }
148 }
149}
150
151#[derive(Debug, Copy, Clone, Error, Eq, PartialEq)]
152pub struct InvalidBlockSize;
153
154impl Display for InvalidBlockSize {
155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156 f.write_str("invalid block size")
157 }
158}
159
160#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
162#[allow(non_camel_case_types)]
163pub enum TxSize {
164 TX_4X4,
165 TX_8X8,
166 TX_16X16,
167 TX_32X32,
168 TX_64X64,
169
170 TX_4X8,
171 TX_8X4,
172 TX_8X16,
173 TX_16X8,
174 TX_16X32,
175 TX_32X16,
176 TX_32X64,
177 TX_64X32,
178
179 TX_4X16,
180 TX_16X4,
181 TX_8X32,
182 TX_32X8,
183 TX_16X64,
184 TX_64X16,
185}
186
187impl TxSize {
188 pub const fn width(self) -> usize {
189 1 << self.width_log2()
190 }
191
192 pub const fn width_log2(self) -> usize {
193 use crate::data::block::TxSize::*;
194 match self {
195 TX_4X4 | TX_4X8 | TX_4X16 => 2,
196 TX_8X8 | TX_8X4 | TX_8X16 | TX_8X32 => 3,
197 TX_16X16 | TX_16X8 | TX_16X32 | TX_16X4 | TX_16X64 => 4,
198 TX_32X32 | TX_32X16 | TX_32X64 | TX_32X8 => 5,
199 TX_64X64 | TX_64X32 | TX_64X16 => 6,
200 }
201 }
202
203 pub const fn height(self) -> usize {
204 1 << self.height_log2()
205 }
206
207 pub const fn height_log2(self) -> usize {
208 use crate::data::block::TxSize::*;
209 match self {
210 TX_4X4 | TX_8X4 | TX_16X4 => 2,
211 TX_8X8 | TX_4X8 | TX_16X8 | TX_32X8 => 3,
212 TX_16X16 | TX_8X16 | TX_32X16 | TX_4X16 | TX_64X16 => 4,
213 TX_32X32 | TX_16X32 | TX_64X32 | TX_8X32 => 5,
214 TX_64X64 | TX_32X64 | TX_16X64 => 6,
215 }
216 }
217}
218
219#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
222pub struct BlockOffset {
223 pub x: usize,
224 pub y: usize,
225}
226
227impl BlockOffset {
228 pub const fn to_luma_plane_offset(self) -> PlaneOffset {
230 PlaneOffset {
231 x: (self.x as isize) << BLOCK_TO_PLANE_SHIFT,
232 y: (self.y as isize) << BLOCK_TO_PLANE_SHIFT,
233 }
234 }
235
236 pub fn with_offset(self, col_offset: isize, row_offset: isize) -> BlockOffset {
237 let x = self.x as isize + col_offset;
238 let y = self.y as isize + row_offset;
239 debug_assert!(x >= 0);
240 debug_assert!(y >= 0);
241
242 BlockOffset {
243 x: x as usize,
244 y: y as usize,
245 }
246 }
247}
248
249#[derive(Clone)]
250pub struct FrameBlocks {
251 blocks: Box<[Block]>,
252 pub cols: usize,
253}
254
255impl Index<usize> for FrameBlocks {
256 type Output = [Block];
257
258 fn index(&self, index: usize) -> &Self::Output {
259 &self.blocks[index * self.cols..(index + 1) * self.cols]
260 }
261}
262
263impl IndexMut<usize> for FrameBlocks {
264 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
265 &mut self.blocks[index * self.cols..(index + 1) * self.cols]
266 }
267}
268
269impl Index<PlaneBlockOffset> for FrameBlocks {
272 type Output = Block;
273
274 fn index(&self, bo: PlaneBlockOffset) -> &Self::Output {
275 &self[bo.0.y][bo.0.x]
276 }
277}
278
279impl IndexMut<PlaneBlockOffset> for FrameBlocks {
280 fn index_mut(&mut self, bo: PlaneBlockOffset) -> &mut Self::Output {
281 &mut self[bo.0.y][bo.0.x]
282 }
283}
284
285#[derive(Copy, Clone, Default)]
286pub struct Block {}