Coverage Report

Created: 2025-11-24 07:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/av-scenechange-0.14.1/src/data/block.rs
Line
Count
Source
1
use std::{
2
    fmt,
3
    fmt::Display,
4
    ops::{Index, IndexMut},
5
};
6
7
use thiserror::Error;
8
use v_frame::plane::PlaneOffset;
9
10
use crate::data::{
11
    plane::PlaneBlockOffset,
12
    superblock::{MI_SIZE_LOG2, SB_SIZE_LOG2},
13
};
14
15
pub const MAX_TX_SIZE: usize = 64;
16
pub const BLOCK_TO_PLANE_SHIFT: usize = MI_SIZE_LOG2;
17
pub 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)]
22
pub 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
48
impl BlockSize {
49
    /// # Errors
50
    ///
51
    /// - Returns `InvalidBlockSize` if the given `w` and `h` do not produce a
52
    ///   valid block size.
53
0
    pub fn from_width_and_height_opt(w: usize, h: usize) -> Result<BlockSize, InvalidBlockSize> {
54
        use crate::data::block::BlockSize::*;
55
56
0
        match (w, h) {
57
0
            (4, 4) => Ok(BLOCK_4X4),
58
0
            (4, 8) => Ok(BLOCK_4X8),
59
0
            (4, 16) => Ok(BLOCK_4X16),
60
0
            (8, 4) => Ok(BLOCK_8X4),
61
0
            (8, 8) => Ok(BLOCK_8X8),
62
0
            (8, 16) => Ok(BLOCK_8X16),
63
0
            (8, 32) => Ok(BLOCK_8X32),
64
0
            (16, 4) => Ok(BLOCK_16X4),
65
0
            (16, 8) => Ok(BLOCK_16X8),
66
0
            (16, 16) => Ok(BLOCK_16X16),
67
0
            (16, 32) => Ok(BLOCK_16X32),
68
0
            (16, 64) => Ok(BLOCK_16X64),
69
0
            (32, 8) => Ok(BLOCK_32X8),
70
0
            (32, 16) => Ok(BLOCK_32X16),
71
0
            (32, 32) => Ok(BLOCK_32X32),
72
0
            (32, 64) => Ok(BLOCK_32X64),
73
0
            (64, 16) => Ok(BLOCK_64X16),
74
0
            (64, 32) => Ok(BLOCK_64X32),
75
0
            (64, 64) => Ok(BLOCK_64X64),
76
0
            (64, 128) => Ok(BLOCK_64X128),
77
0
            (128, 64) => Ok(BLOCK_128X64),
78
0
            (128, 128) => Ok(BLOCK_128X128),
79
0
            _ => Err(InvalidBlockSize),
80
        }
81
0
    }
82
83
    /// # Panics
84
    ///
85
    /// - If the given `w` and `h` do not produce a valid block size.
86
0
    pub fn from_width_and_height(w: usize, h: usize) -> BlockSize {
87
0
        Self::from_width_and_height_opt(w, h).unwrap()
88
0
    }
89
90
0
    pub const fn width(self) -> usize {
91
0
        1 << self.width_log2()
92
0
    }
93
94
0
    pub const fn width_log2(self) -> usize {
95
        use crate::data::block::BlockSize::*;
96
97
0
        match self {
98
0
            BLOCK_4X4 | BLOCK_4X8 | BLOCK_4X16 => 2,
99
0
            BLOCK_8X4 | BLOCK_8X8 | BLOCK_8X16 | BLOCK_8X32 => 3,
100
0
            BLOCK_16X4 | BLOCK_16X8 | BLOCK_16X16 | BLOCK_16X32 | BLOCK_16X64 => 4,
101
0
            BLOCK_32X8 | BLOCK_32X16 | BLOCK_32X32 | BLOCK_32X64 => 5,
102
0
            BLOCK_64X16 | BLOCK_64X32 | BLOCK_64X64 | BLOCK_64X128 => 6,
103
0
            BLOCK_128X64 | BLOCK_128X128 => 7,
104
        }
105
0
    }
106
107
0
    pub const fn height(self) -> usize {
108
0
        1 << self.height_log2()
109
0
    }
110
111
0
    pub const fn height_log2(self) -> usize {
112
        use crate::data::block::BlockSize::*;
113
114
0
        match self {
115
0
            BLOCK_4X4 | BLOCK_8X4 | BLOCK_16X4 => 2,
116
0
            BLOCK_4X8 | BLOCK_8X8 | BLOCK_16X8 | BLOCK_32X8 => 3,
117
0
            BLOCK_4X16 | BLOCK_8X16 | BLOCK_16X16 | BLOCK_32X16 | BLOCK_64X16 => 4,
118
0
            BLOCK_8X32 | BLOCK_16X32 | BLOCK_32X32 | BLOCK_64X32 => 5,
119
0
            BLOCK_16X64 | BLOCK_32X64 | BLOCK_64X64 | BLOCK_128X64 => 6,
120
0
            BLOCK_64X128 | BLOCK_128X128 => 7,
121
        }
122
0
    }
123
124
0
    pub const fn tx_size(self) -> TxSize {
125
        use crate::data::block::{BlockSize::*, TxSize::*};
126
127
0
        match self {
128
0
            BLOCK_4X4 => TX_4X4,
129
0
            BLOCK_4X8 => TX_4X8,
130
0
            BLOCK_8X4 => TX_8X4,
131
0
            BLOCK_8X8 => TX_8X8,
132
0
            BLOCK_8X16 => TX_8X16,
133
0
            BLOCK_16X8 => TX_16X8,
134
0
            BLOCK_16X16 => TX_16X16,
135
0
            BLOCK_16X32 => TX_16X32,
136
0
            BLOCK_32X16 => TX_32X16,
137
0
            BLOCK_32X32 => TX_32X32,
138
0
            BLOCK_32X64 => TX_32X64,
139
0
            BLOCK_64X32 => TX_64X32,
140
0
            BLOCK_4X16 => TX_4X16,
141
0
            BLOCK_16X4 => TX_16X4,
142
0
            BLOCK_8X32 => TX_8X32,
143
0
            BLOCK_32X8 => TX_32X8,
144
0
            BLOCK_16X64 => TX_16X64,
145
0
            BLOCK_64X16 => TX_64X16,
146
0
            _ => TX_64X64,
147
        }
148
0
    }
149
}
150
151
#[derive(Debug, Copy, Clone, Error, Eq, PartialEq)]
152
pub struct InvalidBlockSize;
153
154
impl Display for InvalidBlockSize {
155
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156
0
        f.write_str("invalid block size")
157
0
    }
158
}
159
160
/// Transform Size
161
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
162
#[allow(non_camel_case_types)]
163
pub 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
187
impl TxSize {
188
0
    pub const fn width(self) -> usize {
189
0
        1 << self.width_log2()
190
0
    }
191
192
0
    pub const fn width_log2(self) -> usize {
193
        use crate::data::block::TxSize::*;
194
0
        match self {
195
0
            TX_4X4 | TX_4X8 | TX_4X16 => 2,
196
0
            TX_8X8 | TX_8X4 | TX_8X16 | TX_8X32 => 3,
197
0
            TX_16X16 | TX_16X8 | TX_16X32 | TX_16X4 | TX_16X64 => 4,
198
0
            TX_32X32 | TX_32X16 | TX_32X64 | TX_32X8 => 5,
199
0
            TX_64X64 | TX_64X32 | TX_64X16 => 6,
200
        }
201
0
    }
202
203
0
    pub const fn height(self) -> usize {
204
0
        1 << self.height_log2()
205
0
    }
206
207
0
    pub const fn height_log2(self) -> usize {
208
        use crate::data::block::TxSize::*;
209
0
        match self {
210
0
            TX_4X4 | TX_8X4 | TX_16X4 => 2,
211
0
            TX_8X8 | TX_4X8 | TX_16X8 | TX_32X8 => 3,
212
0
            TX_16X16 | TX_8X16 | TX_32X16 | TX_4X16 | TX_64X16 => 4,
213
0
            TX_32X32 | TX_16X32 | TX_64X32 | TX_8X32 => 5,
214
0
            TX_64X64 | TX_32X64 | TX_16X64 => 6,
215
        }
216
0
    }
217
}
218
219
/// Absolute offset in blocks, where a block is defined
220
/// to be an `N*N` square where `N == (1 << BLOCK_TO_PLANE_SHIFT)`.
221
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
222
pub struct BlockOffset {
223
    pub x: usize,
224
    pub y: usize,
225
}
226
227
impl BlockOffset {
228
    /// Convert to plane offset without decimation.
229
0
    pub const fn to_luma_plane_offset(self) -> PlaneOffset {
230
0
        PlaneOffset {
231
0
            x: (self.x as isize) << BLOCK_TO_PLANE_SHIFT,
232
0
            y: (self.y as isize) << BLOCK_TO_PLANE_SHIFT,
233
0
        }
234
0
    }
235
236
0
    pub fn with_offset(self, col_offset: isize, row_offset: isize) -> BlockOffset {
237
0
        let x = self.x as isize + col_offset;
238
0
        let y = self.y as isize + row_offset;
239
0
        debug_assert!(x >= 0);
240
0
        debug_assert!(y >= 0);
241
242
0
        BlockOffset {
243
0
            x: x as usize,
244
0
            y: y as usize,
245
0
        }
246
0
    }
247
}
248
249
#[derive(Clone)]
250
pub struct FrameBlocks {
251
    blocks: Box<[Block]>,
252
    pub cols: usize,
253
}
254
255
impl Index<usize> for FrameBlocks {
256
    type Output = [Block];
257
258
0
    fn index(&self, index: usize) -> &Self::Output {
259
0
        &self.blocks[index * self.cols..(index + 1) * self.cols]
260
0
    }
261
}
262
263
impl IndexMut<usize> for FrameBlocks {
264
0
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
265
0
        &mut self.blocks[index * self.cols..(index + 1) * self.cols]
266
0
    }
267
}
268
269
// for convenience, also index by BlockOffset
270
271
impl Index<PlaneBlockOffset> for FrameBlocks {
272
    type Output = Block;
273
274
0
    fn index(&self, bo: PlaneBlockOffset) -> &Self::Output {
275
0
        &self[bo.0.y][bo.0.x]
276
0
    }
277
}
278
279
impl IndexMut<PlaneBlockOffset> for FrameBlocks {
280
0
    fn index_mut(&mut self, bo: PlaneBlockOffset) -> &mut Self::Output {
281
0
        &mut self[bo.0.y][bo.0.x]
282
0
    }
283
}
284
285
#[derive(Copy, Clone, Default)]
286
pub struct Block {}