/rust/registry/src/index.crates.io-1949cf8c6b5b557f/image-webp-0.2.4/src/vp8.rs
Line | Count | Source |
1 | | //! An implementation of the VP8 Video Codec |
2 | | //! |
3 | | //! This module contains a partial implementation of the |
4 | | //! VP8 video format as defined in RFC-6386. |
5 | | //! |
6 | | //! It decodes Keyframes only. |
7 | | //! VP8 is the underpinning of the WebP image format |
8 | | //! |
9 | | //! # Related Links |
10 | | //! * [rfc-6386](http://tools.ietf.org/html/rfc6386) - The VP8 Data Format and Decoding Guide |
11 | | //! * [VP8.pdf](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/37073.pdf) - An overview of of the VP8 format |
12 | | |
13 | | use byteorder_lite::{LittleEndian, ReadBytesExt}; |
14 | | use std::default::Default; |
15 | | use std::io::Read; |
16 | | |
17 | | use crate::decoder::{DecodingError, UpsamplingMethod}; |
18 | | use crate::yuv; |
19 | | |
20 | | use super::vp8_arithmetic_decoder::ArithmeticDecoder; |
21 | | use super::{loop_filter, transform}; |
22 | | |
23 | | const MAX_SEGMENTS: usize = 4; |
24 | | const NUM_DCT_TOKENS: usize = 12; |
25 | | |
26 | | // Prediction modes |
27 | | const DC_PRED: i8 = 0; |
28 | | const V_PRED: i8 = 1; |
29 | | const H_PRED: i8 = 2; |
30 | | const TM_PRED: i8 = 3; |
31 | | const B_PRED: i8 = 4; |
32 | | |
33 | | const B_DC_PRED: i8 = 0; |
34 | | const B_TM_PRED: i8 = 1; |
35 | | const B_VE_PRED: i8 = 2; |
36 | | const B_HE_PRED: i8 = 3; |
37 | | const B_LD_PRED: i8 = 4; |
38 | | const B_RD_PRED: i8 = 5; |
39 | | const B_VR_PRED: i8 = 6; |
40 | | const B_VL_PRED: i8 = 7; |
41 | | const B_HD_PRED: i8 = 8; |
42 | | const B_HU_PRED: i8 = 9; |
43 | | |
44 | | // Prediction mode enum |
45 | | #[repr(i8)] |
46 | | #[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] |
47 | | enum LumaMode { |
48 | | /// Predict DC using row above and column to the left. |
49 | | #[default] |
50 | | DC = DC_PRED, |
51 | | |
52 | | /// Predict rows using row above. |
53 | | V = V_PRED, |
54 | | |
55 | | /// Predict columns using column to the left. |
56 | | H = H_PRED, |
57 | | |
58 | | /// Propagate second differences. |
59 | | TM = TM_PRED, |
60 | | |
61 | | /// Each Y subblock is independently predicted. |
62 | | B = B_PRED, |
63 | | } |
64 | | |
65 | | #[repr(i8)] |
66 | | #[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] |
67 | | enum ChromaMode { |
68 | | /// Predict DC using row above and column to the left. |
69 | | #[default] |
70 | | DC = DC_PRED, |
71 | | |
72 | | /// Predict rows using row above. |
73 | | V = V_PRED, |
74 | | |
75 | | /// Predict columns using column to the left. |
76 | | H = H_PRED, |
77 | | |
78 | | /// Propagate second differences. |
79 | | TM = TM_PRED, |
80 | | } |
81 | | |
82 | | #[repr(i8)] |
83 | | #[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] |
84 | | enum IntraMode { |
85 | | #[default] |
86 | | DC = B_DC_PRED, |
87 | | TM = B_TM_PRED, |
88 | | VE = B_VE_PRED, |
89 | | HE = B_HE_PRED, |
90 | | LD = B_LD_PRED, |
91 | | RD = B_RD_PRED, |
92 | | VR = B_VR_PRED, |
93 | | VL = B_VL_PRED, |
94 | | HD = B_HD_PRED, |
95 | | HU = B_HU_PRED, |
96 | | } |
97 | | |
98 | | type Prob = u8; |
99 | | |
100 | | #[derive(Clone, Copy)] |
101 | | pub(crate) struct TreeNode { |
102 | | pub left: u8, |
103 | | pub right: u8, |
104 | | pub prob: Prob, |
105 | | pub index: u8, |
106 | | } |
107 | | |
108 | | impl TreeNode { |
109 | | const UNINIT: TreeNode = TreeNode { |
110 | | left: 0, |
111 | | right: 0, |
112 | | prob: 0, |
113 | | index: 0, |
114 | | }; |
115 | | |
116 | 0 | const fn prepare_branch(t: i8) -> u8 { |
117 | 0 | if t > 0 { |
118 | 0 | (t as u8) / 2 |
119 | | } else { |
120 | 0 | let value = -t; |
121 | 0 | 0x80 | (value as u8) |
122 | | } |
123 | 0 | } |
124 | | |
125 | 39.7M | pub(crate) const fn value_from_branch(t: u8) -> i8 { |
126 | 39.7M | (t & !0x80) as i8 |
127 | 39.7M | } |
128 | | } |
129 | | |
130 | 0 | const fn tree_nodes_from<const N: usize, const M: usize>( |
131 | 0 | tree: [i8; N], |
132 | 0 | probs: [Prob; M], |
133 | 0 | ) -> [TreeNode; M] { |
134 | 0 | if N != 2 * M { |
135 | 0 | panic!("invalid tree with probs"); |
136 | 0 | } |
137 | 0 | let mut nodes = [TreeNode::UNINIT; M]; |
138 | 0 | let mut i = 0; |
139 | 0 | while i < M { |
140 | 0 | nodes[i].left = TreeNode::prepare_branch(tree[2 * i]); |
141 | 0 | nodes[i].right = TreeNode::prepare_branch(tree[2 * i + 1]); |
142 | 0 | nodes[i].prob = probs[i]; |
143 | 0 | nodes[i].index = i as u8; |
144 | 0 | i += 1; |
145 | 0 | } |
146 | 0 | nodes |
147 | 0 | } |
148 | | |
149 | | const SEGMENT_ID_TREE: [i8; 6] = [2, 4, -0, -1, -2, -3]; |
150 | | |
151 | | const SEGMENT_TREE_NODE_DEFAULTS: [TreeNode; 3] = tree_nodes_from(SEGMENT_ID_TREE, [255; 3]); |
152 | | |
153 | | // Section 11.2 |
154 | | // Tree for determining the keyframe luma intra prediction modes: |
155 | | const KEYFRAME_YMODE_TREE: [i8; 8] = [-B_PRED, 2, 4, 6, -DC_PRED, -V_PRED, -H_PRED, -TM_PRED]; |
156 | | |
157 | | // Default probabilities for decoding the keyframe luma modes |
158 | | const KEYFRAME_YMODE_PROBS: [Prob; 4] = [145, 156, 163, 128]; |
159 | | |
160 | | const KEYFRAME_YMODE_NODES: [TreeNode; 4] = |
161 | | tree_nodes_from(KEYFRAME_YMODE_TREE, KEYFRAME_YMODE_PROBS); |
162 | | |
163 | | // Tree for determining the keyframe B_PRED mode: |
164 | | const KEYFRAME_BPRED_MODE_TREE: [i8; 18] = [ |
165 | | -B_DC_PRED, 2, -B_TM_PRED, 4, -B_VE_PRED, 6, 8, 12, -B_HE_PRED, 10, -B_RD_PRED, -B_VR_PRED, |
166 | | -B_LD_PRED, 14, -B_VL_PRED, 16, -B_HD_PRED, -B_HU_PRED, |
167 | | ]; |
168 | | |
169 | | // Probabilities for the BPRED_MODE_TREE |
170 | | const KEYFRAME_BPRED_MODE_PROBS: [[[Prob; 9]; 10]; 10] = [ |
171 | | [ |
172 | | [231, 120, 48, 89, 115, 113, 120, 152, 112], |
173 | | [152, 179, 64, 126, 170, 118, 46, 70, 95], |
174 | | [175, 69, 143, 80, 85, 82, 72, 155, 103], |
175 | | [56, 58, 10, 171, 218, 189, 17, 13, 152], |
176 | | [144, 71, 10, 38, 171, 213, 144, 34, 26], |
177 | | [114, 26, 17, 163, 44, 195, 21, 10, 173], |
178 | | [121, 24, 80, 195, 26, 62, 44, 64, 85], |
179 | | [170, 46, 55, 19, 136, 160, 33, 206, 71], |
180 | | [63, 20, 8, 114, 114, 208, 12, 9, 226], |
181 | | [81, 40, 11, 96, 182, 84, 29, 16, 36], |
182 | | ], |
183 | | [ |
184 | | [134, 183, 89, 137, 98, 101, 106, 165, 148], |
185 | | [72, 187, 100, 130, 157, 111, 32, 75, 80], |
186 | | [66, 102, 167, 99, 74, 62, 40, 234, 128], |
187 | | [41, 53, 9, 178, 241, 141, 26, 8, 107], |
188 | | [104, 79, 12, 27, 217, 255, 87, 17, 7], |
189 | | [74, 43, 26, 146, 73, 166, 49, 23, 157], |
190 | | [65, 38, 105, 160, 51, 52, 31, 115, 128], |
191 | | [87, 68, 71, 44, 114, 51, 15, 186, 23], |
192 | | [47, 41, 14, 110, 182, 183, 21, 17, 194], |
193 | | [66, 45, 25, 102, 197, 189, 23, 18, 22], |
194 | | ], |
195 | | [ |
196 | | [88, 88, 147, 150, 42, 46, 45, 196, 205], |
197 | | [43, 97, 183, 117, 85, 38, 35, 179, 61], |
198 | | [39, 53, 200, 87, 26, 21, 43, 232, 171], |
199 | | [56, 34, 51, 104, 114, 102, 29, 93, 77], |
200 | | [107, 54, 32, 26, 51, 1, 81, 43, 31], |
201 | | [39, 28, 85, 171, 58, 165, 90, 98, 64], |
202 | | [34, 22, 116, 206, 23, 34, 43, 166, 73], |
203 | | [68, 25, 106, 22, 64, 171, 36, 225, 114], |
204 | | [34, 19, 21, 102, 132, 188, 16, 76, 124], |
205 | | [62, 18, 78, 95, 85, 57, 50, 48, 51], |
206 | | ], |
207 | | [ |
208 | | [193, 101, 35, 159, 215, 111, 89, 46, 111], |
209 | | [60, 148, 31, 172, 219, 228, 21, 18, 111], |
210 | | [112, 113, 77, 85, 179, 255, 38, 120, 114], |
211 | | [40, 42, 1, 196, 245, 209, 10, 25, 109], |
212 | | [100, 80, 8, 43, 154, 1, 51, 26, 71], |
213 | | [88, 43, 29, 140, 166, 213, 37, 43, 154], |
214 | | [61, 63, 30, 155, 67, 45, 68, 1, 209], |
215 | | [142, 78, 78, 16, 255, 128, 34, 197, 171], |
216 | | [41, 40, 5, 102, 211, 183, 4, 1, 221], |
217 | | [51, 50, 17, 168, 209, 192, 23, 25, 82], |
218 | | ], |
219 | | [ |
220 | | [125, 98, 42, 88, 104, 85, 117, 175, 82], |
221 | | [95, 84, 53, 89, 128, 100, 113, 101, 45], |
222 | | [75, 79, 123, 47, 51, 128, 81, 171, 1], |
223 | | [57, 17, 5, 71, 102, 57, 53, 41, 49], |
224 | | [115, 21, 2, 10, 102, 255, 166, 23, 6], |
225 | | [38, 33, 13, 121, 57, 73, 26, 1, 85], |
226 | | [41, 10, 67, 138, 77, 110, 90, 47, 114], |
227 | | [101, 29, 16, 10, 85, 128, 101, 196, 26], |
228 | | [57, 18, 10, 102, 102, 213, 34, 20, 43], |
229 | | [117, 20, 15, 36, 163, 128, 68, 1, 26], |
230 | | ], |
231 | | [ |
232 | | [138, 31, 36, 171, 27, 166, 38, 44, 229], |
233 | | [67, 87, 58, 169, 82, 115, 26, 59, 179], |
234 | | [63, 59, 90, 180, 59, 166, 93, 73, 154], |
235 | | [40, 40, 21, 116, 143, 209, 34, 39, 175], |
236 | | [57, 46, 22, 24, 128, 1, 54, 17, 37], |
237 | | [47, 15, 16, 183, 34, 223, 49, 45, 183], |
238 | | [46, 17, 33, 183, 6, 98, 15, 32, 183], |
239 | | [65, 32, 73, 115, 28, 128, 23, 128, 205], |
240 | | [40, 3, 9, 115, 51, 192, 18, 6, 223], |
241 | | [87, 37, 9, 115, 59, 77, 64, 21, 47], |
242 | | ], |
243 | | [ |
244 | | [104, 55, 44, 218, 9, 54, 53, 130, 226], |
245 | | [64, 90, 70, 205, 40, 41, 23, 26, 57], |
246 | | [54, 57, 112, 184, 5, 41, 38, 166, 213], |
247 | | [30, 34, 26, 133, 152, 116, 10, 32, 134], |
248 | | [75, 32, 12, 51, 192, 255, 160, 43, 51], |
249 | | [39, 19, 53, 221, 26, 114, 32, 73, 255], |
250 | | [31, 9, 65, 234, 2, 15, 1, 118, 73], |
251 | | [88, 31, 35, 67, 102, 85, 55, 186, 85], |
252 | | [56, 21, 23, 111, 59, 205, 45, 37, 192], |
253 | | [55, 38, 70, 124, 73, 102, 1, 34, 98], |
254 | | ], |
255 | | [ |
256 | | [102, 61, 71, 37, 34, 53, 31, 243, 192], |
257 | | [69, 60, 71, 38, 73, 119, 28, 222, 37], |
258 | | [68, 45, 128, 34, 1, 47, 11, 245, 171], |
259 | | [62, 17, 19, 70, 146, 85, 55, 62, 70], |
260 | | [75, 15, 9, 9, 64, 255, 184, 119, 16], |
261 | | [37, 43, 37, 154, 100, 163, 85, 160, 1], |
262 | | [63, 9, 92, 136, 28, 64, 32, 201, 85], |
263 | | [86, 6, 28, 5, 64, 255, 25, 248, 1], |
264 | | [56, 8, 17, 132, 137, 255, 55, 116, 128], |
265 | | [58, 15, 20, 82, 135, 57, 26, 121, 40], |
266 | | ], |
267 | | [ |
268 | | [164, 50, 31, 137, 154, 133, 25, 35, 218], |
269 | | [51, 103, 44, 131, 131, 123, 31, 6, 158], |
270 | | [86, 40, 64, 135, 148, 224, 45, 183, 128], |
271 | | [22, 26, 17, 131, 240, 154, 14, 1, 209], |
272 | | [83, 12, 13, 54, 192, 255, 68, 47, 28], |
273 | | [45, 16, 21, 91, 64, 222, 7, 1, 197], |
274 | | [56, 21, 39, 155, 60, 138, 23, 102, 213], |
275 | | [85, 26, 85, 85, 128, 128, 32, 146, 171], |
276 | | [18, 11, 7, 63, 144, 171, 4, 4, 246], |
277 | | [35, 27, 10, 146, 174, 171, 12, 26, 128], |
278 | | ], |
279 | | [ |
280 | | [190, 80, 35, 99, 180, 80, 126, 54, 45], |
281 | | [85, 126, 47, 87, 176, 51, 41, 20, 32], |
282 | | [101, 75, 128, 139, 118, 146, 116, 128, 85], |
283 | | [56, 41, 15, 176, 236, 85, 37, 9, 62], |
284 | | [146, 36, 19, 30, 171, 255, 97, 27, 20], |
285 | | [71, 30, 17, 119, 118, 255, 17, 18, 138], |
286 | | [101, 38, 60, 138, 55, 70, 43, 26, 142], |
287 | | [138, 45, 61, 62, 219, 1, 81, 188, 64], |
288 | | [32, 41, 20, 117, 151, 142, 20, 21, 163], |
289 | | [112, 19, 12, 61, 195, 128, 48, 4, 24], |
290 | | ], |
291 | | ]; |
292 | | |
293 | | const KEYFRAME_BPRED_MODE_NODES: [[[TreeNode; 9]; 10]; 10] = { |
294 | | let mut output = [[[TreeNode::UNINIT; 9]; 10]; 10]; |
295 | | let mut i = 0; |
296 | | while i < output.len() { |
297 | | let mut j = 0; |
298 | | while j < output[i].len() { |
299 | | output[i][j] = |
300 | | tree_nodes_from(KEYFRAME_BPRED_MODE_TREE, KEYFRAME_BPRED_MODE_PROBS[i][j]); |
301 | | j += 1; |
302 | | } |
303 | | i += 1; |
304 | | } |
305 | | output |
306 | | }; |
307 | | |
308 | | // Section 11.4 Tree for determining macroblock the chroma mode |
309 | | const KEYFRAME_UV_MODE_TREE: [i8; 6] = [-DC_PRED, 2, -V_PRED, 4, -H_PRED, -TM_PRED]; |
310 | | |
311 | | // Probabilities for determining macroblock mode |
312 | | const KEYFRAME_UV_MODE_PROBS: [Prob; 3] = [142, 114, 183]; |
313 | | |
314 | | const KEYFRAME_UV_MODE_NODES: [TreeNode; 3] = |
315 | | tree_nodes_from(KEYFRAME_UV_MODE_TREE, KEYFRAME_UV_MODE_PROBS); |
316 | | |
317 | | // Section 13.4 |
318 | | type TokenProbTables = [[[[Prob; NUM_DCT_TOKENS - 1]; 3]; 8]; 4]; |
319 | | type TokenProbTreeNodes = [[[[TreeNode; NUM_DCT_TOKENS - 1]; 3]; 8]; 4]; |
320 | | |
321 | | // Probabilities that a token's probability will be updated |
322 | | const COEFF_UPDATE_PROBS: TokenProbTables = [ |
323 | | [ |
324 | | [ |
325 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
326 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
327 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
328 | | ], |
329 | | [ |
330 | | [176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
331 | | [223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255], |
332 | | [249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255], |
333 | | ], |
334 | | [ |
335 | | [255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255], |
336 | | [234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
337 | | [253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
338 | | ], |
339 | | [ |
340 | | [255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
341 | | [239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
342 | | [254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
343 | | ], |
344 | | [ |
345 | | [255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
346 | | [251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
347 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
348 | | ], |
349 | | [ |
350 | | [255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
351 | | [251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
352 | | [254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
353 | | ], |
354 | | [ |
355 | | [255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255], |
356 | | [250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255], |
357 | | [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
358 | | ], |
359 | | [ |
360 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
361 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
362 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
363 | | ], |
364 | | ], |
365 | | [ |
366 | | [ |
367 | | [217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
368 | | [225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255], |
369 | | [234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255], |
370 | | ], |
371 | | [ |
372 | | [255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
373 | | [223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
374 | | [238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255], |
375 | | ], |
376 | | [ |
377 | | [255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
378 | | [249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
379 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
380 | | ], |
381 | | [ |
382 | | [255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
383 | | [247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
384 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
385 | | ], |
386 | | [ |
387 | | [255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
388 | | [252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
389 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
390 | | ], |
391 | | [ |
392 | | [255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
393 | | [253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
394 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
395 | | ], |
396 | | [ |
397 | | [255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255], |
398 | | [250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
399 | | [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
400 | | ], |
401 | | [ |
402 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
403 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
404 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
405 | | ], |
406 | | ], |
407 | | [ |
408 | | [ |
409 | | [186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255], |
410 | | [234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255], |
411 | | [251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255], |
412 | | ], |
413 | | [ |
414 | | [255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
415 | | [236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
416 | | [251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255], |
417 | | ], |
418 | | [ |
419 | | [255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
420 | | [254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
421 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
422 | | ], |
423 | | [ |
424 | | [255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
425 | | [254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
426 | | [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
427 | | ], |
428 | | [ |
429 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
430 | | [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
431 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
432 | | ], |
433 | | [ |
434 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
435 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
436 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
437 | | ], |
438 | | [ |
439 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
440 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
441 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
442 | | ], |
443 | | [ |
444 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
445 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
446 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
447 | | ], |
448 | | ], |
449 | | [ |
450 | | [ |
451 | | [248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
452 | | [250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255], |
453 | | [248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255], |
454 | | ], |
455 | | [ |
456 | | [255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255], |
457 | | [246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255], |
458 | | [252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255], |
459 | | ], |
460 | | [ |
461 | | [255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255], |
462 | | [248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255], |
463 | | [253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255], |
464 | | ], |
465 | | [ |
466 | | [255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
467 | | [245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
468 | | [253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
469 | | ], |
470 | | [ |
471 | | [255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255], |
472 | | [252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
473 | | [255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
474 | | ], |
475 | | [ |
476 | | [255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
477 | | [249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
478 | | [255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255], |
479 | | ], |
480 | | [ |
481 | | [255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255], |
482 | | [250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
483 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
484 | | ], |
485 | | [ |
486 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
487 | | [254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
488 | | [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], |
489 | | ], |
490 | | ], |
491 | | ]; |
492 | | |
493 | | // Section 13.5 |
494 | | // Default Probabilities for tokens |
495 | | const COEFF_PROBS: TokenProbTables = [ |
496 | | [ |
497 | | [ |
498 | | [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], |
499 | | [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], |
500 | | [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], |
501 | | ], |
502 | | [ |
503 | | [253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128], |
504 | | [189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128], |
505 | | [106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128], |
506 | | ], |
507 | | [ |
508 | | [1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128], |
509 | | [181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128], |
510 | | [78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128], |
511 | | ], |
512 | | [ |
513 | | [1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128], |
514 | | [184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128], |
515 | | [77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128], |
516 | | ], |
517 | | [ |
518 | | [1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128], |
519 | | [170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128], |
520 | | [37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128], |
521 | | ], |
522 | | [ |
523 | | [1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128], |
524 | | [207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128], |
525 | | [102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128], |
526 | | ], |
527 | | [ |
528 | | [1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128], |
529 | | [177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128], |
530 | | [80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128], |
531 | | ], |
532 | | [ |
533 | | [1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128], |
534 | | [246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128], |
535 | | [255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], |
536 | | ], |
537 | | ], |
538 | | [ |
539 | | [ |
540 | | [198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62], |
541 | | [131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1], |
542 | | [68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128], |
543 | | ], |
544 | | [ |
545 | | [1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128], |
546 | | [184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128], |
547 | | [81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128], |
548 | | ], |
549 | | [ |
550 | | [1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128], |
551 | | [99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128], |
552 | | [23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128], |
553 | | ], |
554 | | [ |
555 | | [1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128], |
556 | | [109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128], |
557 | | [44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128], |
558 | | ], |
559 | | [ |
560 | | [1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128], |
561 | | [94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128], |
562 | | [22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128], |
563 | | ], |
564 | | [ |
565 | | [1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128], |
566 | | [124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128], |
567 | | [35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128], |
568 | | ], |
569 | | [ |
570 | | [1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128], |
571 | | [121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128], |
572 | | [45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128], |
573 | | ], |
574 | | [ |
575 | | [1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128], |
576 | | [203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128], |
577 | | [137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128], |
578 | | ], |
579 | | ], |
580 | | [ |
581 | | [ |
582 | | [253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128], |
583 | | [175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128], |
584 | | [73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128], |
585 | | ], |
586 | | [ |
587 | | [1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128], |
588 | | [239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128], |
589 | | [155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128], |
590 | | ], |
591 | | [ |
592 | | [1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128], |
593 | | [201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128], |
594 | | [69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128], |
595 | | ], |
596 | | [ |
597 | | [1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128], |
598 | | [223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128], |
599 | | [141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128], |
600 | | ], |
601 | | [ |
602 | | [1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128], |
603 | | [190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128], |
604 | | [149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128], |
605 | | ], |
606 | | [ |
607 | | [1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128], |
608 | | [247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128], |
609 | | [240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128], |
610 | | ], |
611 | | [ |
612 | | [1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128], |
613 | | [213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128], |
614 | | [55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128], |
615 | | ], |
616 | | [ |
617 | | [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], |
618 | | [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], |
619 | | [128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128], |
620 | | ], |
621 | | ], |
622 | | [ |
623 | | [ |
624 | | [202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255], |
625 | | [126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128], |
626 | | [61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128], |
627 | | ], |
628 | | [ |
629 | | [1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128], |
630 | | [166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128], |
631 | | [39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128], |
632 | | ], |
633 | | [ |
634 | | [1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128], |
635 | | [124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128], |
636 | | [24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128], |
637 | | ], |
638 | | [ |
639 | | [1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128], |
640 | | [149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128], |
641 | | [28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128], |
642 | | ], |
643 | | [ |
644 | | [1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128], |
645 | | [123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128], |
646 | | [20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128], |
647 | | ], |
648 | | [ |
649 | | [1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128], |
650 | | [168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128], |
651 | | [47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128], |
652 | | ], |
653 | | [ |
654 | | [1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128], |
655 | | [141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128], |
656 | | [42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128], |
657 | | ], |
658 | | [ |
659 | | [1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128], |
660 | | [244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128], |
661 | | [238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128], |
662 | | ], |
663 | | ], |
664 | | ]; |
665 | | |
666 | | const COEFF_PROB_NODES: TokenProbTreeNodes = { |
667 | | let mut output = [[[[TreeNode::UNINIT; 11]; 3]; 8]; 4]; |
668 | | let mut i = 0; |
669 | | while i < output.len() { |
670 | | let mut j = 0; |
671 | | while j < output[i].len() { |
672 | | let mut k = 0; |
673 | | while k < output[i][j].len() { |
674 | | output[i][j][k] = tree_nodes_from(DCT_TOKEN_TREE, COEFF_PROBS[i][j][k]); |
675 | | k += 1; |
676 | | } |
677 | | j += 1; |
678 | | } |
679 | | i += 1; |
680 | | } |
681 | | output |
682 | | }; |
683 | | |
684 | | // DCT Tokens |
685 | | const DCT_0: i8 = 0; |
686 | | const DCT_1: i8 = 1; |
687 | | const DCT_2: i8 = 2; |
688 | | const DCT_3: i8 = 3; |
689 | | const DCT_4: i8 = 4; |
690 | | const DCT_CAT1: i8 = 5; |
691 | | const DCT_CAT2: i8 = 6; |
692 | | const DCT_CAT3: i8 = 7; |
693 | | const DCT_CAT4: i8 = 8; |
694 | | const DCT_CAT5: i8 = 9; |
695 | | const DCT_CAT6: i8 = 10; |
696 | | const DCT_EOB: i8 = 11; |
697 | | |
698 | | const DCT_TOKEN_TREE: [i8; 22] = [ |
699 | | -DCT_EOB, 2, -DCT_0, 4, -DCT_1, 6, 8, 12, -DCT_2, 10, -DCT_3, -DCT_4, 14, 16, -DCT_CAT1, |
700 | | -DCT_CAT2, 18, 20, -DCT_CAT3, -DCT_CAT4, -DCT_CAT5, -DCT_CAT6, |
701 | | ]; |
702 | | |
703 | | const PROB_DCT_CAT: [[Prob; 12]; 6] = [ |
704 | | [159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], |
705 | | [165, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], |
706 | | [173, 148, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0], |
707 | | [176, 155, 140, 135, 0, 0, 0, 0, 0, 0, 0, 0], |
708 | | [180, 157, 141, 134, 130, 0, 0, 0, 0, 0, 0, 0], |
709 | | [254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0], |
710 | | ]; |
711 | | |
712 | | const DCT_CAT_BASE: [u8; 6] = [5, 7, 11, 19, 35, 67]; |
713 | | const COEFF_BANDS: [u8; 16] = [0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7]; |
714 | | |
715 | | #[rustfmt::skip] |
716 | | const DC_QUANT: [i16; 128] = [ |
717 | | 4, 5, 6, 7, 8, 9, 10, 10, |
718 | | 11, 12, 13, 14, 15, 16, 17, 17, |
719 | | 18, 19, 20, 20, 21, 21, 22, 22, |
720 | | 23, 23, 24, 25, 25, 26, 27, 28, |
721 | | 29, 30, 31, 32, 33, 34, 35, 36, |
722 | | 37, 37, 38, 39, 40, 41, 42, 43, |
723 | | 44, 45, 46, 46, 47, 48, 49, 50, |
724 | | 51, 52, 53, 54, 55, 56, 57, 58, |
725 | | 59, 60, 61, 62, 63, 64, 65, 66, |
726 | | 67, 68, 69, 70, 71, 72, 73, 74, |
727 | | 75, 76, 76, 77, 78, 79, 80, 81, |
728 | | 82, 83, 84, 85, 86, 87, 88, 89, |
729 | | 91, 93, 95, 96, 98, 100, 101, 102, |
730 | | 104, 106, 108, 110, 112, 114, 116, 118, |
731 | | 122, 124, 126, 128, 130, 132, 134, 136, |
732 | | 138, 140, 143, 145, 148, 151, 154, 157, |
733 | | ]; |
734 | | |
735 | | #[rustfmt::skip] |
736 | | const AC_QUANT: [i16; 128] = [ |
737 | | 4, 5, 6, 7, 8, 9, 10, 11, |
738 | | 12, 13, 14, 15, 16, 17, 18, 19, |
739 | | 20, 21, 22, 23, 24, 25, 26, 27, |
740 | | 28, 29, 30, 31, 32, 33, 34, 35, |
741 | | 36, 37, 38, 39, 40, 41, 42, 43, |
742 | | 44, 45, 46, 47, 48, 49, 50, 51, |
743 | | 52, 53, 54, 55, 56, 57, 58, 60, |
744 | | 62, 64, 66, 68, 70, 72, 74, 76, |
745 | | 78, 80, 82, 84, 86, 88, 90, 92, |
746 | | 94, 96, 98, 100, 102, 104, 106, 108, |
747 | | 110, 112, 114, 116, 119, 122, 125, 128, |
748 | | 131, 134, 137, 140, 143, 146, 149, 152, |
749 | | 155, 158, 161, 164, 167, 170, 173, 177, |
750 | | 181, 185, 189, 193, 197, 201, 205, 209, |
751 | | 213, 217, 221, 225, 229, 234, 239, 245, |
752 | | 249, 254, 259, 264, 269, 274, 279, 284, |
753 | | ]; |
754 | | |
755 | | const ZIGZAG: [u8; 16] = [0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15]; |
756 | | |
757 | | #[derive(Default, Clone, Copy)] |
758 | | struct MacroBlock { |
759 | | bpred: [IntraMode; 16], |
760 | | complexity: [u8; 9], |
761 | | luma_mode: LumaMode, |
762 | | chroma_mode: ChromaMode, |
763 | | segmentid: u8, |
764 | | coeffs_skipped: bool, |
765 | | non_zero_dct: bool, |
766 | | } |
767 | | |
768 | | /// A Representation of the last decoded video frame |
769 | | #[derive(Default, Debug, Clone)] |
770 | | pub struct Frame { |
771 | | /// The width of the luma plane |
772 | | pub width: u16, |
773 | | |
774 | | /// The height of the luma plane |
775 | | pub height: u16, |
776 | | |
777 | | /// The luma plane of the frame |
778 | | pub ybuf: Vec<u8>, |
779 | | |
780 | | /// The blue plane of the frame |
781 | | pub ubuf: Vec<u8>, |
782 | | |
783 | | /// The red plane of the frame |
784 | | pub vbuf: Vec<u8>, |
785 | | |
786 | | /// Indicates whether this frame is a keyframe |
787 | | pub keyframe: bool, |
788 | | |
789 | | version: u8, |
790 | | |
791 | | /// Indicates whether this frame is intended for display |
792 | | pub for_display: bool, |
793 | | |
794 | | // Section 9.2 |
795 | | /// The pixel type of the frame as defined by Section 9.2 |
796 | | /// of the VP8 Specification |
797 | | pub pixel_type: u8, |
798 | | |
799 | | // Section 9.4 and 15 |
800 | | filter_type: bool, //if true uses simple filter // if false uses normal filter |
801 | | filter_level: u8, |
802 | | sharpness_level: u8, |
803 | | } |
804 | | |
805 | | impl Frame { |
806 | 0 | const fn chroma_width(&self) -> u16 { |
807 | 0 | self.width.div_ceil(2) |
808 | 0 | } |
809 | | |
810 | 1.11k | const fn buffer_width(&self) -> u16 { |
811 | 1.11k | let difference = self.width % 16; |
812 | 1.11k | if difference > 0 { |
813 | 886 | self.width + (16 - difference % 16) |
814 | | } else { |
815 | 230 | self.width |
816 | | } |
817 | 1.11k | } |
818 | | |
819 | | /// Fills an rgb buffer from the YUV buffers |
820 | 622 | pub(crate) fn fill_rgb(&self, buf: &mut [u8], upsampling_method: UpsamplingMethod) { |
821 | | const BPP: usize = 3; |
822 | | |
823 | 622 | match upsampling_method { |
824 | 622 | UpsamplingMethod::Bilinear => { |
825 | 622 | yuv::fill_rgb_buffer_fancy::<BPP>( |
826 | 622 | buf, |
827 | 622 | &self.ybuf, |
828 | 622 | &self.ubuf, |
829 | 622 | &self.vbuf, |
830 | 622 | usize::from(self.width), |
831 | 622 | usize::from(self.height), |
832 | 622 | usize::from(self.buffer_width()), |
833 | 622 | ); |
834 | 622 | } |
835 | 0 | UpsamplingMethod::Simple => { |
836 | 0 | yuv::fill_rgb_buffer_simple::<BPP>( |
837 | 0 | buf, |
838 | 0 | &self.ybuf, |
839 | 0 | &self.ubuf, |
840 | 0 | &self.vbuf, |
841 | 0 | usize::from(self.width), |
842 | 0 | usize::from(self.chroma_width()), |
843 | 0 | usize::from(self.buffer_width()), |
844 | 0 | ); |
845 | 0 | } |
846 | | } |
847 | 622 | } |
848 | | |
849 | | /// Fills an rgba buffer from the YUV buffers |
850 | 494 | pub(crate) fn fill_rgba(&self, buf: &mut [u8], upsampling_method: UpsamplingMethod) { |
851 | | const BPP: usize = 4; |
852 | | |
853 | 494 | match upsampling_method { |
854 | 494 | UpsamplingMethod::Bilinear => { |
855 | 494 | yuv::fill_rgb_buffer_fancy::<BPP>( |
856 | 494 | buf, |
857 | 494 | &self.ybuf, |
858 | 494 | &self.ubuf, |
859 | 494 | &self.vbuf, |
860 | 494 | usize::from(self.width), |
861 | 494 | usize::from(self.height), |
862 | 494 | usize::from(self.buffer_width()), |
863 | 494 | ); |
864 | 494 | } |
865 | 0 | UpsamplingMethod::Simple => { |
866 | 0 | yuv::fill_rgb_buffer_simple::<BPP>( |
867 | 0 | buf, |
868 | 0 | &self.ybuf, |
869 | 0 | &self.ubuf, |
870 | 0 | &self.vbuf, |
871 | 0 | usize::from(self.width), |
872 | 0 | usize::from(self.chroma_width()), |
873 | 0 | usize::from(self.buffer_width()), |
874 | 0 | ); |
875 | 0 | } |
876 | | } |
877 | 494 | } |
878 | | /// Gets the buffer size |
879 | | #[must_use] |
880 | 0 | pub fn get_buf_size(&self) -> usize { |
881 | 0 | self.ybuf.len() * 3 |
882 | 0 | } |
883 | | } |
884 | | |
885 | | #[derive(Clone, Copy, Default)] |
886 | | struct Segment { |
887 | | ydc: i16, |
888 | | yac: i16, |
889 | | |
890 | | y2dc: i16, |
891 | | y2ac: i16, |
892 | | |
893 | | uvdc: i16, |
894 | | uvac: i16, |
895 | | |
896 | | delta_values: bool, |
897 | | |
898 | | quantizer_level: i8, |
899 | | loopfilter_level: i8, |
900 | | } |
901 | | |
902 | | /// VP8 Decoder |
903 | | /// |
904 | | /// Only decodes keyframes |
905 | | pub struct Vp8Decoder<R> { |
906 | | r: R, |
907 | | b: ArithmeticDecoder, |
908 | | |
909 | | mbwidth: u16, |
910 | | mbheight: u16, |
911 | | macroblocks: Vec<MacroBlock>, |
912 | | |
913 | | frame: Frame, |
914 | | |
915 | | segments_enabled: bool, |
916 | | segments_update_map: bool, |
917 | | segment: [Segment; MAX_SEGMENTS], |
918 | | |
919 | | loop_filter_adjustments_enabled: bool, |
920 | | ref_delta: [i32; 4], |
921 | | mode_delta: [i32; 4], |
922 | | |
923 | | partitions: [ArithmeticDecoder; 8], |
924 | | num_partitions: u8, |
925 | | |
926 | | segment_tree_nodes: [TreeNode; 3], |
927 | | token_probs: Box<TokenProbTreeNodes>, |
928 | | |
929 | | // Section 9.10 |
930 | | prob_intra: Prob, |
931 | | |
932 | | // Section 9.11 |
933 | | prob_skip_false: Option<Prob>, |
934 | | |
935 | | top: Vec<MacroBlock>, |
936 | | left: MacroBlock, |
937 | | |
938 | | // The borders from the previous macroblock, used for predictions |
939 | | // See Section 12 |
940 | | // Note that the left border contains the top left pixel |
941 | | top_border_y: Vec<u8>, |
942 | | left_border_y: Vec<u8>, |
943 | | |
944 | | top_border_u: Vec<u8>, |
945 | | left_border_u: Vec<u8>, |
946 | | |
947 | | top_border_v: Vec<u8>, |
948 | | left_border_v: Vec<u8>, |
949 | | } |
950 | | |
951 | | impl<R: Read> Vp8Decoder<R> { |
952 | | /// Create a new decoder. |
953 | | /// The reader must present a raw vp8 bitstream to the decoder |
954 | 2.67k | fn new(r: R) -> Self { |
955 | 2.67k | let f = Frame::default(); |
956 | 2.67k | let s = Segment::default(); |
957 | 2.67k | let m = MacroBlock::default(); |
958 | | |
959 | 2.67k | Self { |
960 | 2.67k | r, |
961 | 2.67k | b: ArithmeticDecoder::new(), |
962 | 2.67k | |
963 | 2.67k | mbwidth: 0, |
964 | 2.67k | mbheight: 0, |
965 | 2.67k | macroblocks: Vec::new(), |
966 | 2.67k | |
967 | 2.67k | frame: f, |
968 | 2.67k | segments_enabled: false, |
969 | 2.67k | segments_update_map: false, |
970 | 2.67k | segment: [s; MAX_SEGMENTS], |
971 | 2.67k | |
972 | 2.67k | loop_filter_adjustments_enabled: false, |
973 | 2.67k | ref_delta: [0; 4], |
974 | 2.67k | mode_delta: [0; 4], |
975 | 2.67k | |
976 | 2.67k | partitions: [ |
977 | 2.67k | ArithmeticDecoder::new(), |
978 | 2.67k | ArithmeticDecoder::new(), |
979 | 2.67k | ArithmeticDecoder::new(), |
980 | 2.67k | ArithmeticDecoder::new(), |
981 | 2.67k | ArithmeticDecoder::new(), |
982 | 2.67k | ArithmeticDecoder::new(), |
983 | 2.67k | ArithmeticDecoder::new(), |
984 | 2.67k | ArithmeticDecoder::new(), |
985 | 2.67k | ], |
986 | 2.67k | |
987 | 2.67k | num_partitions: 1, |
988 | 2.67k | |
989 | 2.67k | segment_tree_nodes: SEGMENT_TREE_NODE_DEFAULTS, |
990 | 2.67k | token_probs: Box::new(COEFF_PROB_NODES), |
991 | 2.67k | |
992 | 2.67k | // Section 9.10 |
993 | 2.67k | prob_intra: 0u8, |
994 | 2.67k | |
995 | 2.67k | // Section 9.11 |
996 | 2.67k | prob_skip_false: None, |
997 | 2.67k | |
998 | 2.67k | top: Vec::new(), |
999 | 2.67k | left: m, |
1000 | 2.67k | |
1001 | 2.67k | top_border_y: Vec::new(), |
1002 | 2.67k | left_border_y: Vec::new(), |
1003 | 2.67k | |
1004 | 2.67k | top_border_u: Vec::new(), |
1005 | 2.67k | left_border_u: Vec::new(), |
1006 | 2.67k | |
1007 | 2.67k | top_border_v: Vec::new(), |
1008 | 2.67k | left_border_v: Vec::new(), |
1009 | 2.67k | } |
1010 | 2.67k | } <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Line | Count | Source | 954 | 2.67k | fn new(r: R) -> Self { | 955 | 2.67k | let f = Frame::default(); | 956 | 2.67k | let s = Segment::default(); | 957 | 2.67k | let m = MacroBlock::default(); | 958 | | | 959 | 2.67k | Self { | 960 | 2.67k | r, | 961 | 2.67k | b: ArithmeticDecoder::new(), | 962 | 2.67k | | 963 | 2.67k | mbwidth: 0, | 964 | 2.67k | mbheight: 0, | 965 | 2.67k | macroblocks: Vec::new(), | 966 | 2.67k | | 967 | 2.67k | frame: f, | 968 | 2.67k | segments_enabled: false, | 969 | 2.67k | segments_update_map: false, | 970 | 2.67k | segment: [s; MAX_SEGMENTS], | 971 | 2.67k | | 972 | 2.67k | loop_filter_adjustments_enabled: false, | 973 | 2.67k | ref_delta: [0; 4], | 974 | 2.67k | mode_delta: [0; 4], | 975 | 2.67k | | 976 | 2.67k | partitions: [ | 977 | 2.67k | ArithmeticDecoder::new(), | 978 | 2.67k | ArithmeticDecoder::new(), | 979 | 2.67k | ArithmeticDecoder::new(), | 980 | 2.67k | ArithmeticDecoder::new(), | 981 | 2.67k | ArithmeticDecoder::new(), | 982 | 2.67k | ArithmeticDecoder::new(), | 983 | 2.67k | ArithmeticDecoder::new(), | 984 | 2.67k | ArithmeticDecoder::new(), | 985 | 2.67k | ], | 986 | 2.67k | | 987 | 2.67k | num_partitions: 1, | 988 | 2.67k | | 989 | 2.67k | segment_tree_nodes: SEGMENT_TREE_NODE_DEFAULTS, | 990 | 2.67k | token_probs: Box::new(COEFF_PROB_NODES), | 991 | 2.67k | | 992 | 2.67k | // Section 9.10 | 993 | 2.67k | prob_intra: 0u8, | 994 | 2.67k | | 995 | 2.67k | // Section 9.11 | 996 | 2.67k | prob_skip_false: None, | 997 | 2.67k | | 998 | 2.67k | top: Vec::new(), | 999 | 2.67k | left: m, | 1000 | 2.67k | | 1001 | 2.67k | top_border_y: Vec::new(), | 1002 | 2.67k | left_border_y: Vec::new(), | 1003 | 2.67k | | 1004 | 2.67k | top_border_u: Vec::new(), | 1005 | 2.67k | left_border_u: Vec::new(), | 1006 | 2.67k | | 1007 | 2.67k | top_border_v: Vec::new(), | 1008 | 2.67k | left_border_v: Vec::new(), | 1009 | 2.67k | } | 1010 | 2.67k | } |
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::new |
1011 | | |
1012 | 2.29k | fn update_token_probabilities(&mut self) -> Result<(), DecodingError> { |
1013 | 2.29k | let mut res = self.b.start_accumulated_result(); |
1014 | 9.19k | for (i, is) in COEFF_UPDATE_PROBS.iter().enumerate() { |
1015 | 73.5k | for (j, js) in is.iter().enumerate() { |
1016 | 220k | for (k, ks) in js.iter().enumerate() { |
1017 | 2.42M | for (t, prob) in ks.iter().enumerate().take(NUM_DCT_TOKENS - 1) { |
1018 | 2.42M | if self.b.read_bool(*prob).or_accumulate(&mut res) { |
1019 | 36.1k | let v = self.b.read_literal(8).or_accumulate(&mut res); |
1020 | 36.1k | self.token_probs[i][j][k][t].prob = v; |
1021 | 2.39M | } |
1022 | | } |
1023 | | } |
1024 | | } |
1025 | | } |
1026 | 2.29k | self.b.check(res, ()) |
1027 | 2.29k | } <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::update_token_probabilities Line | Count | Source | 1012 | 2.29k | fn update_token_probabilities(&mut self) -> Result<(), DecodingError> { | 1013 | 2.29k | let mut res = self.b.start_accumulated_result(); | 1014 | 9.19k | for (i, is) in COEFF_UPDATE_PROBS.iter().enumerate() { | 1015 | 73.5k | for (j, js) in is.iter().enumerate() { | 1016 | 220k | for (k, ks) in js.iter().enumerate() { | 1017 | 2.42M | for (t, prob) in ks.iter().enumerate().take(NUM_DCT_TOKENS - 1) { | 1018 | 2.42M | if self.b.read_bool(*prob).or_accumulate(&mut res) { | 1019 | 36.1k | let v = self.b.read_literal(8).or_accumulate(&mut res); | 1020 | 36.1k | self.token_probs[i][j][k][t].prob = v; | 1021 | 2.39M | } | 1022 | | } | 1023 | | } | 1024 | | } | 1025 | | } | 1026 | 2.29k | self.b.check(res, ()) | 1027 | 2.29k | } |
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::update_token_probabilities |
1028 | | |
1029 | 2.49k | fn init_partitions(&mut self, n: usize) -> Result<(), DecodingError> { |
1030 | 2.49k | if n > 1 { |
1031 | 138 | let mut sizes = vec![0; 3 * n - 3]; |
1032 | 138 | self.r.read_exact(sizes.as_mut_slice())?; |
1033 | | |
1034 | 284 | for (i, s) in sizes.chunks(3).enumerate() { |
1035 | 284 | let size = { s } |
1036 | 284 | .read_u24::<LittleEndian>() |
1037 | 284 | .expect("Reading from &[u8] can't fail and the chunk is complete"); |
1038 | | |
1039 | 284 | let size = size as usize; |
1040 | 284 | let mut buf = vec![[0; 4]; size.div_ceil(4)]; |
1041 | 284 | let bytes: &mut [u8] = buf.as_mut_slice().as_flattened_mut(); |
1042 | 284 | self.r.read_exact(&mut bytes[..size])?; |
1043 | 207 | self.partitions[i].init(buf, size)?; |
1044 | | } |
1045 | 2.35k | } |
1046 | | |
1047 | 2.40k | let mut buf = Vec::new(); |
1048 | 2.40k | self.r.read_to_end(&mut buf)?; |
1049 | 2.40k | let size = buf.len(); |
1050 | 2.40k | let mut chunks = vec![[0; 4]; size.div_ceil(4)]; |
1051 | 2.40k | chunks.as_mut_slice().as_flattened_mut()[..size].copy_from_slice(&buf); |
1052 | 2.40k | self.partitions[n - 1].init(chunks, size)?; |
1053 | | |
1054 | 2.40k | Ok(()) |
1055 | 2.49k | } <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::init_partitions Line | Count | Source | 1029 | 2.49k | fn init_partitions(&mut self, n: usize) -> Result<(), DecodingError> { | 1030 | 2.49k | if n > 1 { | 1031 | 138 | let mut sizes = vec![0; 3 * n - 3]; | 1032 | 138 | self.r.read_exact(sizes.as_mut_slice())?; | 1033 | | | 1034 | 284 | for (i, s) in sizes.chunks(3).enumerate() { | 1035 | 284 | let size = { s } | 1036 | 284 | .read_u24::<LittleEndian>() | 1037 | 284 | .expect("Reading from &[u8] can't fail and the chunk is complete"); | 1038 | | | 1039 | 284 | let size = size as usize; | 1040 | 284 | let mut buf = vec![[0; 4]; size.div_ceil(4)]; | 1041 | 284 | let bytes: &mut [u8] = buf.as_mut_slice().as_flattened_mut(); | 1042 | 284 | self.r.read_exact(&mut bytes[..size])?; | 1043 | 207 | self.partitions[i].init(buf, size)?; | 1044 | | } | 1045 | 2.35k | } | 1046 | | | 1047 | 2.40k | let mut buf = Vec::new(); | 1048 | 2.40k | self.r.read_to_end(&mut buf)?; | 1049 | 2.40k | let size = buf.len(); | 1050 | 2.40k | let mut chunks = vec![[0; 4]; size.div_ceil(4)]; | 1051 | 2.40k | chunks.as_mut_slice().as_flattened_mut()[..size].copy_from_slice(&buf); | 1052 | 2.40k | self.partitions[n - 1].init(chunks, size)?; | 1053 | | | 1054 | 2.40k | Ok(()) | 1055 | 2.49k | } |
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::init_partitions |
1056 | | |
1057 | 2.40k | fn read_quantization_indices(&mut self) -> Result<(), DecodingError> { |
1058 | 11.8k | fn dc_quant(index: i32) -> i16 { |
1059 | 11.8k | DC_QUANT[index.clamp(0, 127) as usize] |
1060 | 11.8k | } |
1061 | | |
1062 | 11.8k | fn ac_quant(index: i32) -> i16 { |
1063 | 11.8k | AC_QUANT[index.clamp(0, 127) as usize] |
1064 | 11.8k | } |
1065 | | |
1066 | 2.40k | let mut res = self.b.start_accumulated_result(); |
1067 | | |
1068 | 2.40k | let yac_abs = self.b.read_literal(7).or_accumulate(&mut res); |
1069 | 2.40k | let ydc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res); |
1070 | 2.40k | let y2dc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res); |
1071 | 2.40k | let y2ac_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res); |
1072 | 2.40k | let uvdc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res); |
1073 | 2.40k | let uvac_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res); |
1074 | | |
1075 | 2.40k | let n = if self.segments_enabled { |
1076 | 518 | MAX_SEGMENTS |
1077 | | } else { |
1078 | 1.88k | 1 |
1079 | | }; |
1080 | 3.95k | for i in 0usize..n { |
1081 | 3.95k | let base = i32::from(if self.segments_enabled { |
1082 | 2.07k | if self.segment[i].delta_values { |
1083 | 516 | i16::from(self.segment[i].quantizer_level) + i16::from(yac_abs) |
1084 | | } else { |
1085 | 1.55k | i16::from(self.segment[i].quantizer_level) |
1086 | | } |
1087 | | } else { |
1088 | 1.88k | i16::from(yac_abs) |
1089 | | }); |
1090 | | |
1091 | 3.95k | self.segment[i].ydc = dc_quant(base + ydc_delta); |
1092 | 3.95k | self.segment[i].yac = ac_quant(base); |
1093 | | |
1094 | 3.95k | self.segment[i].y2dc = dc_quant(base + y2dc_delta) * 2; |
1095 | | // The intermediate result (max`284*155`) can be larger than the `i16` range. |
1096 | 3.95k | self.segment[i].y2ac = (i32::from(ac_quant(base + y2ac_delta)) * 155 / 100) as i16; |
1097 | | |
1098 | 3.95k | self.segment[i].uvdc = dc_quant(base + uvdc_delta); |
1099 | 3.95k | self.segment[i].uvac = ac_quant(base + uvac_delta); |
1100 | | |
1101 | 3.95k | if self.segment[i].y2ac < 8 { |
1102 | 1.70k | self.segment[i].y2ac = 8; |
1103 | 2.25k | } |
1104 | | |
1105 | 3.95k | if self.segment[i].uvdc > 132 { |
1106 | 334 | self.segment[i].uvdc = 132; |
1107 | 3.62k | } |
1108 | | } |
1109 | | |
1110 | 2.40k | self.b.check(res, ()) |
1111 | 2.40k | } <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_quantization_indices Line | Count | Source | 1057 | 2.40k | fn read_quantization_indices(&mut self) -> Result<(), DecodingError> { | 1058 | | fn dc_quant(index: i32) -> i16 { | 1059 | | DC_QUANT[index.clamp(0, 127) as usize] | 1060 | | } | 1061 | | | 1062 | | fn ac_quant(index: i32) -> i16 { | 1063 | | AC_QUANT[index.clamp(0, 127) as usize] | 1064 | | } | 1065 | | | 1066 | 2.40k | let mut res = self.b.start_accumulated_result(); | 1067 | | | 1068 | 2.40k | let yac_abs = self.b.read_literal(7).or_accumulate(&mut res); | 1069 | 2.40k | let ydc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res); | 1070 | 2.40k | let y2dc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res); | 1071 | 2.40k | let y2ac_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res); | 1072 | 2.40k | let uvdc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res); | 1073 | 2.40k | let uvac_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res); | 1074 | | | 1075 | 2.40k | let n = if self.segments_enabled { | 1076 | 518 | MAX_SEGMENTS | 1077 | | } else { | 1078 | 1.88k | 1 | 1079 | | }; | 1080 | 3.95k | for i in 0usize..n { | 1081 | 3.95k | let base = i32::from(if self.segments_enabled { | 1082 | 2.07k | if self.segment[i].delta_values { | 1083 | 516 | i16::from(self.segment[i].quantizer_level) + i16::from(yac_abs) | 1084 | | } else { | 1085 | 1.55k | i16::from(self.segment[i].quantizer_level) | 1086 | | } | 1087 | | } else { | 1088 | 1.88k | i16::from(yac_abs) | 1089 | | }); | 1090 | | | 1091 | 3.95k | self.segment[i].ydc = dc_quant(base + ydc_delta); | 1092 | 3.95k | self.segment[i].yac = ac_quant(base); | 1093 | | | 1094 | 3.95k | self.segment[i].y2dc = dc_quant(base + y2dc_delta) * 2; | 1095 | | // The intermediate result (max`284*155`) can be larger than the `i16` range. | 1096 | 3.95k | self.segment[i].y2ac = (i32::from(ac_quant(base + y2ac_delta)) * 155 / 100) as i16; | 1097 | | | 1098 | 3.95k | self.segment[i].uvdc = dc_quant(base + uvdc_delta); | 1099 | 3.95k | self.segment[i].uvac = ac_quant(base + uvac_delta); | 1100 | | | 1101 | 3.95k | if self.segment[i].y2ac < 8 { | 1102 | 1.70k | self.segment[i].y2ac = 8; | 1103 | 2.25k | } | 1104 | | | 1105 | 3.95k | if self.segment[i].uvdc > 132 { | 1106 | 334 | self.segment[i].uvdc = 132; | 1107 | 3.62k | } | 1108 | | } | 1109 | | | 1110 | 2.40k | self.b.check(res, ()) | 1111 | 2.40k | } |
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::read_quantization_indices |
1112 | | |
1113 | 537 | fn read_loop_filter_adjustments(&mut self) -> Result<(), DecodingError> { |
1114 | 537 | let mut res = self.b.start_accumulated_result(); |
1115 | | |
1116 | 537 | if self.b.read_flag().or_accumulate(&mut res) { |
1117 | 1.74k | for i in 0usize..4 { |
1118 | 1.39k | self.ref_delta[i] = self.b.read_optional_signed_value(6).or_accumulate(&mut res); |
1119 | 1.39k | } |
1120 | | |
1121 | 1.74k | for i in 0usize..4 { |
1122 | 1.39k | self.mode_delta[i] = self.b.read_optional_signed_value(6).or_accumulate(&mut res); |
1123 | 1.39k | } |
1124 | 188 | } |
1125 | | |
1126 | 537 | self.b.check(res, ()) |
1127 | 537 | } <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_loop_filter_adjustments Line | Count | Source | 1113 | 537 | fn read_loop_filter_adjustments(&mut self) -> Result<(), DecodingError> { | 1114 | 537 | let mut res = self.b.start_accumulated_result(); | 1115 | | | 1116 | 537 | if self.b.read_flag().or_accumulate(&mut res) { | 1117 | 1.74k | for i in 0usize..4 { | 1118 | 1.39k | self.ref_delta[i] = self.b.read_optional_signed_value(6).or_accumulate(&mut res); | 1119 | 1.39k | } | 1120 | | | 1121 | 1.74k | for i in 0usize..4 { | 1122 | 1.39k | self.mode_delta[i] = self.b.read_optional_signed_value(6).or_accumulate(&mut res); | 1123 | 1.39k | } | 1124 | 188 | } | 1125 | | | 1126 | 537 | self.b.check(res, ()) | 1127 | 537 | } |
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::read_loop_filter_adjustments |
1128 | | |
1129 | 622 | fn read_segment_updates(&mut self) -> Result<(), DecodingError> { |
1130 | 622 | let mut res = self.b.start_accumulated_result(); |
1131 | | |
1132 | | // Section 9.3 |
1133 | 622 | self.segments_update_map = self.b.read_flag().or_accumulate(&mut res); |
1134 | 622 | let update_segment_feature_data = self.b.read_flag().or_accumulate(&mut res); |
1135 | | |
1136 | 622 | if update_segment_feature_data { |
1137 | 475 | let segment_feature_mode = self.b.read_flag().or_accumulate(&mut res); |
1138 | | |
1139 | 2.37k | for i in 0usize..MAX_SEGMENTS { |
1140 | 1.90k | self.segment[i].delta_values = !segment_feature_mode; |
1141 | 1.90k | } |
1142 | | |
1143 | 2.37k | for i in 0usize..MAX_SEGMENTS { |
1144 | 1.90k | self.segment[i].quantizer_level = |
1145 | 1.90k | self.b.read_optional_signed_value(7).or_accumulate(&mut res) as i8; |
1146 | 1.90k | } |
1147 | | |
1148 | 2.37k | for i in 0usize..MAX_SEGMENTS { |
1149 | 1.90k | self.segment[i].loopfilter_level = |
1150 | 1.90k | self.b.read_optional_signed_value(6).or_accumulate(&mut res) as i8; |
1151 | 1.90k | } |
1152 | 147 | } |
1153 | | |
1154 | 622 | if self.segments_update_map { |
1155 | 1.72k | for i in 0usize..3 { |
1156 | 1.29k | let update = self.b.read_flag().or_accumulate(&mut res); |
1157 | | |
1158 | 1.29k | let prob = if update { |
1159 | 738 | self.b.read_literal(8).or_accumulate(&mut res) |
1160 | | } else { |
1161 | 555 | 255 |
1162 | | }; |
1163 | 1.29k | self.segment_tree_nodes[i].prob = prob; |
1164 | | } |
1165 | 191 | } |
1166 | | |
1167 | 622 | self.b.check(res, ()) |
1168 | 622 | } <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_segment_updates Line | Count | Source | 1129 | 622 | fn read_segment_updates(&mut self) -> Result<(), DecodingError> { | 1130 | 622 | let mut res = self.b.start_accumulated_result(); | 1131 | | | 1132 | | // Section 9.3 | 1133 | 622 | self.segments_update_map = self.b.read_flag().or_accumulate(&mut res); | 1134 | 622 | let update_segment_feature_data = self.b.read_flag().or_accumulate(&mut res); | 1135 | | | 1136 | 622 | if update_segment_feature_data { | 1137 | 475 | let segment_feature_mode = self.b.read_flag().or_accumulate(&mut res); | 1138 | | | 1139 | 2.37k | for i in 0usize..MAX_SEGMENTS { | 1140 | 1.90k | self.segment[i].delta_values = !segment_feature_mode; | 1141 | 1.90k | } | 1142 | | | 1143 | 2.37k | for i in 0usize..MAX_SEGMENTS { | 1144 | 1.90k | self.segment[i].quantizer_level = | 1145 | 1.90k | self.b.read_optional_signed_value(7).or_accumulate(&mut res) as i8; | 1146 | 1.90k | } | 1147 | | | 1148 | 2.37k | for i in 0usize..MAX_SEGMENTS { | 1149 | 1.90k | self.segment[i].loopfilter_level = | 1150 | 1.90k | self.b.read_optional_signed_value(6).or_accumulate(&mut res) as i8; | 1151 | 1.90k | } | 1152 | 147 | } | 1153 | | | 1154 | 622 | if self.segments_update_map { | 1155 | 1.72k | for i in 0usize..3 { | 1156 | 1.29k | let update = self.b.read_flag().or_accumulate(&mut res); | 1157 | | | 1158 | 1.29k | let prob = if update { | 1159 | 738 | self.b.read_literal(8).or_accumulate(&mut res) | 1160 | | } else { | 1161 | 555 | 255 | 1162 | | }; | 1163 | 1.29k | self.segment_tree_nodes[i].prob = prob; | 1164 | | } | 1165 | 191 | } | 1166 | | | 1167 | 622 | self.b.check(res, ()) | 1168 | 622 | } |
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::read_segment_updates |
1169 | | |
1170 | 2.67k | fn read_frame_header(&mut self) -> Result<(), DecodingError> { |
1171 | 2.67k | let tag = self.r.read_u24::<LittleEndian>()?; |
1172 | | |
1173 | 2.66k | self.frame.keyframe = tag & 1 == 0; |
1174 | 2.66k | self.frame.version = ((tag >> 1) & 7) as u8; |
1175 | 2.66k | self.frame.for_display = (tag >> 4) & 1 != 0; |
1176 | | |
1177 | 2.66k | let first_partition_size = tag >> 5; |
1178 | | |
1179 | 2.66k | if self.frame.keyframe { |
1180 | 2.59k | let mut tag = [0u8; 3]; |
1181 | 2.59k | self.r.read_exact(&mut tag)?; |
1182 | | |
1183 | 2.59k | if tag != [0x9d, 0x01, 0x2a] { |
1184 | 7 | return Err(DecodingError::Vp8MagicInvalid(tag)); |
1185 | 2.58k | } |
1186 | | |
1187 | 2.58k | let w = self.r.read_u16::<LittleEndian>()?; |
1188 | 2.58k | let h = self.r.read_u16::<LittleEndian>()?; |
1189 | | |
1190 | 2.58k | self.frame.width = w & 0x3FFF; |
1191 | 2.58k | self.frame.height = h & 0x3FFF; |
1192 | | |
1193 | 2.58k | self.top = init_top_macroblocks(self.frame.width as usize); |
1194 | | // Almost always the first macro block, except when non exists (i.e. `width == 0`) |
1195 | 2.58k | self.left = self.top.first().copied().unwrap_or_default(); |
1196 | | |
1197 | 2.58k | self.mbwidth = self.frame.width.div_ceil(16); |
1198 | 2.58k | self.mbheight = self.frame.height.div_ceil(16); |
1199 | | |
1200 | 2.58k | self.frame.ybuf = |
1201 | 2.58k | vec![0u8; usize::from(self.mbwidth) * 16 * usize::from(self.mbheight) * 16]; |
1202 | 2.58k | self.frame.ubuf = |
1203 | 2.58k | vec![0u8; usize::from(self.mbwidth) * 8 * usize::from(self.mbheight) * 8]; |
1204 | 2.58k | self.frame.vbuf = |
1205 | 2.58k | vec![0u8; usize::from(self.mbwidth) * 8 * usize::from(self.mbheight) * 8]; |
1206 | | |
1207 | 2.58k | self.top_border_y = vec![127u8; self.frame.width as usize + 4 + 16]; |
1208 | 2.58k | self.left_border_y = vec![129u8; 1 + 16]; |
1209 | | |
1210 | | // 8 pixels per macroblock |
1211 | 2.58k | self.top_border_u = vec![127u8; 8 * self.mbwidth as usize]; |
1212 | 2.58k | self.left_border_u = vec![129u8; 1 + 8]; |
1213 | | |
1214 | 2.58k | self.top_border_v = vec![127u8; 8 * self.mbwidth as usize]; |
1215 | 2.58k | self.left_border_v = vec![129u8; 1 + 8]; |
1216 | 64 | } |
1217 | | |
1218 | 2.64k | let size = first_partition_size as usize; |
1219 | 2.64k | let mut buf = vec![[0; 4]; size.div_ceil(4)]; |
1220 | 2.64k | let bytes: &mut [u8] = buf.as_mut_slice().as_flattened_mut(); |
1221 | 2.64k | self.r.read_exact(&mut bytes[..size])?; |
1222 | | |
1223 | | // initialise binary decoder |
1224 | 2.58k | self.b.init(buf, size)?; |
1225 | | |
1226 | 2.58k | let mut res = self.b.start_accumulated_result(); |
1227 | 2.58k | if self.frame.keyframe { |
1228 | 2.52k | let color_space = self.b.read_literal(1).or_accumulate(&mut res); |
1229 | 2.52k | self.frame.pixel_type = self.b.read_literal(1).or_accumulate(&mut res); |
1230 | | |
1231 | 2.52k | if color_space != 0 { |
1232 | 1 | return Err(DecodingError::ColorSpaceInvalid(color_space)); |
1233 | 2.52k | } |
1234 | 56 | } |
1235 | | |
1236 | 2.58k | self.segments_enabled = self.b.read_flag().or_accumulate(&mut res); |
1237 | 2.58k | if self.segments_enabled { |
1238 | 622 | self.read_segment_updates()?; |
1239 | 1.96k | } |
1240 | | |
1241 | 2.56k | self.frame.filter_type = self.b.read_flag().or_accumulate(&mut res); |
1242 | 2.56k | self.frame.filter_level = self.b.read_literal(6).or_accumulate(&mut res); |
1243 | 2.56k | self.frame.sharpness_level = self.b.read_literal(3).or_accumulate(&mut res); |
1244 | | |
1245 | 2.56k | self.loop_filter_adjustments_enabled = self.b.read_flag().or_accumulate(&mut res); |
1246 | 2.56k | if self.loop_filter_adjustments_enabled { |
1247 | 537 | self.read_loop_filter_adjustments()?; |
1248 | 2.03k | } |
1249 | | |
1250 | 2.51k | let num_partitions = 1 << self.b.read_literal(2).or_accumulate(&mut res) as usize; |
1251 | 2.51k | self.b.check(res, ())?; |
1252 | | |
1253 | 2.49k | self.num_partitions = num_partitions as u8; |
1254 | 2.49k | self.init_partitions(num_partitions)?; |
1255 | | |
1256 | 2.40k | self.read_quantization_indices()?; |
1257 | | |
1258 | 2.30k | if !self.frame.keyframe { |
1259 | | // 9.7 refresh golden frame and altref frame |
1260 | | // FIXME: support this? |
1261 | 4 | return Err(DecodingError::UnsupportedFeature( |
1262 | 4 | "Non-keyframe frames".to_owned(), |
1263 | 4 | )); |
1264 | 2.29k | } |
1265 | | |
1266 | | // Refresh entropy probs ????? |
1267 | 2.29k | let _ = self.b.read_literal(1); |
1268 | | |
1269 | 2.29k | self.update_token_probabilities()?; |
1270 | | |
1271 | 2.18k | let mut res = self.b.start_accumulated_result(); |
1272 | 2.18k | let mb_no_skip_coeff = self.b.read_literal(1).or_accumulate(&mut res); |
1273 | 2.18k | self.prob_skip_false = if mb_no_skip_coeff == 1 { |
1274 | 785 | Some(self.b.read_literal(8).or_accumulate(&mut res)) |
1275 | | } else { |
1276 | 1.39k | None |
1277 | | }; |
1278 | 2.18k | self.b.check(res, ())?; |
1279 | | |
1280 | 2.18k | if !self.frame.keyframe { |
1281 | | // 9.10 remaining frame data |
1282 | 0 | self.prob_intra = 0; |
1283 | | |
1284 | | // FIXME: support this? |
1285 | 0 | return Err(DecodingError::UnsupportedFeature( |
1286 | 0 | "Non-keyframe frames".to_owned(), |
1287 | 0 | )); |
1288 | 2.18k | } else { |
1289 | 2.18k | // Reset motion vectors |
1290 | 2.18k | } |
1291 | | |
1292 | 2.18k | Ok(()) |
1293 | 2.67k | } <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_frame_header Line | Count | Source | 1170 | 2.67k | fn read_frame_header(&mut self) -> Result<(), DecodingError> { | 1171 | 2.67k | let tag = self.r.read_u24::<LittleEndian>()?; | 1172 | | | 1173 | 2.66k | self.frame.keyframe = tag & 1 == 0; | 1174 | 2.66k | self.frame.version = ((tag >> 1) & 7) as u8; | 1175 | 2.66k | self.frame.for_display = (tag >> 4) & 1 != 0; | 1176 | | | 1177 | 2.66k | let first_partition_size = tag >> 5; | 1178 | | | 1179 | 2.66k | if self.frame.keyframe { | 1180 | 2.59k | let mut tag = [0u8; 3]; | 1181 | 2.59k | self.r.read_exact(&mut tag)?; | 1182 | | | 1183 | 2.59k | if tag != [0x9d, 0x01, 0x2a] { | 1184 | 7 | return Err(DecodingError::Vp8MagicInvalid(tag)); | 1185 | 2.58k | } | 1186 | | | 1187 | 2.58k | let w = self.r.read_u16::<LittleEndian>()?; | 1188 | 2.58k | let h = self.r.read_u16::<LittleEndian>()?; | 1189 | | | 1190 | 2.58k | self.frame.width = w & 0x3FFF; | 1191 | 2.58k | self.frame.height = h & 0x3FFF; | 1192 | | | 1193 | 2.58k | self.top = init_top_macroblocks(self.frame.width as usize); | 1194 | | // Almost always the first macro block, except when non exists (i.e. `width == 0`) | 1195 | 2.58k | self.left = self.top.first().copied().unwrap_or_default(); | 1196 | | | 1197 | 2.58k | self.mbwidth = self.frame.width.div_ceil(16); | 1198 | 2.58k | self.mbheight = self.frame.height.div_ceil(16); | 1199 | | | 1200 | 2.58k | self.frame.ybuf = | 1201 | 2.58k | vec![0u8; usize::from(self.mbwidth) * 16 * usize::from(self.mbheight) * 16]; | 1202 | 2.58k | self.frame.ubuf = | 1203 | 2.58k | vec![0u8; usize::from(self.mbwidth) * 8 * usize::from(self.mbheight) * 8]; | 1204 | 2.58k | self.frame.vbuf = | 1205 | 2.58k | vec![0u8; usize::from(self.mbwidth) * 8 * usize::from(self.mbheight) * 8]; | 1206 | | | 1207 | 2.58k | self.top_border_y = vec![127u8; self.frame.width as usize + 4 + 16]; | 1208 | 2.58k | self.left_border_y = vec![129u8; 1 + 16]; | 1209 | | | 1210 | | // 8 pixels per macroblock | 1211 | 2.58k | self.top_border_u = vec![127u8; 8 * self.mbwidth as usize]; | 1212 | 2.58k | self.left_border_u = vec![129u8; 1 + 8]; | 1213 | | | 1214 | 2.58k | self.top_border_v = vec![127u8; 8 * self.mbwidth as usize]; | 1215 | 2.58k | self.left_border_v = vec![129u8; 1 + 8]; | 1216 | 64 | } | 1217 | | | 1218 | 2.64k | let size = first_partition_size as usize; | 1219 | 2.64k | let mut buf = vec![[0; 4]; size.div_ceil(4)]; | 1220 | 2.64k | let bytes: &mut [u8] = buf.as_mut_slice().as_flattened_mut(); | 1221 | 2.64k | self.r.read_exact(&mut bytes[..size])?; | 1222 | | | 1223 | | // initialise binary decoder | 1224 | 2.58k | self.b.init(buf, size)?; | 1225 | | | 1226 | 2.58k | let mut res = self.b.start_accumulated_result(); | 1227 | 2.58k | if self.frame.keyframe { | 1228 | 2.52k | let color_space = self.b.read_literal(1).or_accumulate(&mut res); | 1229 | 2.52k | self.frame.pixel_type = self.b.read_literal(1).or_accumulate(&mut res); | 1230 | | | 1231 | 2.52k | if color_space != 0 { | 1232 | 1 | return Err(DecodingError::ColorSpaceInvalid(color_space)); | 1233 | 2.52k | } | 1234 | 56 | } | 1235 | | | 1236 | 2.58k | self.segments_enabled = self.b.read_flag().or_accumulate(&mut res); | 1237 | 2.58k | if self.segments_enabled { | 1238 | 622 | self.read_segment_updates()?; | 1239 | 1.96k | } | 1240 | | | 1241 | 2.56k | self.frame.filter_type = self.b.read_flag().or_accumulate(&mut res); | 1242 | 2.56k | self.frame.filter_level = self.b.read_literal(6).or_accumulate(&mut res); | 1243 | 2.56k | self.frame.sharpness_level = self.b.read_literal(3).or_accumulate(&mut res); | 1244 | | | 1245 | 2.56k | self.loop_filter_adjustments_enabled = self.b.read_flag().or_accumulate(&mut res); | 1246 | 2.56k | if self.loop_filter_adjustments_enabled { | 1247 | 537 | self.read_loop_filter_adjustments()?; | 1248 | 2.03k | } | 1249 | | | 1250 | 2.51k | let num_partitions = 1 << self.b.read_literal(2).or_accumulate(&mut res) as usize; | 1251 | 2.51k | self.b.check(res, ())?; | 1252 | | | 1253 | 2.49k | self.num_partitions = num_partitions as u8; | 1254 | 2.49k | self.init_partitions(num_partitions)?; | 1255 | | | 1256 | 2.40k | self.read_quantization_indices()?; | 1257 | | | 1258 | 2.30k | if !self.frame.keyframe { | 1259 | | // 9.7 refresh golden frame and altref frame | 1260 | | // FIXME: support this? | 1261 | 4 | return Err(DecodingError::UnsupportedFeature( | 1262 | 4 | "Non-keyframe frames".to_owned(), | 1263 | 4 | )); | 1264 | 2.29k | } | 1265 | | | 1266 | | // Refresh entropy probs ????? | 1267 | 2.29k | let _ = self.b.read_literal(1); | 1268 | | | 1269 | 2.29k | self.update_token_probabilities()?; | 1270 | | | 1271 | 2.18k | let mut res = self.b.start_accumulated_result(); | 1272 | 2.18k | let mb_no_skip_coeff = self.b.read_literal(1).or_accumulate(&mut res); | 1273 | 2.18k | self.prob_skip_false = if mb_no_skip_coeff == 1 { | 1274 | 785 | Some(self.b.read_literal(8).or_accumulate(&mut res)) | 1275 | | } else { | 1276 | 1.39k | None | 1277 | | }; | 1278 | 2.18k | self.b.check(res, ())?; | 1279 | | | 1280 | 2.18k | if !self.frame.keyframe { | 1281 | | // 9.10 remaining frame data | 1282 | 0 | self.prob_intra = 0; | 1283 | | | 1284 | | // FIXME: support this? | 1285 | 0 | return Err(DecodingError::UnsupportedFeature( | 1286 | 0 | "Non-keyframe frames".to_owned(), | 1287 | 0 | )); | 1288 | 2.18k | } else { | 1289 | 2.18k | // Reset motion vectors | 1290 | 2.18k | } | 1291 | | | 1292 | 2.18k | Ok(()) | 1293 | 2.67k | } |
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::read_frame_header |
1294 | | |
1295 | 2.17M | fn read_macroblock_header(&mut self, mbx: usize) -> Result<MacroBlock, DecodingError> { |
1296 | 2.17M | let mut mb = MacroBlock::default(); |
1297 | 2.17M | let mut res = self.b.start_accumulated_result(); |
1298 | | |
1299 | 2.17M | if self.segments_enabled && self.segments_update_map { |
1300 | 987k | mb.segmentid = |
1301 | 987k | (self.b.read_with_tree(&self.segment_tree_nodes)).or_accumulate(&mut res) as u8; |
1302 | 1.19M | }; |
1303 | | |
1304 | 2.17M | mb.coeffs_skipped = if let Some(prob) = self.prob_skip_false { |
1305 | 1.82M | self.b.read_bool(prob).or_accumulate(&mut res) |
1306 | | } else { |
1307 | 357k | false |
1308 | | }; |
1309 | | |
1310 | 2.17M | let inter_predicted = if !self.frame.keyframe { |
1311 | 0 | self.b.read_bool(self.prob_intra).or_accumulate(&mut res) |
1312 | | } else { |
1313 | 2.17M | false |
1314 | | }; |
1315 | | |
1316 | 2.17M | if inter_predicted { |
1317 | 0 | return Err(DecodingError::UnsupportedFeature( |
1318 | 0 | "VP8 inter-prediction".to_owned(), |
1319 | 0 | )); |
1320 | 2.17M | } |
1321 | | |
1322 | 2.17M | if self.frame.keyframe { |
1323 | | // intra prediction |
1324 | 2.17M | let luma = (self.b.read_with_tree(&KEYFRAME_YMODE_NODES)).or_accumulate(&mut res); |
1325 | | mb.luma_mode = |
1326 | 2.17M | LumaMode::from_i8(luma).ok_or(DecodingError::LumaPredictionModeInvalid(luma))?; |
1327 | | |
1328 | 2.17M | match mb.luma_mode.into_intra() { |
1329 | | // `LumaMode::B` - This is predicted individually |
1330 | | None => { |
1331 | 4.88M | for y in 0usize..4 { |
1332 | 19.5M | for x in 0usize..4 { |
1333 | 15.6M | let top = self.top[mbx].bpred[12 + x]; |
1334 | 15.6M | let left = self.left.bpred[y]; |
1335 | 15.6M | let intra = self.b.read_with_tree( |
1336 | 15.6M | &KEYFRAME_BPRED_MODE_NODES[top as usize][left as usize], |
1337 | | ); |
1338 | 15.6M | let intra = intra.or_accumulate(&mut res); |
1339 | 15.6M | let bmode = IntraMode::from_i8(intra) |
1340 | 15.6M | .ok_or(DecodingError::IntraPredictionModeInvalid(intra))?; |
1341 | 15.6M | mb.bpred[x + y * 4] = bmode; |
1342 | | |
1343 | 15.6M | self.top[mbx].bpred[12 + x] = bmode; |
1344 | 15.6M | self.left.bpred[y] = bmode; |
1345 | | } |
1346 | | } |
1347 | | } |
1348 | 1.20M | Some(mode) => { |
1349 | 6.00M | for i in 0usize..4 { |
1350 | 4.80M | mb.bpred[12 + i] = mode; |
1351 | 4.80M | self.left.bpred[i] = mode; |
1352 | 4.80M | } |
1353 | | } |
1354 | | } |
1355 | | |
1356 | 2.17M | let chroma = (self.b.read_with_tree(&KEYFRAME_UV_MODE_NODES)).or_accumulate(&mut res); |
1357 | 2.17M | mb.chroma_mode = ChromaMode::from_i8(chroma) |
1358 | 2.17M | .ok_or(DecodingError::ChromaPredictionModeInvalid(chroma))?; |
1359 | 0 | } |
1360 | | |
1361 | 2.17M | self.top[mbx].chroma_mode = mb.chroma_mode; |
1362 | 2.17M | self.top[mbx].luma_mode = mb.luma_mode; |
1363 | 2.17M | self.top[mbx].bpred = mb.bpred; |
1364 | | |
1365 | 2.17M | self.b.check(res, mb) |
1366 | 2.17M | } <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_macroblock_header Line | Count | Source | 1295 | 2.17M | fn read_macroblock_header(&mut self, mbx: usize) -> Result<MacroBlock, DecodingError> { | 1296 | 2.17M | let mut mb = MacroBlock::default(); | 1297 | 2.17M | let mut res = self.b.start_accumulated_result(); | 1298 | | | 1299 | 2.17M | if self.segments_enabled && self.segments_update_map { | 1300 | 987k | mb.segmentid = | 1301 | 987k | (self.b.read_with_tree(&self.segment_tree_nodes)).or_accumulate(&mut res) as u8; | 1302 | 1.19M | }; | 1303 | | | 1304 | 2.17M | mb.coeffs_skipped = if let Some(prob) = self.prob_skip_false { | 1305 | 1.82M | self.b.read_bool(prob).or_accumulate(&mut res) | 1306 | | } else { | 1307 | 357k | false | 1308 | | }; | 1309 | | | 1310 | 2.17M | let inter_predicted = if !self.frame.keyframe { | 1311 | 0 | self.b.read_bool(self.prob_intra).or_accumulate(&mut res) | 1312 | | } else { | 1313 | 2.17M | false | 1314 | | }; | 1315 | | | 1316 | 2.17M | if inter_predicted { | 1317 | 0 | return Err(DecodingError::UnsupportedFeature( | 1318 | 0 | "VP8 inter-prediction".to_owned(), | 1319 | 0 | )); | 1320 | 2.17M | } | 1321 | | | 1322 | 2.17M | if self.frame.keyframe { | 1323 | | // intra prediction | 1324 | 2.17M | let luma = (self.b.read_with_tree(&KEYFRAME_YMODE_NODES)).or_accumulate(&mut res); | 1325 | | mb.luma_mode = | 1326 | 2.17M | LumaMode::from_i8(luma).ok_or(DecodingError::LumaPredictionModeInvalid(luma))?; | 1327 | | | 1328 | 2.17M | match mb.luma_mode.into_intra() { | 1329 | | // `LumaMode::B` - This is predicted individually | 1330 | | None => { | 1331 | 4.88M | for y in 0usize..4 { | 1332 | 19.5M | for x in 0usize..4 { | 1333 | 15.6M | let top = self.top[mbx].bpred[12 + x]; | 1334 | 15.6M | let left = self.left.bpred[y]; | 1335 | 15.6M | let intra = self.b.read_with_tree( | 1336 | 15.6M | &KEYFRAME_BPRED_MODE_NODES[top as usize][left as usize], | 1337 | | ); | 1338 | 15.6M | let intra = intra.or_accumulate(&mut res); | 1339 | 15.6M | let bmode = IntraMode::from_i8(intra) | 1340 | 15.6M | .ok_or(DecodingError::IntraPredictionModeInvalid(intra))?; | 1341 | 15.6M | mb.bpred[x + y * 4] = bmode; | 1342 | | | 1343 | 15.6M | self.top[mbx].bpred[12 + x] = bmode; | 1344 | 15.6M | self.left.bpred[y] = bmode; | 1345 | | } | 1346 | | } | 1347 | | } | 1348 | 1.20M | Some(mode) => { | 1349 | 6.00M | for i in 0usize..4 { | 1350 | 4.80M | mb.bpred[12 + i] = mode; | 1351 | 4.80M | self.left.bpred[i] = mode; | 1352 | 4.80M | } | 1353 | | } | 1354 | | } | 1355 | | | 1356 | 2.17M | let chroma = (self.b.read_with_tree(&KEYFRAME_UV_MODE_NODES)).or_accumulate(&mut res); | 1357 | 2.17M | mb.chroma_mode = ChromaMode::from_i8(chroma) | 1358 | 2.17M | .ok_or(DecodingError::ChromaPredictionModeInvalid(chroma))?; | 1359 | 0 | } | 1360 | | | 1361 | 2.17M | self.top[mbx].chroma_mode = mb.chroma_mode; | 1362 | 2.17M | self.top[mbx].luma_mode = mb.luma_mode; | 1363 | 2.17M | self.top[mbx].bpred = mb.bpred; | 1364 | | | 1365 | 2.17M | self.b.check(res, mb) | 1366 | 2.17M | } |
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::read_macroblock_header |
1367 | | |
1368 | 2.17M | fn intra_predict_luma(&mut self, mbx: usize, mby: usize, mb: &MacroBlock, resdata: &[i32]) { |
1369 | 2.17M | let stride = 1usize + 16 + 4; |
1370 | 2.17M | let mw = self.mbwidth as usize; |
1371 | 2.17M | let mut ws = create_border_luma(mbx, mby, mw, &self.top_border_y, &self.left_border_y); |
1372 | | |
1373 | 2.17M | match mb.luma_mode { |
1374 | 153k | LumaMode::V => predict_vpred(&mut ws, 16, 1, 1, stride), |
1375 | 291k | LumaMode::H => predict_hpred(&mut ws, 16, 1, 1, stride), |
1376 | 346k | LumaMode::TM => predict_tmpred(&mut ws, 16, 1, 1, stride), |
1377 | 409k | LumaMode::DC => predict_dcpred(&mut ws, 16, stride, mby != 0, mbx != 0), |
1378 | 976k | LumaMode::B => predict_4x4(&mut ws, stride, &mb.bpred, resdata), |
1379 | | } |
1380 | | |
1381 | 2.17M | if mb.luma_mode != LumaMode::B { |
1382 | 6.00M | for y in 0usize..4 { |
1383 | 24.0M | for x in 0usize..4 { |
1384 | 19.2M | let i = x + y * 4; |
1385 | 19.2M | // Create a reference to a [i32; 16] array for add_residue (slices of size 16 do not work). |
1386 | 19.2M | let rb: &[i32; 16] = resdata[i * 16..][..16].try_into().unwrap(); |
1387 | 19.2M | let y0 = 1 + y * 4; |
1388 | 19.2M | let x0 = 1 + x * 4; |
1389 | 19.2M | |
1390 | 19.2M | add_residue(&mut ws, rb, y0, x0, stride); |
1391 | 19.2M | } |
1392 | | } |
1393 | 976k | } |
1394 | | |
1395 | 2.17M | self.left_border_y[0] = ws[16]; |
1396 | | |
1397 | 34.8M | for (i, left) in self.left_border_y[1..][..16].iter_mut().enumerate() { |
1398 | 34.8M | *left = ws[(i + 1) * stride + 16]; |
1399 | 34.8M | } |
1400 | | |
1401 | 34.8M | for (top, &w) in self.top_border_y[mbx * 16..][..16] |
1402 | 2.17M | .iter_mut() |
1403 | 2.17M | .zip(&ws[16 * stride + 1..][..16]) |
1404 | 34.8M | { |
1405 | 34.8M | *top = w; |
1406 | 34.8M | } |
1407 | | |
1408 | 37.0M | for y in 0usize..16 { |
1409 | 557M | for (ybuf, &ws) in self.frame.ybuf[(mby * 16 + y) * mw * 16 + mbx * 16..][..16] |
1410 | 34.8M | .iter_mut() |
1411 | 34.8M | .zip(ws[(1 + y) * stride + 1..][..16].iter()) |
1412 | 557M | { |
1413 | 557M | *ybuf = ws; |
1414 | 557M | } |
1415 | | } |
1416 | 2.17M | } <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_luma Line | Count | Source | 1368 | 2.17M | fn intra_predict_luma(&mut self, mbx: usize, mby: usize, mb: &MacroBlock, resdata: &[i32]) { | 1369 | 2.17M | let stride = 1usize + 16 + 4; | 1370 | 2.17M | let mw = self.mbwidth as usize; | 1371 | 2.17M | let mut ws = create_border_luma(mbx, mby, mw, &self.top_border_y, &self.left_border_y); | 1372 | | | 1373 | 2.17M | match mb.luma_mode { | 1374 | 153k | LumaMode::V => predict_vpred(&mut ws, 16, 1, 1, stride), | 1375 | 291k | LumaMode::H => predict_hpred(&mut ws, 16, 1, 1, stride), | 1376 | 346k | LumaMode::TM => predict_tmpred(&mut ws, 16, 1, 1, stride), | 1377 | 409k | LumaMode::DC => predict_dcpred(&mut ws, 16, stride, mby != 0, mbx != 0), | 1378 | 976k | LumaMode::B => predict_4x4(&mut ws, stride, &mb.bpred, resdata), | 1379 | | } | 1380 | | | 1381 | 2.17M | if mb.luma_mode != LumaMode::B { | 1382 | 6.00M | for y in 0usize..4 { | 1383 | 24.0M | for x in 0usize..4 { | 1384 | 19.2M | let i = x + y * 4; | 1385 | 19.2M | // Create a reference to a [i32; 16] array for add_residue (slices of size 16 do not work). | 1386 | 19.2M | let rb: &[i32; 16] = resdata[i * 16..][..16].try_into().unwrap(); | 1387 | 19.2M | let y0 = 1 + y * 4; | 1388 | 19.2M | let x0 = 1 + x * 4; | 1389 | 19.2M | | 1390 | 19.2M | add_residue(&mut ws, rb, y0, x0, stride); | 1391 | 19.2M | } | 1392 | | } | 1393 | 976k | } | 1394 | | | 1395 | 2.17M | self.left_border_y[0] = ws[16]; | 1396 | | | 1397 | 34.8M | for (i, left) in self.left_border_y[1..][..16].iter_mut().enumerate() { | 1398 | 34.8M | *left = ws[(i + 1) * stride + 16]; | 1399 | 34.8M | } | 1400 | | | 1401 | 34.8M | for (top, &w) in self.top_border_y[mbx * 16..][..16] | 1402 | 2.17M | .iter_mut() | 1403 | 2.17M | .zip(&ws[16 * stride + 1..][..16]) | 1404 | 34.8M | { | 1405 | 34.8M | *top = w; | 1406 | 34.8M | } | 1407 | | | 1408 | 37.0M | for y in 0usize..16 { | 1409 | 557M | for (ybuf, &ws) in self.frame.ybuf[(mby * 16 + y) * mw * 16 + mbx * 16..][..16] | 1410 | 34.8M | .iter_mut() | 1411 | 34.8M | .zip(ws[(1 + y) * stride + 1..][..16].iter()) | 1412 | 557M | { | 1413 | 557M | *ybuf = ws; | 1414 | 557M | } | 1415 | | } | 1416 | 2.17M | } |
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::intra_predict_luma |
1417 | | |
1418 | 2.17M | fn intra_predict_chroma(&mut self, mbx: usize, mby: usize, mb: &MacroBlock, resdata: &[i32]) { |
1419 | 2.17M | let stride = 1usize + 8; |
1420 | | |
1421 | 2.17M | let mw = self.mbwidth as usize; |
1422 | | |
1423 | | //8x8 with left top border of 1 |
1424 | 2.17M | let mut uws = create_border_chroma(mbx, mby, &self.top_border_u, &self.left_border_u); |
1425 | 2.17M | let mut vws = create_border_chroma(mbx, mby, &self.top_border_v, &self.left_border_v); |
1426 | | |
1427 | 2.17M | match mb.chroma_mode { |
1428 | 1.11M | ChromaMode::DC => { |
1429 | 1.11M | predict_dcpred(&mut uws, 8, stride, mby != 0, mbx != 0); |
1430 | 1.11M | predict_dcpred(&mut vws, 8, stride, mby != 0, mbx != 0); |
1431 | 1.11M | } |
1432 | 377k | ChromaMode::V => { |
1433 | 377k | predict_vpred(&mut uws, 8, 1, 1, stride); |
1434 | 377k | predict_vpred(&mut vws, 8, 1, 1, stride); |
1435 | 377k | } |
1436 | 274k | ChromaMode::H => { |
1437 | 274k | predict_hpred(&mut uws, 8, 1, 1, stride); |
1438 | 274k | predict_hpred(&mut vws, 8, 1, 1, stride); |
1439 | 274k | } |
1440 | 412k | ChromaMode::TM => { |
1441 | 412k | predict_tmpred(&mut uws, 8, 1, 1, stride); |
1442 | 412k | predict_tmpred(&mut vws, 8, 1, 1, stride); |
1443 | 412k | } |
1444 | | } |
1445 | | |
1446 | 6.53M | for y in 0usize..2 { |
1447 | 13.0M | for x in 0usize..2 { |
1448 | 8.71M | let i = x + y * 2; |
1449 | 8.71M | let urb: &[i32; 16] = resdata[16 * 16 + i * 16..][..16].try_into().unwrap(); |
1450 | 8.71M | |
1451 | 8.71M | let y0 = 1 + y * 4; |
1452 | 8.71M | let x0 = 1 + x * 4; |
1453 | 8.71M | add_residue(&mut uws, urb, y0, x0, stride); |
1454 | 8.71M | |
1455 | 8.71M | let vrb: &[i32; 16] = resdata[20 * 16 + i * 16..][..16].try_into().unwrap(); |
1456 | 8.71M | |
1457 | 8.71M | add_residue(&mut vws, vrb, y0, x0, stride); |
1458 | 8.71M | } |
1459 | | } |
1460 | | |
1461 | 2.17M | set_chroma_border(&mut self.left_border_u, &mut self.top_border_u, &uws, mbx); |
1462 | 2.17M | set_chroma_border(&mut self.left_border_v, &mut self.top_border_v, &vws, mbx); |
1463 | | |
1464 | 19.6M | for y in 0usize..8 { |
1465 | 17.4M | let uv_buf_index = (mby * 8 + y) * mw * 8 + mbx * 8; |
1466 | 17.4M | let ws_index = (1 + y) * stride + 1; |
1467 | | |
1468 | 139M | for (((ub, vb), &uw), &vw) in self.frame.ubuf[uv_buf_index..][..8] |
1469 | 17.4M | .iter_mut() |
1470 | 17.4M | .zip(self.frame.vbuf[uv_buf_index..][..8].iter_mut()) |
1471 | 17.4M | .zip(uws[ws_index..][..8].iter()) |
1472 | 17.4M | .zip(vws[ws_index..][..8].iter()) |
1473 | 139M | { |
1474 | 139M | *ub = uw; |
1475 | 139M | *vb = vw; |
1476 | 139M | } |
1477 | | } |
1478 | 2.17M | } <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_chroma Line | Count | Source | 1418 | 2.17M | fn intra_predict_chroma(&mut self, mbx: usize, mby: usize, mb: &MacroBlock, resdata: &[i32]) { | 1419 | 2.17M | let stride = 1usize + 8; | 1420 | | | 1421 | 2.17M | let mw = self.mbwidth as usize; | 1422 | | | 1423 | | //8x8 with left top border of 1 | 1424 | 2.17M | let mut uws = create_border_chroma(mbx, mby, &self.top_border_u, &self.left_border_u); | 1425 | 2.17M | let mut vws = create_border_chroma(mbx, mby, &self.top_border_v, &self.left_border_v); | 1426 | | | 1427 | 2.17M | match mb.chroma_mode { | 1428 | 1.11M | ChromaMode::DC => { | 1429 | 1.11M | predict_dcpred(&mut uws, 8, stride, mby != 0, mbx != 0); | 1430 | 1.11M | predict_dcpred(&mut vws, 8, stride, mby != 0, mbx != 0); | 1431 | 1.11M | } | 1432 | 377k | ChromaMode::V => { | 1433 | 377k | predict_vpred(&mut uws, 8, 1, 1, stride); | 1434 | 377k | predict_vpred(&mut vws, 8, 1, 1, stride); | 1435 | 377k | } | 1436 | 274k | ChromaMode::H => { | 1437 | 274k | predict_hpred(&mut uws, 8, 1, 1, stride); | 1438 | 274k | predict_hpred(&mut vws, 8, 1, 1, stride); | 1439 | 274k | } | 1440 | 412k | ChromaMode::TM => { | 1441 | 412k | predict_tmpred(&mut uws, 8, 1, 1, stride); | 1442 | 412k | predict_tmpred(&mut vws, 8, 1, 1, stride); | 1443 | 412k | } | 1444 | | } | 1445 | | | 1446 | 6.53M | for y in 0usize..2 { | 1447 | 13.0M | for x in 0usize..2 { | 1448 | 8.71M | let i = x + y * 2; | 1449 | 8.71M | let urb: &[i32; 16] = resdata[16 * 16 + i * 16..][..16].try_into().unwrap(); | 1450 | 8.71M | | 1451 | 8.71M | let y0 = 1 + y * 4; | 1452 | 8.71M | let x0 = 1 + x * 4; | 1453 | 8.71M | add_residue(&mut uws, urb, y0, x0, stride); | 1454 | 8.71M | | 1455 | 8.71M | let vrb: &[i32; 16] = resdata[20 * 16 + i * 16..][..16].try_into().unwrap(); | 1456 | 8.71M | | 1457 | 8.71M | add_residue(&mut vws, vrb, y0, x0, stride); | 1458 | 8.71M | } | 1459 | | } | 1460 | | | 1461 | 2.17M | set_chroma_border(&mut self.left_border_u, &mut self.top_border_u, &uws, mbx); | 1462 | 2.17M | set_chroma_border(&mut self.left_border_v, &mut self.top_border_v, &vws, mbx); | 1463 | | | 1464 | 19.6M | for y in 0usize..8 { | 1465 | 17.4M | let uv_buf_index = (mby * 8 + y) * mw * 8 + mbx * 8; | 1466 | 17.4M | let ws_index = (1 + y) * stride + 1; | 1467 | | | 1468 | 139M | for (((ub, vb), &uw), &vw) in self.frame.ubuf[uv_buf_index..][..8] | 1469 | 17.4M | .iter_mut() | 1470 | 17.4M | .zip(self.frame.vbuf[uv_buf_index..][..8].iter_mut()) | 1471 | 17.4M | .zip(uws[ws_index..][..8].iter()) | 1472 | 17.4M | .zip(vws[ws_index..][..8].iter()) | 1473 | 139M | { | 1474 | 139M | *ub = uw; | 1475 | 139M | *vb = vw; | 1476 | 139M | } | 1477 | | } | 1478 | 2.17M | } |
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::intra_predict_chroma |
1479 | | |
1480 | 12.5M | fn read_coefficients( |
1481 | 12.5M | &mut self, |
1482 | 12.5M | block: &mut [i32; 16], |
1483 | 12.5M | p: usize, |
1484 | 12.5M | plane: usize, |
1485 | 12.5M | complexity: usize, |
1486 | 12.5M | dcq: i16, |
1487 | 12.5M | acq: i16, |
1488 | 12.5M | ) -> Result<bool, DecodingError> { |
1489 | | // perform bounds checks once up front, |
1490 | | // so that the compiler doesn't have to insert them in the hot loop below |
1491 | 12.5M | assert!(complexity <= 2); |
1492 | | |
1493 | 12.5M | let first = if plane == 0 { 1usize } else { 0usize }; |
1494 | 12.5M | let probs = &self.token_probs[plane]; |
1495 | 12.5M | let decoder = &mut self.partitions[p]; |
1496 | | |
1497 | 12.5M | let mut res = decoder.start_accumulated_result(); |
1498 | | |
1499 | 12.5M | let mut complexity = complexity; |
1500 | 12.5M | let mut has_coefficients = false; |
1501 | 12.5M | let mut skip = false; |
1502 | | |
1503 | 18.7M | for i in first..16usize { |
1504 | 18.7M | let band = COEFF_BANDS[i] as usize; |
1505 | 18.7M | let tree = &probs[band][complexity]; |
1506 | | |
1507 | 18.7M | let token = decoder |
1508 | 18.7M | .read_with_tree_with_first_node(tree, tree[skip as usize]) |
1509 | 18.7M | .or_accumulate(&mut res); |
1510 | | |
1511 | 18.7M | let mut abs_value = i32::from(match token { |
1512 | 12.5M | DCT_EOB => break, |
1513 | | |
1514 | | DCT_0 => { |
1515 | 2.28M | skip = true; |
1516 | 2.28M | has_coefficients = true; |
1517 | 2.28M | complexity = 0; |
1518 | 2.28M | continue; |
1519 | | } |
1520 | | |
1521 | 3.98M | literal @ DCT_1..=DCT_4 => i16::from(literal), |
1522 | | |
1523 | 142k | category @ DCT_CAT1..=DCT_CAT6 => { |
1524 | 142k | let probs = PROB_DCT_CAT[(category - DCT_CAT1) as usize]; |
1525 | | |
1526 | 142k | let mut extra = 0i16; |
1527 | | |
1528 | 1.00M | for t in probs.iter().copied() { |
1529 | 1.00M | if t == 0 { |
1530 | 142k | break; |
1531 | 864k | } |
1532 | 864k | let b = decoder.read_bool(t).or_accumulate(&mut res); |
1533 | 864k | extra = extra + extra + i16::from(b); |
1534 | | } |
1535 | | |
1536 | 142k | i16::from(DCT_CAT_BASE[(category - DCT_CAT1) as usize]) + extra |
1537 | | } |
1538 | | |
1539 | 0 | c => panic!("unknown token: {c}"), |
1540 | | }); |
1541 | | |
1542 | 3.98M | skip = false; |
1543 | | |
1544 | 3.98M | complexity = if abs_value == 0 { |
1545 | 0 | 0 |
1546 | 3.98M | } else if abs_value == 1 { |
1547 | 3.14M | 1 |
1548 | | } else { |
1549 | 841k | 2 |
1550 | | }; |
1551 | | |
1552 | 3.98M | if decoder.read_flag().or_accumulate(&mut res) { |
1553 | 2.00M | abs_value = -abs_value; |
1554 | 2.00M | } |
1555 | | |
1556 | 3.98M | let zigzag = ZIGZAG[i] as usize; |
1557 | 3.98M | block[zigzag] = abs_value * i32::from(if zigzag > 0 { acq } else { dcq }); |
1558 | | |
1559 | 3.98M | has_coefficients = true; |
1560 | | } |
1561 | | |
1562 | 12.5M | decoder.check(res, has_coefficients) |
1563 | 12.5M | } <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_coefficients Line | Count | Source | 1480 | 12.5M | fn read_coefficients( | 1481 | 12.5M | &mut self, | 1482 | 12.5M | block: &mut [i32; 16], | 1483 | 12.5M | p: usize, | 1484 | 12.5M | plane: usize, | 1485 | 12.5M | complexity: usize, | 1486 | 12.5M | dcq: i16, | 1487 | 12.5M | acq: i16, | 1488 | 12.5M | ) -> Result<bool, DecodingError> { | 1489 | | // perform bounds checks once up front, | 1490 | | // so that the compiler doesn't have to insert them in the hot loop below | 1491 | 12.5M | assert!(complexity <= 2); | 1492 | | | 1493 | 12.5M | let first = if plane == 0 { 1usize } else { 0usize }; | 1494 | 12.5M | let probs = &self.token_probs[plane]; | 1495 | 12.5M | let decoder = &mut self.partitions[p]; | 1496 | | | 1497 | 12.5M | let mut res = decoder.start_accumulated_result(); | 1498 | | | 1499 | 12.5M | let mut complexity = complexity; | 1500 | 12.5M | let mut has_coefficients = false; | 1501 | 12.5M | let mut skip = false; | 1502 | | | 1503 | 18.7M | for i in first..16usize { | 1504 | 18.7M | let band = COEFF_BANDS[i] as usize; | 1505 | 18.7M | let tree = &probs[band][complexity]; | 1506 | | | 1507 | 18.7M | let token = decoder | 1508 | 18.7M | .read_with_tree_with_first_node(tree, tree[skip as usize]) | 1509 | 18.7M | .or_accumulate(&mut res); | 1510 | | | 1511 | 18.7M | let mut abs_value = i32::from(match token { | 1512 | 12.5M | DCT_EOB => break, | 1513 | | | 1514 | | DCT_0 => { | 1515 | 2.28M | skip = true; | 1516 | 2.28M | has_coefficients = true; | 1517 | 2.28M | complexity = 0; | 1518 | 2.28M | continue; | 1519 | | } | 1520 | | | 1521 | 3.98M | literal @ DCT_1..=DCT_4 => i16::from(literal), | 1522 | | | 1523 | 142k | category @ DCT_CAT1..=DCT_CAT6 => { | 1524 | 142k | let probs = PROB_DCT_CAT[(category - DCT_CAT1) as usize]; | 1525 | | | 1526 | 142k | let mut extra = 0i16; | 1527 | | | 1528 | 1.00M | for t in probs.iter().copied() { | 1529 | 1.00M | if t == 0 { | 1530 | 142k | break; | 1531 | 864k | } | 1532 | 864k | let b = decoder.read_bool(t).or_accumulate(&mut res); | 1533 | 864k | extra = extra + extra + i16::from(b); | 1534 | | } | 1535 | | | 1536 | 142k | i16::from(DCT_CAT_BASE[(category - DCT_CAT1) as usize]) + extra | 1537 | | } | 1538 | | | 1539 | 0 | c => panic!("unknown token: {c}"), | 1540 | | }); | 1541 | | | 1542 | 3.98M | skip = false; | 1543 | | | 1544 | 3.98M | complexity = if abs_value == 0 { | 1545 | 0 | 0 | 1546 | 3.98M | } else if abs_value == 1 { | 1547 | 3.14M | 1 | 1548 | | } else { | 1549 | 841k | 2 | 1550 | | }; | 1551 | | | 1552 | 3.98M | if decoder.read_flag().or_accumulate(&mut res) { | 1553 | 2.00M | abs_value = -abs_value; | 1554 | 2.00M | } | 1555 | | | 1556 | 3.98M | let zigzag = ZIGZAG[i] as usize; | 1557 | 3.98M | block[zigzag] = abs_value * i32::from(if zigzag > 0 { acq } else { dcq }); | 1558 | | | 1559 | 3.98M | has_coefficients = true; | 1560 | | } | 1561 | | | 1562 | 12.5M | decoder.check(res, has_coefficients) | 1563 | 12.5M | } |
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::read_coefficients |
1564 | | |
1565 | 513k | fn read_residual_data( |
1566 | 513k | &mut self, |
1567 | 513k | mb: &mut MacroBlock, |
1568 | 513k | mbx: usize, |
1569 | 513k | p: usize, |
1570 | 513k | ) -> Result<[i32; 384], DecodingError> { |
1571 | 513k | let sindex = mb.segmentid as usize; |
1572 | 513k | let mut blocks = [0i32; 384]; |
1573 | 513k | let mut plane = if mb.luma_mode == LumaMode::B { 3 } else { 1 }; |
1574 | | |
1575 | 513k | if plane == 1 { |
1576 | 216k | let complexity = self.top[mbx].complexity[0] + self.left.complexity[0]; |
1577 | 216k | let mut block = [0i32; 16]; |
1578 | 216k | let dcq = self.segment[sindex].y2dc; |
1579 | 216k | let acq = self.segment[sindex].y2ac; |
1580 | 216k | let n = self.read_coefficients(&mut block, p, plane, complexity as usize, dcq, acq)?; |
1581 | | |
1582 | 216k | self.left.complexity[0] = if n { 1 } else { 0 }; |
1583 | 216k | self.top[mbx].complexity[0] = if n { 1 } else { 0 }; |
1584 | | |
1585 | 216k | transform::iwht4x4(&mut block); |
1586 | | |
1587 | 3.67M | for k in 0usize..16 { |
1588 | 3.46M | blocks[16 * k] = block[k]; |
1589 | 3.46M | } |
1590 | | |
1591 | 216k | plane = 0; |
1592 | 296k | } |
1593 | | |
1594 | 2.56M | for y in 0usize..4 { |
1595 | 2.05M | let mut left = self.left.complexity[y + 1]; |
1596 | 10.2M | for x in 0usize..4 { |
1597 | 8.20M | let i = x + y * 4; |
1598 | 8.20M | let block = &mut blocks[i * 16..][..16]; |
1599 | 8.20M | let block: &mut [i32; 16] = block.try_into().unwrap(); |
1600 | | |
1601 | 8.20M | let complexity = self.top[mbx].complexity[x + 1] + left; |
1602 | 8.20M | let dcq = self.segment[sindex].ydc; |
1603 | 8.20M | let acq = self.segment[sindex].yac; |
1604 | | |
1605 | 8.20M | let n = self.read_coefficients(block, p, plane, complexity as usize, dcq, acq)?; |
1606 | | |
1607 | 8.20M | if block[0] != 0 || n { |
1608 | 2.45M | mb.non_zero_dct = true; |
1609 | 2.45M | transform::idct4x4(block); |
1610 | 5.74M | } |
1611 | | |
1612 | 8.20M | left = if n { 1 } else { 0 }; |
1613 | 8.20M | self.top[mbx].complexity[x + 1] = if n { 1 } else { 0 }; |
1614 | | } |
1615 | | |
1616 | 2.05M | self.left.complexity[y + 1] = left; |
1617 | | } |
1618 | | |
1619 | 512k | plane = 2; |
1620 | | |
1621 | 1.53M | for &j in &[5usize, 7usize] { |
1622 | 3.07M | for y in 0usize..2 { |
1623 | 2.04M | let mut left = self.left.complexity[y + j]; |
1624 | | |
1625 | 6.14M | for x in 0usize..2 { |
1626 | 4.09M | let i = x + y * 2 + if j == 5 { 16 } else { 20 }; |
1627 | 4.09M | let block = &mut blocks[i * 16..][..16]; |
1628 | 4.09M | let block: &mut [i32; 16] = block.try_into().unwrap(); |
1629 | | |
1630 | 4.09M | let complexity = self.top[mbx].complexity[x + j] + left; |
1631 | 4.09M | let dcq = self.segment[sindex].uvdc; |
1632 | 4.09M | let acq = self.segment[sindex].uvac; |
1633 | | |
1634 | 4.09M | let n = |
1635 | 4.09M | self.read_coefficients(block, p, plane, complexity as usize, dcq, acq)?; |
1636 | 4.09M | if block[0] != 0 || n { |
1637 | 309k | mb.non_zero_dct = true; |
1638 | 309k | transform::idct4x4(block); |
1639 | 3.79M | } |
1640 | | |
1641 | 4.09M | left = if n { 1 } else { 0 }; |
1642 | 4.09M | self.top[mbx].complexity[x + j] = if n { 1 } else { 0 }; |
1643 | | } |
1644 | | |
1645 | 2.04M | self.left.complexity[y + j] = left; |
1646 | | } |
1647 | | } |
1648 | | |
1649 | 512k | Ok(blocks) |
1650 | 513k | } <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_residual_data Line | Count | Source | 1565 | 513k | fn read_residual_data( | 1566 | 513k | &mut self, | 1567 | 513k | mb: &mut MacroBlock, | 1568 | 513k | mbx: usize, | 1569 | 513k | p: usize, | 1570 | 513k | ) -> Result<[i32; 384], DecodingError> { | 1571 | 513k | let sindex = mb.segmentid as usize; | 1572 | 513k | let mut blocks = [0i32; 384]; | 1573 | 513k | let mut plane = if mb.luma_mode == LumaMode::B { 3 } else { 1 }; | 1574 | | | 1575 | 513k | if plane == 1 { | 1576 | 216k | let complexity = self.top[mbx].complexity[0] + self.left.complexity[0]; | 1577 | 216k | let mut block = [0i32; 16]; | 1578 | 216k | let dcq = self.segment[sindex].y2dc; | 1579 | 216k | let acq = self.segment[sindex].y2ac; | 1580 | 216k | let n = self.read_coefficients(&mut block, p, plane, complexity as usize, dcq, acq)?; | 1581 | | | 1582 | 216k | self.left.complexity[0] = if n { 1 } else { 0 }; | 1583 | 216k | self.top[mbx].complexity[0] = if n { 1 } else { 0 }; | 1584 | | | 1585 | 216k | transform::iwht4x4(&mut block); | 1586 | | | 1587 | 3.67M | for k in 0usize..16 { | 1588 | 3.46M | blocks[16 * k] = block[k]; | 1589 | 3.46M | } | 1590 | | | 1591 | 216k | plane = 0; | 1592 | 296k | } | 1593 | | | 1594 | 2.56M | for y in 0usize..4 { | 1595 | 2.05M | let mut left = self.left.complexity[y + 1]; | 1596 | 10.2M | for x in 0usize..4 { | 1597 | 8.20M | let i = x + y * 4; | 1598 | 8.20M | let block = &mut blocks[i * 16..][..16]; | 1599 | 8.20M | let block: &mut [i32; 16] = block.try_into().unwrap(); | 1600 | | | 1601 | 8.20M | let complexity = self.top[mbx].complexity[x + 1] + left; | 1602 | 8.20M | let dcq = self.segment[sindex].ydc; | 1603 | 8.20M | let acq = self.segment[sindex].yac; | 1604 | | | 1605 | 8.20M | let n = self.read_coefficients(block, p, plane, complexity as usize, dcq, acq)?; | 1606 | | | 1607 | 8.20M | if block[0] != 0 || n { | 1608 | 2.45M | mb.non_zero_dct = true; | 1609 | 2.45M | transform::idct4x4(block); | 1610 | 5.74M | } | 1611 | | | 1612 | 8.20M | left = if n { 1 } else { 0 }; | 1613 | 8.20M | self.top[mbx].complexity[x + 1] = if n { 1 } else { 0 }; | 1614 | | } | 1615 | | | 1616 | 2.05M | self.left.complexity[y + 1] = left; | 1617 | | } | 1618 | | | 1619 | 512k | plane = 2; | 1620 | | | 1621 | 1.53M | for &j in &[5usize, 7usize] { | 1622 | 3.07M | for y in 0usize..2 { | 1623 | 2.04M | let mut left = self.left.complexity[y + j]; | 1624 | | | 1625 | 6.14M | for x in 0usize..2 { | 1626 | 4.09M | let i = x + y * 2 + if j == 5 { 16 } else { 20 }; | 1627 | 4.09M | let block = &mut blocks[i * 16..][..16]; | 1628 | 4.09M | let block: &mut [i32; 16] = block.try_into().unwrap(); | 1629 | | | 1630 | 4.09M | let complexity = self.top[mbx].complexity[x + j] + left; | 1631 | 4.09M | let dcq = self.segment[sindex].uvdc; | 1632 | 4.09M | let acq = self.segment[sindex].uvac; | 1633 | | | 1634 | 4.09M | let n = | 1635 | 4.09M | self.read_coefficients(block, p, plane, complexity as usize, dcq, acq)?; | 1636 | 4.09M | if block[0] != 0 || n { | 1637 | 309k | mb.non_zero_dct = true; | 1638 | 309k | transform::idct4x4(block); | 1639 | 3.79M | } | 1640 | | | 1641 | 4.09M | left = if n { 1 } else { 0 }; | 1642 | 4.09M | self.top[mbx].complexity[x + j] = if n { 1 } else { 0 }; | 1643 | | } | 1644 | | | 1645 | 2.04M | self.left.complexity[y + j] = left; | 1646 | | } | 1647 | | } | 1648 | | | 1649 | 512k | Ok(blocks) | 1650 | 513k | } |
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::read_residual_data |
1651 | | |
1652 | | /// Does loop filtering on the macroblock |
1653 | 1.56M | fn loop_filter(&mut self, mbx: usize, mby: usize, mb: &MacroBlock) { |
1654 | 1.56M | let luma_w = self.mbwidth as usize * 16; |
1655 | 1.56M | let chroma_w = self.mbwidth as usize * 8; |
1656 | | |
1657 | 1.56M | let (filter_level, interior_limit, hev_threshold) = self.calculate_filter_parameters(mb); |
1658 | | |
1659 | 1.56M | if filter_level > 0 { |
1660 | 1.54M | let mbedge_limit = (filter_level + 2) * 2 + interior_limit; |
1661 | 1.54M | let sub_bedge_limit = (filter_level * 2) + interior_limit; |
1662 | | |
1663 | | // we skip subblock filtering if the coding mode isn't B_PRED and there's no DCT coefficient coded |
1664 | 1.54M | let do_subblock_filtering = |
1665 | 1.54M | mb.luma_mode == LumaMode::B || (!mb.coeffs_skipped && mb.non_zero_dct); |
1666 | | |
1667 | | //filter across left of macroblock |
1668 | 1.54M | if mbx > 0 { |
1669 | | //simple loop filtering |
1670 | 1.51M | if self.frame.filter_type { |
1671 | 3.49M | for y in 0usize..16 { |
1672 | 3.29M | let y0 = mby * 16 + y; |
1673 | 3.29M | let x0 = mbx * 16; |
1674 | 3.29M | |
1675 | 3.29M | loop_filter::simple_segment_horizontal( |
1676 | 3.29M | mbedge_limit, |
1677 | 3.29M | &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8], |
1678 | 3.29M | ); |
1679 | 3.29M | } |
1680 | | } else { |
1681 | 22.2M | for y in 0usize..16 { |
1682 | 20.9M | let y0 = mby * 16 + y; |
1683 | 20.9M | let x0 = mbx * 16; |
1684 | 20.9M | |
1685 | 20.9M | loop_filter::macroblock_filter_horizontal( |
1686 | 20.9M | hev_threshold, |
1687 | 20.9M | interior_limit, |
1688 | 20.9M | mbedge_limit, |
1689 | 20.9M | &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8], |
1690 | 20.9M | ); |
1691 | 20.9M | } |
1692 | | |
1693 | 11.7M | for y in 0usize..8 { |
1694 | 10.4M | let y0 = mby * 8 + y; |
1695 | 10.4M | let x0 = mbx * 8; |
1696 | 10.4M | |
1697 | 10.4M | loop_filter::macroblock_filter_horizontal( |
1698 | 10.4M | hev_threshold, |
1699 | 10.4M | interior_limit, |
1700 | 10.4M | mbedge_limit, |
1701 | 10.4M | &mut self.frame.ubuf[y0 * chroma_w + x0 - 4..][..8], |
1702 | 10.4M | ); |
1703 | 10.4M | loop_filter::macroblock_filter_horizontal( |
1704 | 10.4M | hev_threshold, |
1705 | 10.4M | interior_limit, |
1706 | 10.4M | mbedge_limit, |
1707 | 10.4M | &mut self.frame.vbuf[y0 * chroma_w + x0 - 4..][..8], |
1708 | 10.4M | ); |
1709 | 10.4M | } |
1710 | | } |
1711 | 27.2k | } |
1712 | | |
1713 | | //filter across vertical subblocks in macroblock |
1714 | 1.54M | if do_subblock_filtering { |
1715 | 690k | if self.frame.filter_type { |
1716 | 373k | for x in (4usize..16 - 1).step_by(4) { |
1717 | 6.34M | for y in 0..16 { |
1718 | 5.97M | let y0 = mby * 16 + y; |
1719 | 5.97M | let x0 = mbx * 16 + x; |
1720 | 5.97M | |
1721 | 5.97M | loop_filter::simple_segment_horizontal( |
1722 | 5.97M | sub_bedge_limit, |
1723 | 5.97M | &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8], |
1724 | 5.97M | ); |
1725 | 5.97M | } |
1726 | | } |
1727 | | } else { |
1728 | 1.69M | for x in (4usize..16 - 3).step_by(4) { |
1729 | 28.8M | for y in 0..16 { |
1730 | 27.1M | let y0 = mby * 16 + y; |
1731 | 27.1M | let x0 = mbx * 16 + x; |
1732 | 27.1M | |
1733 | 27.1M | loop_filter::subblock_filter_horizontal( |
1734 | 27.1M | hev_threshold, |
1735 | 27.1M | interior_limit, |
1736 | 27.1M | sub_bedge_limit, |
1737 | 27.1M | &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8], |
1738 | 27.1M | ); |
1739 | 27.1M | } |
1740 | | } |
1741 | | |
1742 | 5.09M | for y in 0usize..8 { |
1743 | 4.52M | let y0 = mby * 8 + y; |
1744 | 4.52M | let x0 = mbx * 8 + 4; |
1745 | 4.52M | |
1746 | 4.52M | loop_filter::subblock_filter_horizontal( |
1747 | 4.52M | hev_threshold, |
1748 | 4.52M | interior_limit, |
1749 | 4.52M | sub_bedge_limit, |
1750 | 4.52M | &mut self.frame.ubuf[y0 * chroma_w + x0 - 4..][..8], |
1751 | 4.52M | ); |
1752 | 4.52M | |
1753 | 4.52M | loop_filter::subblock_filter_horizontal( |
1754 | 4.52M | hev_threshold, |
1755 | 4.52M | interior_limit, |
1756 | 4.52M | sub_bedge_limit, |
1757 | 4.52M | &mut self.frame.vbuf[y0 * chroma_w + x0 - 4..][..8], |
1758 | 4.52M | ); |
1759 | 4.52M | } |
1760 | | } |
1761 | 850k | } |
1762 | | |
1763 | | //filter across top of macroblock |
1764 | 1.54M | if mby > 0 { |
1765 | 1.50M | if self.frame.filter_type { |
1766 | 3.39M | for x in 0usize..16 { |
1767 | 3.19M | let y0 = mby * 16; |
1768 | 3.19M | let x0 = mbx * 16 + x; |
1769 | 3.19M | |
1770 | 3.19M | loop_filter::simple_segment_vertical( |
1771 | 3.19M | mbedge_limit, |
1772 | 3.19M | &mut self.frame.ybuf[..], |
1773 | 3.19M | y0 * luma_w + x0, |
1774 | 3.19M | luma_w, |
1775 | 3.19M | ); |
1776 | 3.19M | } |
1777 | | } else { |
1778 | | //if bottom macroblock, can only filter if there is 3 pixels below |
1779 | 22.1M | for x in 0usize..16 { |
1780 | 20.8M | let y0 = mby * 16; |
1781 | 20.8M | let x0 = mbx * 16 + x; |
1782 | 20.8M | |
1783 | 20.8M | loop_filter::macroblock_filter_vertical( |
1784 | 20.8M | hev_threshold, |
1785 | 20.8M | interior_limit, |
1786 | 20.8M | mbedge_limit, |
1787 | 20.8M | &mut self.frame.ybuf[..], |
1788 | 20.8M | y0 * luma_w + x0, |
1789 | 20.8M | luma_w, |
1790 | 20.8M | ); |
1791 | 20.8M | } |
1792 | | |
1793 | 11.7M | for x in 0usize..8 { |
1794 | 10.4M | let y0 = mby * 8; |
1795 | 10.4M | let x0 = mbx * 8 + x; |
1796 | 10.4M | |
1797 | 10.4M | loop_filter::macroblock_filter_vertical( |
1798 | 10.4M | hev_threshold, |
1799 | 10.4M | interior_limit, |
1800 | 10.4M | mbedge_limit, |
1801 | 10.4M | &mut self.frame.ubuf[..], |
1802 | 10.4M | y0 * chroma_w + x0, |
1803 | 10.4M | chroma_w, |
1804 | 10.4M | ); |
1805 | 10.4M | loop_filter::macroblock_filter_vertical( |
1806 | 10.4M | hev_threshold, |
1807 | 10.4M | interior_limit, |
1808 | 10.4M | mbedge_limit, |
1809 | 10.4M | &mut self.frame.vbuf[..], |
1810 | 10.4M | y0 * chroma_w + x0, |
1811 | 10.4M | chroma_w, |
1812 | 10.4M | ); |
1813 | 10.4M | } |
1814 | | } |
1815 | 39.8k | } |
1816 | | |
1817 | | //filter across horizontal subblock edges within the macroblock |
1818 | 1.54M | if do_subblock_filtering { |
1819 | 690k | if self.frame.filter_type { |
1820 | 373k | for y in (4usize..16 - 1).step_by(4) { |
1821 | 6.34M | for x in 0..16 { |
1822 | 5.97M | let y0 = mby * 16 + y; |
1823 | 5.97M | let x0 = mbx * 16 + x; |
1824 | 5.97M | |
1825 | 5.97M | loop_filter::simple_segment_vertical( |
1826 | 5.97M | sub_bedge_limit, |
1827 | 5.97M | &mut self.frame.ybuf[..], |
1828 | 5.97M | y0 * luma_w + x0, |
1829 | 5.97M | luma_w, |
1830 | 5.97M | ); |
1831 | 5.97M | } |
1832 | | } |
1833 | | } else { |
1834 | 1.69M | for y in (4usize..16 - 3).step_by(4) { |
1835 | 28.8M | for x in 0..16 { |
1836 | 27.1M | let y0 = mby * 16 + y; |
1837 | 27.1M | let x0 = mbx * 16 + x; |
1838 | 27.1M | |
1839 | 27.1M | loop_filter::subblock_filter_vertical( |
1840 | 27.1M | hev_threshold, |
1841 | 27.1M | interior_limit, |
1842 | 27.1M | sub_bedge_limit, |
1843 | 27.1M | &mut self.frame.ybuf[..], |
1844 | 27.1M | y0 * luma_w + x0, |
1845 | 27.1M | luma_w, |
1846 | 27.1M | ); |
1847 | 27.1M | } |
1848 | | } |
1849 | | |
1850 | 5.09M | for x in 0..8 { |
1851 | 4.52M | let y0 = mby * 8 + 4; |
1852 | 4.52M | let x0 = mbx * 8 + x; |
1853 | 4.52M | |
1854 | 4.52M | loop_filter::subblock_filter_vertical( |
1855 | 4.52M | hev_threshold, |
1856 | 4.52M | interior_limit, |
1857 | 4.52M | sub_bedge_limit, |
1858 | 4.52M | &mut self.frame.ubuf[..], |
1859 | 4.52M | y0 * chroma_w + x0, |
1860 | 4.52M | chroma_w, |
1861 | 4.52M | ); |
1862 | 4.52M | |
1863 | 4.52M | loop_filter::subblock_filter_vertical( |
1864 | 4.52M | hev_threshold, |
1865 | 4.52M | interior_limit, |
1866 | 4.52M | sub_bedge_limit, |
1867 | 4.52M | &mut self.frame.vbuf[..], |
1868 | 4.52M | y0 * chroma_w + x0, |
1869 | 4.52M | chroma_w, |
1870 | 4.52M | ); |
1871 | 4.52M | } |
1872 | | } |
1873 | 850k | } |
1874 | 23.7k | } |
1875 | 1.56M | } <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::loop_filter Line | Count | Source | 1653 | 1.56M | fn loop_filter(&mut self, mbx: usize, mby: usize, mb: &MacroBlock) { | 1654 | 1.56M | let luma_w = self.mbwidth as usize * 16; | 1655 | 1.56M | let chroma_w = self.mbwidth as usize * 8; | 1656 | | | 1657 | 1.56M | let (filter_level, interior_limit, hev_threshold) = self.calculate_filter_parameters(mb); | 1658 | | | 1659 | 1.56M | if filter_level > 0 { | 1660 | 1.54M | let mbedge_limit = (filter_level + 2) * 2 + interior_limit; | 1661 | 1.54M | let sub_bedge_limit = (filter_level * 2) + interior_limit; | 1662 | | | 1663 | | // we skip subblock filtering if the coding mode isn't B_PRED and there's no DCT coefficient coded | 1664 | 1.54M | let do_subblock_filtering = | 1665 | 1.54M | mb.luma_mode == LumaMode::B || (!mb.coeffs_skipped && mb.non_zero_dct); | 1666 | | | 1667 | | //filter across left of macroblock | 1668 | 1.54M | if mbx > 0 { | 1669 | | //simple loop filtering | 1670 | 1.51M | if self.frame.filter_type { | 1671 | 3.49M | for y in 0usize..16 { | 1672 | 3.29M | let y0 = mby * 16 + y; | 1673 | 3.29M | let x0 = mbx * 16; | 1674 | 3.29M | | 1675 | 3.29M | loop_filter::simple_segment_horizontal( | 1676 | 3.29M | mbedge_limit, | 1677 | 3.29M | &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8], | 1678 | 3.29M | ); | 1679 | 3.29M | } | 1680 | | } else { | 1681 | 22.2M | for y in 0usize..16 { | 1682 | 20.9M | let y0 = mby * 16 + y; | 1683 | 20.9M | let x0 = mbx * 16; | 1684 | 20.9M | | 1685 | 20.9M | loop_filter::macroblock_filter_horizontal( | 1686 | 20.9M | hev_threshold, | 1687 | 20.9M | interior_limit, | 1688 | 20.9M | mbedge_limit, | 1689 | 20.9M | &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8], | 1690 | 20.9M | ); | 1691 | 20.9M | } | 1692 | | | 1693 | 11.7M | for y in 0usize..8 { | 1694 | 10.4M | let y0 = mby * 8 + y; | 1695 | 10.4M | let x0 = mbx * 8; | 1696 | 10.4M | | 1697 | 10.4M | loop_filter::macroblock_filter_horizontal( | 1698 | 10.4M | hev_threshold, | 1699 | 10.4M | interior_limit, | 1700 | 10.4M | mbedge_limit, | 1701 | 10.4M | &mut self.frame.ubuf[y0 * chroma_w + x0 - 4..][..8], | 1702 | 10.4M | ); | 1703 | 10.4M | loop_filter::macroblock_filter_horizontal( | 1704 | 10.4M | hev_threshold, | 1705 | 10.4M | interior_limit, | 1706 | 10.4M | mbedge_limit, | 1707 | 10.4M | &mut self.frame.vbuf[y0 * chroma_w + x0 - 4..][..8], | 1708 | 10.4M | ); | 1709 | 10.4M | } | 1710 | | } | 1711 | 27.2k | } | 1712 | | | 1713 | | //filter across vertical subblocks in macroblock | 1714 | 1.54M | if do_subblock_filtering { | 1715 | 690k | if self.frame.filter_type { | 1716 | 373k | for x in (4usize..16 - 1).step_by(4) { | 1717 | 6.34M | for y in 0..16 { | 1718 | 5.97M | let y0 = mby * 16 + y; | 1719 | 5.97M | let x0 = mbx * 16 + x; | 1720 | 5.97M | | 1721 | 5.97M | loop_filter::simple_segment_horizontal( | 1722 | 5.97M | sub_bedge_limit, | 1723 | 5.97M | &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8], | 1724 | 5.97M | ); | 1725 | 5.97M | } | 1726 | | } | 1727 | | } else { | 1728 | 1.69M | for x in (4usize..16 - 3).step_by(4) { | 1729 | 28.8M | for y in 0..16 { | 1730 | 27.1M | let y0 = mby * 16 + y; | 1731 | 27.1M | let x0 = mbx * 16 + x; | 1732 | 27.1M | | 1733 | 27.1M | loop_filter::subblock_filter_horizontal( | 1734 | 27.1M | hev_threshold, | 1735 | 27.1M | interior_limit, | 1736 | 27.1M | sub_bedge_limit, | 1737 | 27.1M | &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8], | 1738 | 27.1M | ); | 1739 | 27.1M | } | 1740 | | } | 1741 | | | 1742 | 5.09M | for y in 0usize..8 { | 1743 | 4.52M | let y0 = mby * 8 + y; | 1744 | 4.52M | let x0 = mbx * 8 + 4; | 1745 | 4.52M | | 1746 | 4.52M | loop_filter::subblock_filter_horizontal( | 1747 | 4.52M | hev_threshold, | 1748 | 4.52M | interior_limit, | 1749 | 4.52M | sub_bedge_limit, | 1750 | 4.52M | &mut self.frame.ubuf[y0 * chroma_w + x0 - 4..][..8], | 1751 | 4.52M | ); | 1752 | 4.52M | | 1753 | 4.52M | loop_filter::subblock_filter_horizontal( | 1754 | 4.52M | hev_threshold, | 1755 | 4.52M | interior_limit, | 1756 | 4.52M | sub_bedge_limit, | 1757 | 4.52M | &mut self.frame.vbuf[y0 * chroma_w + x0 - 4..][..8], | 1758 | 4.52M | ); | 1759 | 4.52M | } | 1760 | | } | 1761 | 850k | } | 1762 | | | 1763 | | //filter across top of macroblock | 1764 | 1.54M | if mby > 0 { | 1765 | 1.50M | if self.frame.filter_type { | 1766 | 3.39M | for x in 0usize..16 { | 1767 | 3.19M | let y0 = mby * 16; | 1768 | 3.19M | let x0 = mbx * 16 + x; | 1769 | 3.19M | | 1770 | 3.19M | loop_filter::simple_segment_vertical( | 1771 | 3.19M | mbedge_limit, | 1772 | 3.19M | &mut self.frame.ybuf[..], | 1773 | 3.19M | y0 * luma_w + x0, | 1774 | 3.19M | luma_w, | 1775 | 3.19M | ); | 1776 | 3.19M | } | 1777 | | } else { | 1778 | | //if bottom macroblock, can only filter if there is 3 pixels below | 1779 | 22.1M | for x in 0usize..16 { | 1780 | 20.8M | let y0 = mby * 16; | 1781 | 20.8M | let x0 = mbx * 16 + x; | 1782 | 20.8M | | 1783 | 20.8M | loop_filter::macroblock_filter_vertical( | 1784 | 20.8M | hev_threshold, | 1785 | 20.8M | interior_limit, | 1786 | 20.8M | mbedge_limit, | 1787 | 20.8M | &mut self.frame.ybuf[..], | 1788 | 20.8M | y0 * luma_w + x0, | 1789 | 20.8M | luma_w, | 1790 | 20.8M | ); | 1791 | 20.8M | } | 1792 | | | 1793 | 11.7M | for x in 0usize..8 { | 1794 | 10.4M | let y0 = mby * 8; | 1795 | 10.4M | let x0 = mbx * 8 + x; | 1796 | 10.4M | | 1797 | 10.4M | loop_filter::macroblock_filter_vertical( | 1798 | 10.4M | hev_threshold, | 1799 | 10.4M | interior_limit, | 1800 | 10.4M | mbedge_limit, | 1801 | 10.4M | &mut self.frame.ubuf[..], | 1802 | 10.4M | y0 * chroma_w + x0, | 1803 | 10.4M | chroma_w, | 1804 | 10.4M | ); | 1805 | 10.4M | loop_filter::macroblock_filter_vertical( | 1806 | 10.4M | hev_threshold, | 1807 | 10.4M | interior_limit, | 1808 | 10.4M | mbedge_limit, | 1809 | 10.4M | &mut self.frame.vbuf[..], | 1810 | 10.4M | y0 * chroma_w + x0, | 1811 | 10.4M | chroma_w, | 1812 | 10.4M | ); | 1813 | 10.4M | } | 1814 | | } | 1815 | 39.8k | } | 1816 | | | 1817 | | //filter across horizontal subblock edges within the macroblock | 1818 | 1.54M | if do_subblock_filtering { | 1819 | 690k | if self.frame.filter_type { | 1820 | 373k | for y in (4usize..16 - 1).step_by(4) { | 1821 | 6.34M | for x in 0..16 { | 1822 | 5.97M | let y0 = mby * 16 + y; | 1823 | 5.97M | let x0 = mbx * 16 + x; | 1824 | 5.97M | | 1825 | 5.97M | loop_filter::simple_segment_vertical( | 1826 | 5.97M | sub_bedge_limit, | 1827 | 5.97M | &mut self.frame.ybuf[..], | 1828 | 5.97M | y0 * luma_w + x0, | 1829 | 5.97M | luma_w, | 1830 | 5.97M | ); | 1831 | 5.97M | } | 1832 | | } | 1833 | | } else { | 1834 | 1.69M | for y in (4usize..16 - 3).step_by(4) { | 1835 | 28.8M | for x in 0..16 { | 1836 | 27.1M | let y0 = mby * 16 + y; | 1837 | 27.1M | let x0 = mbx * 16 + x; | 1838 | 27.1M | | 1839 | 27.1M | loop_filter::subblock_filter_vertical( | 1840 | 27.1M | hev_threshold, | 1841 | 27.1M | interior_limit, | 1842 | 27.1M | sub_bedge_limit, | 1843 | 27.1M | &mut self.frame.ybuf[..], | 1844 | 27.1M | y0 * luma_w + x0, | 1845 | 27.1M | luma_w, | 1846 | 27.1M | ); | 1847 | 27.1M | } | 1848 | | } | 1849 | | | 1850 | 5.09M | for x in 0..8 { | 1851 | 4.52M | let y0 = mby * 8 + 4; | 1852 | 4.52M | let x0 = mbx * 8 + x; | 1853 | 4.52M | | 1854 | 4.52M | loop_filter::subblock_filter_vertical( | 1855 | 4.52M | hev_threshold, | 1856 | 4.52M | interior_limit, | 1857 | 4.52M | sub_bedge_limit, | 1858 | 4.52M | &mut self.frame.ubuf[..], | 1859 | 4.52M | y0 * chroma_w + x0, | 1860 | 4.52M | chroma_w, | 1861 | 4.52M | ); | 1862 | 4.52M | | 1863 | 4.52M | loop_filter::subblock_filter_vertical( | 1864 | 4.52M | hev_threshold, | 1865 | 4.52M | interior_limit, | 1866 | 4.52M | sub_bedge_limit, | 1867 | 4.52M | &mut self.frame.vbuf[..], | 1868 | 4.52M | y0 * chroma_w + x0, | 1869 | 4.52M | chroma_w, | 1870 | 4.52M | ); | 1871 | 4.52M | } | 1872 | | } | 1873 | 850k | } | 1874 | 23.7k | } | 1875 | 1.56M | } |
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::loop_filter |
1876 | | |
1877 | | //return values are the filter level, interior limit and hev threshold |
1878 | 1.56M | fn calculate_filter_parameters(&self, macroblock: &MacroBlock) -> (u8, u8, u8) { |
1879 | 1.56M | let segment = self.segment[macroblock.segmentid as usize]; |
1880 | 1.56M | let mut filter_level = i32::from(self.frame.filter_level); |
1881 | | |
1882 | | // if frame level filter level is 0, we must skip loop filter |
1883 | 1.56M | if filter_level == 0 { |
1884 | 5.94k | return (0, 0, 0); |
1885 | 1.55M | } |
1886 | | |
1887 | 1.55M | if self.segments_enabled { |
1888 | 1.13M | if segment.delta_values { |
1889 | 817k | filter_level += i32::from(segment.loopfilter_level); |
1890 | 817k | } else { |
1891 | 321k | filter_level = i32::from(segment.loopfilter_level); |
1892 | 321k | } |
1893 | 418k | } |
1894 | | |
1895 | 1.55M | filter_level = filter_level.clamp(0, 63); |
1896 | | |
1897 | 1.55M | if self.loop_filter_adjustments_enabled { |
1898 | 1.01M | filter_level += self.ref_delta[0]; |
1899 | 1.01M | if macroblock.luma_mode == LumaMode::B { |
1900 | 421k | filter_level += self.mode_delta[0]; |
1901 | 597k | } |
1902 | 538k | } |
1903 | | |
1904 | 1.55M | let filter_level = filter_level.clamp(0, 63) as u8; |
1905 | | |
1906 | | //interior limit |
1907 | 1.55M | let mut interior_limit = filter_level; |
1908 | | |
1909 | 1.55M | if self.frame.sharpness_level > 0 { |
1910 | 1.02M | interior_limit >>= if self.frame.sharpness_level > 4 { 2 } else { 1 }; |
1911 | | |
1912 | 1.02M | if interior_limit > 9 - self.frame.sharpness_level { |
1913 | 894k | interior_limit = 9 - self.frame.sharpness_level; |
1914 | 894k | } |
1915 | 533k | } |
1916 | | |
1917 | 1.55M | if interior_limit == 0 { |
1918 | 67.4k | interior_limit = 1; |
1919 | 1.49M | } |
1920 | | |
1921 | | //high edge variance threshold |
1922 | 1.55M | let mut hev_threshold = 0; |
1923 | | |
1924 | | #[allow(clippy::collapsible_else_if)] |
1925 | 1.55M | if self.frame.keyframe { |
1926 | 1.55M | if filter_level >= 40 { |
1927 | 917k | hev_threshold = 2; |
1928 | 917k | } else if filter_level >= 15 { |
1929 | 344k | hev_threshold = 1; |
1930 | 344k | } |
1931 | | } else { |
1932 | 0 | if filter_level >= 40 { |
1933 | 0 | hev_threshold = 3; |
1934 | 0 | } else if filter_level >= 20 { |
1935 | 0 | hev_threshold = 2; |
1936 | 0 | } else if filter_level >= 15 { |
1937 | 0 | hev_threshold = 1; |
1938 | 0 | } |
1939 | | } |
1940 | | |
1941 | 1.55M | (filter_level, interior_limit, hev_threshold) |
1942 | 1.56M | } <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::calculate_filter_parameters Line | Count | Source | 1878 | 1.56M | fn calculate_filter_parameters(&self, macroblock: &MacroBlock) -> (u8, u8, u8) { | 1879 | 1.56M | let segment = self.segment[macroblock.segmentid as usize]; | 1880 | 1.56M | let mut filter_level = i32::from(self.frame.filter_level); | 1881 | | | 1882 | | // if frame level filter level is 0, we must skip loop filter | 1883 | 1.56M | if filter_level == 0 { | 1884 | 5.94k | return (0, 0, 0); | 1885 | 1.55M | } | 1886 | | | 1887 | 1.55M | if self.segments_enabled { | 1888 | 1.13M | if segment.delta_values { | 1889 | 817k | filter_level += i32::from(segment.loopfilter_level); | 1890 | 817k | } else { | 1891 | 321k | filter_level = i32::from(segment.loopfilter_level); | 1892 | 321k | } | 1893 | 418k | } | 1894 | | | 1895 | 1.55M | filter_level = filter_level.clamp(0, 63); | 1896 | | | 1897 | 1.55M | if self.loop_filter_adjustments_enabled { | 1898 | 1.01M | filter_level += self.ref_delta[0]; | 1899 | 1.01M | if macroblock.luma_mode == LumaMode::B { | 1900 | 421k | filter_level += self.mode_delta[0]; | 1901 | 597k | } | 1902 | 538k | } | 1903 | | | 1904 | 1.55M | let filter_level = filter_level.clamp(0, 63) as u8; | 1905 | | | 1906 | | //interior limit | 1907 | 1.55M | let mut interior_limit = filter_level; | 1908 | | | 1909 | 1.55M | if self.frame.sharpness_level > 0 { | 1910 | 1.02M | interior_limit >>= if self.frame.sharpness_level > 4 { 2 } else { 1 }; | 1911 | | | 1912 | 1.02M | if interior_limit > 9 - self.frame.sharpness_level { | 1913 | 894k | interior_limit = 9 - self.frame.sharpness_level; | 1914 | 894k | } | 1915 | 533k | } | 1916 | | | 1917 | 1.55M | if interior_limit == 0 { | 1918 | 67.4k | interior_limit = 1; | 1919 | 1.49M | } | 1920 | | | 1921 | | //high edge variance threshold | 1922 | 1.55M | let mut hev_threshold = 0; | 1923 | | | 1924 | | #[allow(clippy::collapsible_else_if)] | 1925 | 1.55M | if self.frame.keyframe { | 1926 | 1.55M | if filter_level >= 40 { | 1927 | 917k | hev_threshold = 2; | 1928 | 917k | } else if filter_level >= 15 { | 1929 | 344k | hev_threshold = 1; | 1930 | 344k | } | 1931 | | } else { | 1932 | 0 | if filter_level >= 40 { | 1933 | 0 | hev_threshold = 3; | 1934 | 0 | } else if filter_level >= 20 { | 1935 | 0 | hev_threshold = 2; | 1936 | 0 | } else if filter_level >= 15 { | 1937 | 0 | hev_threshold = 1; | 1938 | 0 | } | 1939 | | } | 1940 | | | 1941 | 1.55M | (filter_level, interior_limit, hev_threshold) | 1942 | 1.56M | } |
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::calculate_filter_parameters |
1943 | | |
1944 | | /// Decodes the current frame |
1945 | 2.67k | pub fn decode_frame(r: R) -> Result<Frame, DecodingError> { |
1946 | 2.67k | let decoder = Self::new(r); |
1947 | 2.67k | decoder.decode_frame_() |
1948 | 2.67k | } <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Line | Count | Source | 1945 | 2.67k | pub fn decode_frame(r: R) -> Result<Frame, DecodingError> { | 1946 | 2.67k | let decoder = Self::new(r); | 1947 | 2.67k | decoder.decode_frame_() | 1948 | 2.67k | } |
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::decode_frame |
1949 | | |
1950 | 2.67k | fn decode_frame_(mut self) -> Result<Frame, DecodingError> { |
1951 | 2.67k | self.read_frame_header()?; |
1952 | | |
1953 | 43.6k | for mby in 0..self.mbheight as usize { |
1954 | 43.6k | let p = mby % self.num_partitions as usize; |
1955 | 43.6k | self.left = MacroBlock::default(); |
1956 | | |
1957 | 2.17M | for mbx in 0..self.mbwidth as usize { |
1958 | 2.17M | let mut mb = self.read_macroblock_header(mbx)?; |
1959 | 2.17M | let blocks = if !mb.coeffs_skipped { |
1960 | 513k | self.read_residual_data(&mut mb, mbx, p)? |
1961 | | } else { |
1962 | 1.66M | if mb.luma_mode != LumaMode::B { |
1963 | 985k | self.left.complexity[0] = 0; |
1964 | 985k | self.top[mbx].complexity[0] = 0; |
1965 | 985k | } |
1966 | | |
1967 | 14.9M | for i in 1usize..9 { |
1968 | 13.3M | self.left.complexity[i] = 0; |
1969 | 13.3M | self.top[mbx].complexity[i] = 0; |
1970 | 13.3M | } |
1971 | | |
1972 | 1.66M | [0i32; 384] |
1973 | | }; |
1974 | | |
1975 | 2.17M | self.intra_predict_luma(mbx, mby, &mb, &blocks); |
1976 | 2.17M | self.intra_predict_chroma(mbx, mby, &mb, &blocks); |
1977 | | |
1978 | 2.17M | self.macroblocks.push(mb); |
1979 | | } |
1980 | | |
1981 | 42.6k | self.left_border_y = vec![129u8; 1 + 16]; |
1982 | 42.6k | self.left_border_u = vec![129u8; 1 + 8]; |
1983 | 42.6k | self.left_border_v = vec![129u8; 1 + 8]; |
1984 | | } |
1985 | | |
1986 | | //do loop filtering |
1987 | 32.3k | for mby in 0..self.mbheight as usize { |
1988 | 1.56M | for mbx in 0..self.mbwidth as usize { |
1989 | 1.56M | let mb = self.macroblocks[mby * self.mbwidth as usize + mbx]; |
1990 | 1.56M | self.loop_filter(mbx, mby, &mb); |
1991 | 1.56M | } |
1992 | | } |
1993 | | |
1994 | 1.14k | Ok(self.frame) |
1995 | 2.67k | } <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame_ Line | Count | Source | 1950 | 2.67k | fn decode_frame_(mut self) -> Result<Frame, DecodingError> { | 1951 | 2.67k | self.read_frame_header()?; | 1952 | | | 1953 | 43.6k | for mby in 0..self.mbheight as usize { | 1954 | 43.6k | let p = mby % self.num_partitions as usize; | 1955 | 43.6k | self.left = MacroBlock::default(); | 1956 | | | 1957 | 2.17M | for mbx in 0..self.mbwidth as usize { | 1958 | 2.17M | let mut mb = self.read_macroblock_header(mbx)?; | 1959 | 2.17M | let blocks = if !mb.coeffs_skipped { | 1960 | 513k | self.read_residual_data(&mut mb, mbx, p)? | 1961 | | } else { | 1962 | 1.66M | if mb.luma_mode != LumaMode::B { | 1963 | 985k | self.left.complexity[0] = 0; | 1964 | 985k | self.top[mbx].complexity[0] = 0; | 1965 | 985k | } | 1966 | | | 1967 | 14.9M | for i in 1usize..9 { | 1968 | 13.3M | self.left.complexity[i] = 0; | 1969 | 13.3M | self.top[mbx].complexity[i] = 0; | 1970 | 13.3M | } | 1971 | | | 1972 | 1.66M | [0i32; 384] | 1973 | | }; | 1974 | | | 1975 | 2.17M | self.intra_predict_luma(mbx, mby, &mb, &blocks); | 1976 | 2.17M | self.intra_predict_chroma(mbx, mby, &mb, &blocks); | 1977 | | | 1978 | 2.17M | self.macroblocks.push(mb); | 1979 | | } | 1980 | | | 1981 | 42.6k | self.left_border_y = vec![129u8; 1 + 16]; | 1982 | 42.6k | self.left_border_u = vec![129u8; 1 + 8]; | 1983 | 42.6k | self.left_border_v = vec![129u8; 1 + 8]; | 1984 | | } | 1985 | | | 1986 | | //do loop filtering | 1987 | 32.3k | for mby in 0..self.mbheight as usize { | 1988 | 1.56M | for mbx in 0..self.mbwidth as usize { | 1989 | 1.56M | let mb = self.macroblocks[mby * self.mbwidth as usize + mbx]; | 1990 | 1.56M | self.loop_filter(mbx, mby, &mb); | 1991 | 1.56M | } | 1992 | | } | 1993 | | | 1994 | 1.14k | Ok(self.frame) | 1995 | 2.67k | } |
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::decode_frame_ |
1996 | | } |
1997 | | |
1998 | | impl LumaMode { |
1999 | 2.17M | const fn from_i8(val: i8) -> Option<Self> { |
2000 | 2.17M | Some(match val { |
2001 | 409k | DC_PRED => Self::DC, |
2002 | 153k | V_PRED => Self::V, |
2003 | 291k | H_PRED => Self::H, |
2004 | 346k | TM_PRED => Self::TM, |
2005 | 977k | B_PRED => Self::B, |
2006 | 0 | _ => return None, |
2007 | | }) |
2008 | 2.17M | } |
2009 | | |
2010 | 2.17M | const fn into_intra(self) -> Option<IntraMode> { |
2011 | 2.17M | Some(match self { |
2012 | 409k | Self::DC => IntraMode::DC, |
2013 | 153k | Self::V => IntraMode::VE, |
2014 | 291k | Self::H => IntraMode::HE, |
2015 | 346k | Self::TM => IntraMode::TM, |
2016 | 977k | Self::B => return None, |
2017 | | }) |
2018 | 2.17M | } |
2019 | | } |
2020 | | |
2021 | | impl ChromaMode { |
2022 | 2.17M | const fn from_i8(val: i8) -> Option<Self> { |
2023 | 2.17M | Some(match val { |
2024 | 1.11M | DC_PRED => Self::DC, |
2025 | 377k | V_PRED => Self::V, |
2026 | 275k | H_PRED => Self::H, |
2027 | 412k | TM_PRED => Self::TM, |
2028 | 0 | _ => return None, |
2029 | | }) |
2030 | 2.17M | } |
2031 | | } |
2032 | | |
2033 | | impl IntraMode { |
2034 | 15.6M | const fn from_i8(val: i8) -> Option<Self> { |
2035 | 15.6M | Some(match val { |
2036 | 10.0M | B_DC_PRED => Self::DC, |
2037 | 2.12M | B_TM_PRED => Self::TM, |
2038 | 916k | B_VE_PRED => Self::VE, |
2039 | 672k | B_HE_PRED => Self::HE, |
2040 | 275k | B_LD_PRED => Self::LD, |
2041 | 234k | B_RD_PRED => Self::RD, |
2042 | 321k | B_VR_PRED => Self::VR, |
2043 | 370k | B_VL_PRED => Self::VL, |
2044 | 295k | B_HD_PRED => Self::HD, |
2045 | 377k | B_HU_PRED => Self::HU, |
2046 | 0 | _ => return None, |
2047 | | }) |
2048 | 15.6M | } |
2049 | | } |
2050 | | |
2051 | 2.58k | fn init_top_macroblocks(width: usize) -> Vec<MacroBlock> { |
2052 | 2.58k | let mb_width = width.div_ceil(16); |
2053 | | |
2054 | 2.58k | let mb = MacroBlock { |
2055 | 2.58k | // Section 11.3 #3 |
2056 | 2.58k | bpred: [IntraMode::DC; 16], |
2057 | 2.58k | luma_mode: LumaMode::DC, |
2058 | 2.58k | ..MacroBlock::default() |
2059 | 2.58k | }; |
2060 | | |
2061 | 2.58k | vec![mb; mb_width] |
2062 | 2.58k | } |
2063 | | |
2064 | 2.17M | fn create_border_luma(mbx: usize, mby: usize, mbw: usize, top: &[u8], left: &[u8]) -> [u8; 357] { |
2065 | 2.17M | let stride = 1usize + 16 + 4; |
2066 | 2.17M | let mut ws = [0u8; (1 + 16) * (1 + 16 + 4)]; |
2067 | | |
2068 | | // A |
2069 | | { |
2070 | 2.17M | let above = &mut ws[1..stride]; |
2071 | 2.17M | if mby == 0 { |
2072 | 1.65M | for above in above.iter_mut() { |
2073 | 1.65M | *above = 127; |
2074 | 1.65M | } |
2075 | | } else { |
2076 | 33.5M | for (above, &top) in above[..16].iter_mut().zip(&top[mbx * 16..]) { |
2077 | 33.5M | *above = top; |
2078 | 33.5M | } |
2079 | | |
2080 | 2.09M | if mbx == mbw - 1 { |
2081 | 154k | for above in &mut above[16..] { |
2082 | 154k | *above = top[mbx * 16 + 15]; |
2083 | 154k | } |
2084 | | } else { |
2085 | 8.22M | for (above, &top) in above[16..].iter_mut().zip(&top[mbx * 16 + 16..]) { |
2086 | 8.22M | *above = top; |
2087 | 8.22M | } |
2088 | | } |
2089 | | } |
2090 | | } |
2091 | | |
2092 | 8.71M | for i in 17usize..stride { |
2093 | 8.71M | ws[4 * stride + i] = ws[i]; |
2094 | 8.71M | ws[8 * stride + i] = ws[i]; |
2095 | 8.71M | ws[12 * stride + i] = ws[i]; |
2096 | 8.71M | } |
2097 | | |
2098 | | // L |
2099 | 2.17M | if mbx == 0 { |
2100 | 694k | for i in 0usize..16 { |
2101 | 653k | ws[(i + 1) * stride] = 129; |
2102 | 653k | } |
2103 | | } else { |
2104 | 34.2M | for (i, &left) in (0usize..16).zip(&left[1..]) { |
2105 | 34.2M | ws[(i + 1) * stride] = left; |
2106 | 34.2M | } |
2107 | | } |
2108 | | |
2109 | | // P |
2110 | 2.17M | ws[0] = if mby == 0 { |
2111 | 82.8k | 127 |
2112 | 2.09M | } else if mbx == 0 { |
2113 | 38.9k | 129 |
2114 | | } else { |
2115 | 2.05M | left[0] |
2116 | | }; |
2117 | | |
2118 | 2.17M | ws |
2119 | 2.17M | } |
2120 | | |
2121 | | const CHROMA_BLOCK_SIZE: usize = (8 + 1) * (8 + 1); |
2122 | | // creates the left and top border for chroma prediction |
2123 | 4.35M | fn create_border_chroma( |
2124 | 4.35M | mbx: usize, |
2125 | 4.35M | mby: usize, |
2126 | 4.35M | top: &[u8], |
2127 | 4.35M | left: &[u8], |
2128 | 4.35M | ) -> [u8; CHROMA_BLOCK_SIZE] { |
2129 | 4.35M | let stride: usize = 1usize + 8; |
2130 | 4.35M | let mut chroma_block = [0u8; CHROMA_BLOCK_SIZE]; |
2131 | | |
2132 | | // above |
2133 | | { |
2134 | 4.35M | let above = &mut chroma_block[1..stride]; |
2135 | 4.35M | if mby == 0 { |
2136 | 1.32M | for above in above.iter_mut() { |
2137 | 1.32M | *above = 127; |
2138 | 1.32M | } |
2139 | | } else { |
2140 | 33.5M | for (above, &top) in above.iter_mut().zip(&top[mbx * 8..]) { |
2141 | 33.5M | *above = top; |
2142 | 33.5M | } |
2143 | | } |
2144 | | } |
2145 | | |
2146 | | // left |
2147 | 4.35M | if mbx == 0 { |
2148 | 735k | for y in 0usize..8 { |
2149 | 653k | chroma_block[(y + 1) * stride] = 129; |
2150 | 653k | } |
2151 | | } else { |
2152 | 34.2M | for (y, &left) in (0usize..8).zip(&left[1..]) { |
2153 | 34.2M | chroma_block[(y + 1) * stride] = left; |
2154 | 34.2M | } |
2155 | | } |
2156 | | |
2157 | 4.35M | chroma_block[0] = if mby == 0 { |
2158 | 165k | 127 |
2159 | 4.19M | } else if mbx == 0 { |
2160 | 77.8k | 129 |
2161 | | } else { |
2162 | 4.11M | left[0] |
2163 | | }; |
2164 | | |
2165 | 4.35M | chroma_block |
2166 | 4.35M | } |
2167 | | |
2168 | | // set border |
2169 | 4.35M | fn set_chroma_border( |
2170 | 4.35M | left_border: &mut [u8], |
2171 | 4.35M | top_border: &mut [u8], |
2172 | 4.35M | chroma_block: &[u8], |
2173 | 4.35M | mbx: usize, |
2174 | 4.35M | ) { |
2175 | 4.35M | let stride = 1usize + 8; |
2176 | | // top left is top right of previous chroma block |
2177 | 4.35M | left_border[0] = chroma_block[8]; |
2178 | | |
2179 | | // left border |
2180 | 34.8M | for (i, left) in left_border[1..][..8].iter_mut().enumerate() { |
2181 | 34.8M | *left = chroma_block[(i + 1) * stride + 8]; |
2182 | 34.8M | } |
2183 | | |
2184 | 34.8M | for (top, &w) in top_border[mbx * 8..][..8] |
2185 | 4.35M | .iter_mut() |
2186 | 4.35M | .zip(&chroma_block[8 * stride + 1..][..8]) |
2187 | 34.8M | { |
2188 | 34.8M | *top = w; |
2189 | 34.8M | } |
2190 | 4.35M | } |
2191 | | |
2192 | 20.6M | fn avg3(left: u8, this: u8, right: u8) -> u8 { |
2193 | 20.6M | let avg = (u16::from(left) + 2 * u16::from(this) + u16::from(right) + 2) >> 2; |
2194 | 20.6M | avg as u8 |
2195 | 20.6M | } |
2196 | | |
2197 | 8.79M | fn avg2(this: u8, right: u8) -> u8 { |
2198 | 8.79M | let avg = (u16::from(this) + u16::from(right) + 1) >> 1; |
2199 | 8.79M | avg as u8 |
2200 | 8.79M | } |
2201 | | |
2202 | | // Only 16 elements from rblock are used to add residue, so it is restricted to 16 elements |
2203 | | // to enable SIMD and other optimizations. |
2204 | | // |
2205 | | // Clippy suggests the clamp method, but it seems to optimize worse as of rustc 1.82.0 nightly. |
2206 | | #[allow(clippy::manual_clamp)] |
2207 | 52.2M | fn add_residue(pblock: &mut [u8], rblock: &[i32; 16], y0: usize, x0: usize, stride: usize) { |
2208 | 52.2M | let mut pos = y0 * stride + x0; |
2209 | 209M | for row in rblock.chunks(4) { |
2210 | 836M | for (p, &a) in pblock[pos..][..4].iter_mut().zip(row.iter()) { |
2211 | 836M | *p = (a + i32::from(*p)).max(0).min(255) as u8; |
2212 | 836M | } |
2213 | 209M | pos += stride; |
2214 | | } |
2215 | 52.2M | } |
2216 | | |
2217 | 976k | fn predict_4x4(ws: &mut [u8], stride: usize, modes: &[IntraMode], resdata: &[i32]) { |
2218 | 4.88M | for sby in 0usize..4 { |
2219 | 19.5M | for sbx in 0usize..4 { |
2220 | 15.6M | let i = sbx + sby * 4; |
2221 | 15.6M | let y0 = sby * 4 + 1; |
2222 | 15.6M | let x0 = sbx * 4 + 1; |
2223 | | |
2224 | 15.6M | match modes[i] { |
2225 | 2.11M | IntraMode::TM => predict_tmpred(ws, 4, x0, y0, stride), |
2226 | 916k | IntraMode::VE => predict_bvepred(ws, x0, y0, stride), |
2227 | 672k | IntraMode::HE => predict_bhepred(ws, x0, y0, stride), |
2228 | 10.0M | IntraMode::DC => predict_bdcpred(ws, x0, y0, stride), |
2229 | 275k | IntraMode::LD => predict_bldpred(ws, x0, y0, stride), |
2230 | 234k | IntraMode::RD => predict_brdpred(ws, x0, y0, stride), |
2231 | 321k | IntraMode::VR => predict_bvrpred(ws, x0, y0, stride), |
2232 | 370k | IntraMode::VL => predict_bvlpred(ws, x0, y0, stride), |
2233 | 295k | IntraMode::HD => predict_bhdpred(ws, x0, y0, stride), |
2234 | 377k | IntraMode::HU => predict_bhupred(ws, x0, y0, stride), |
2235 | | } |
2236 | | |
2237 | 15.6M | let rb: &[i32; 16] = resdata[i * 16..][..16].try_into().unwrap(); |
2238 | 15.6M | add_residue(ws, rb, y0, x0, stride); |
2239 | | } |
2240 | | } |
2241 | 976k | } |
2242 | | |
2243 | 909k | fn predict_vpred(a: &mut [u8], size: usize, x0: usize, y0: usize, stride: usize) { |
2244 | | // This pass copies the top row to the rows below it. |
2245 | 909k | let (above, curr) = a.split_at_mut(stride * y0); |
2246 | 909k | let above_slice = &above[x0..]; |
2247 | | |
2248 | 8.50M | for curr_chunk in curr.chunks_exact_mut(stride).take(size) { |
2249 | 97.5M | for (curr, &above) in curr_chunk[1..].iter_mut().zip(above_slice) { |
2250 | 97.5M | *curr = above; |
2251 | 97.5M | } |
2252 | | } |
2253 | 909k | } |
2254 | | |
2255 | 841k | fn predict_hpred(a: &mut [u8], size: usize, x0: usize, y0: usize, stride: usize) { |
2256 | | // This pass copies the first value of a row to the values right of it. |
2257 | 9.05M | for chunk in a.chunks_exact_mut(stride).skip(y0).take(size) { |
2258 | 9.05M | let left = chunk[x0 - 1]; |
2259 | 128M | chunk[x0..].iter_mut().for_each(|a| *a = left); |
2260 | | } |
2261 | 841k | } |
2262 | | |
2263 | 2.63M | fn predict_dcpred(a: &mut [u8], size: usize, stride: usize, above: bool, left: bool) { |
2264 | 2.63M | let mut sum = 0; |
2265 | 2.63M | let mut shf = if size == 8 { 2 } else { 3 }; |
2266 | | |
2267 | 2.63M | if left { |
2268 | 23.9M | for y in 0usize..size { |
2269 | 23.9M | sum += u32::from(a[(y + 1) * stride]); |
2270 | 23.9M | } |
2271 | | |
2272 | 2.58M | shf += 1; |
2273 | 46.4k | } |
2274 | | |
2275 | 2.63M | if above { |
2276 | 23.5M | sum += a[1..=size].iter().fold(0, |acc, &x| acc + u32::from(x)); |
2277 | | |
2278 | 2.54M | shf += 1; |
2279 | 95.2k | } |
2280 | | |
2281 | 2.63M | let dcval = if !left && !above { |
2282 | 3.08k | 128 |
2283 | | } else { |
2284 | 2.63M | (sum + (1 << (shf - 1))) >> shf |
2285 | | }; |
2286 | | |
2287 | 24.3M | for y in 0usize..size { |
2288 | 24.3M | a[1 + stride * (y + 1)..][..size] |
2289 | 24.3M | .iter_mut() |
2290 | 247M | .for_each(|a| *a = dcval as u8); |
2291 | | } |
2292 | 2.63M | } |
2293 | | |
2294 | | // Clippy suggests the clamp method, but it seems to optimize worse as of rustc 1.82.0 nightly. |
2295 | | #[allow(clippy::manual_clamp)] |
2296 | 3.29M | fn predict_tmpred(a: &mut [u8], size: usize, x0: usize, y0: usize, stride: usize) { |
2297 | | // The formula for tmpred is: |
2298 | | // X_ij = L_i + A_j - P (i, j=0, 1, 2, 3) |
2299 | | // |
2300 | | // |-----|-----|-----|-----|-----| |
2301 | | // | P | A0 | A1 | A2 | A3 | |
2302 | | // |-----|-----|-----|-----|-----| |
2303 | | // | L0 | X00 | X01 | X02 | X03 | |
2304 | | // |-----|-----|-----|-----|-----| |
2305 | | // | L1 | X10 | X11 | X12 | X13 | |
2306 | | // |-----|-----|-----|-----|-----| |
2307 | | // | L2 | X20 | X21 | X22 | X23 | |
2308 | | // |-----|-----|-----|-----|-----| |
2309 | | // | L3 | X30 | X31 | X32 | X33 | |
2310 | | // |-----|-----|-----|-----|-----| |
2311 | | // Diagram from p. 52 of RFC 6386 |
2312 | | |
2313 | | // Split at L0 |
2314 | 3.29M | let (above, x_block) = a.split_at_mut(y0 * stride + (x0 - 1)); |
2315 | 3.29M | let p = i32::from(above[(y0 - 1) * stride + x0 - 1]); |
2316 | 3.29M | let above_slice = &above[(y0 - 1) * stride + x0..]; |
2317 | | |
2318 | 20.6M | for y in 0usize..size { |
2319 | 20.6M | let left_minus_p = i32::from(x_block[y * stride]) - p; |
2320 | | |
2321 | | // Add 1 to skip over L0 byte |
2322 | 20.6M | x_block[y * stride + 1..][..size] |
2323 | 20.6M | .iter_mut() |
2324 | 20.6M | .zip(above_slice) |
2325 | 175M | .for_each(|(cur, &abv)| *cur = (left_minus_p + i32::from(abv)).max(0).min(255) as u8); |
2326 | | } |
2327 | 3.29M | } |
2328 | | |
2329 | 10.0M | fn predict_bdcpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { |
2330 | 10.0M | let mut v = 4; |
2331 | | |
2332 | 10.0M | a[(y0 - 1) * stride + x0..][..4] |
2333 | 10.0M | .iter() |
2334 | 40.1M | .for_each(|&a| v += u32::from(a)); |
2335 | | |
2336 | 50.2M | for i in 0usize..4 { |
2337 | 40.1M | v += u32::from(a[(y0 + i) * stride + x0 - 1]); |
2338 | 40.1M | } |
2339 | | |
2340 | 10.0M | v >>= 3; |
2341 | 40.1M | for chunk in a.chunks_exact_mut(stride).skip(y0).take(4) { |
2342 | 160M | for ch in &mut chunk[x0..][..4] { |
2343 | 160M | *ch = v as u8; |
2344 | 160M | } |
2345 | | } |
2346 | 10.0M | } |
2347 | | |
2348 | 1.58M | fn topleft_pixel(a: &[u8], x0: usize, y0: usize, stride: usize) -> u8 { |
2349 | 1.58M | a[(y0 - 1) * stride + x0 - 1] |
2350 | 1.58M | } |
2351 | | |
2352 | 1.56M | fn top_pixels(a: &[u8], x0: usize, y0: usize, stride: usize) -> (u8, u8, u8, u8, u8, u8, u8, u8) { |
2353 | 1.56M | let pos = (y0 - 1) * stride + x0; |
2354 | 1.56M | let a_slice = &a[pos..pos + 8]; |
2355 | 1.56M | let a0 = a_slice[0]; |
2356 | 1.56M | let a1 = a_slice[1]; |
2357 | 1.56M | let a2 = a_slice[2]; |
2358 | 1.56M | let a3 = a_slice[3]; |
2359 | 1.56M | let a4 = a_slice[4]; |
2360 | 1.56M | let a5 = a_slice[5]; |
2361 | 1.56M | let a6 = a_slice[6]; |
2362 | 1.56M | let a7 = a_slice[7]; |
2363 | | |
2364 | 1.56M | (a0, a1, a2, a3, a4, a5, a6, a7) |
2365 | 1.56M | } |
2366 | | |
2367 | 1.04M | fn left_pixels(a: &[u8], x0: usize, y0: usize, stride: usize) -> (u8, u8, u8, u8) { |
2368 | 1.04M | let l0 = a[y0 * stride + x0 - 1]; |
2369 | 1.04M | let l1 = a[(y0 + 1) * stride + x0 - 1]; |
2370 | 1.04M | let l2 = a[(y0 + 2) * stride + x0 - 1]; |
2371 | 1.04M | let l3 = a[(y0 + 3) * stride + x0 - 1]; |
2372 | | |
2373 | 1.04M | (l0, l1, l2, l3) |
2374 | 1.04M | } |
2375 | | |
2376 | 852k | fn edge_pixels( |
2377 | 852k | a: &[u8], |
2378 | 852k | x0: usize, |
2379 | 852k | y0: usize, |
2380 | 852k | stride: usize, |
2381 | 852k | ) -> (u8, u8, u8, u8, u8, u8, u8, u8, u8) { |
2382 | 852k | let pos = (y0 - 1) * stride + x0 - 1; |
2383 | 852k | let a_slice = &a[pos..=pos + 4]; |
2384 | 852k | let e0 = a[pos + 4 * stride]; |
2385 | 852k | let e1 = a[pos + 3 * stride]; |
2386 | 852k | let e2 = a[pos + 2 * stride]; |
2387 | 852k | let e3 = a[pos + stride]; |
2388 | 852k | let e4 = a_slice[0]; |
2389 | 852k | let e5 = a_slice[1]; |
2390 | 852k | let e6 = a_slice[2]; |
2391 | 852k | let e7 = a_slice[3]; |
2392 | 852k | let e8 = a_slice[4]; |
2393 | | |
2394 | 852k | (e0, e1, e2, e3, e4, e5, e6, e7, e8) |
2395 | 852k | } |
2396 | | |
2397 | 916k | fn predict_bvepred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { |
2398 | 916k | let p = topleft_pixel(a, x0, y0, stride); |
2399 | 916k | let (a0, a1, a2, a3, a4, ..) = top_pixels(a, x0, y0, stride); |
2400 | 916k | let avg_1 = avg3(p, a0, a1); |
2401 | 916k | let avg_2 = avg3(a0, a1, a2); |
2402 | 916k | let avg_3 = avg3(a1, a2, a3); |
2403 | 916k | let avg_4 = avg3(a2, a3, a4); |
2404 | | |
2405 | 916k | let avg = [avg_1, avg_2, avg_3, avg_4]; |
2406 | | |
2407 | 916k | let mut pos = y0 * stride + x0; |
2408 | 4.58M | for _ in 0..4 { |
2409 | 3.66M | a[pos..=pos + 3].copy_from_slice(&avg); |
2410 | 3.66M | pos += stride; |
2411 | 3.66M | } |
2412 | 916k | } |
2413 | | |
2414 | 672k | fn predict_bhepred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { |
2415 | 672k | let p = topleft_pixel(a, x0, y0, stride); |
2416 | 672k | let (l0, l1, l2, l3) = left_pixels(a, x0, y0, stride); |
2417 | | |
2418 | 672k | let avgs = [ |
2419 | 672k | avg3(p, l0, l1), |
2420 | 672k | avg3(l0, l1, l2), |
2421 | 672k | avg3(l1, l2, l3), |
2422 | 672k | avg3(l2, l3, l3), |
2423 | 672k | ]; |
2424 | | |
2425 | 672k | let mut pos = y0 * stride + x0; |
2426 | 3.36M | for avg in avgs { |
2427 | 10.7M | for a_p in &mut a[pos..=pos + 3] { |
2428 | 10.7M | *a_p = avg; |
2429 | 10.7M | } |
2430 | 2.68M | pos += stride; |
2431 | | } |
2432 | 672k | } |
2433 | | |
2434 | 275k | fn predict_bldpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { |
2435 | 275k | let (a0, a1, a2, a3, a4, a5, a6, a7) = top_pixels(a, x0, y0, stride); |
2436 | | |
2437 | 275k | let avgs = [ |
2438 | 275k | avg3(a0, a1, a2), |
2439 | 275k | avg3(a1, a2, a3), |
2440 | 275k | avg3(a2, a3, a4), |
2441 | 275k | avg3(a3, a4, a5), |
2442 | 275k | avg3(a4, a5, a6), |
2443 | 275k | avg3(a5, a6, a7), |
2444 | 275k | avg3(a6, a7, a7), |
2445 | 275k | ]; |
2446 | | |
2447 | 275k | let mut pos = y0 * stride + x0; |
2448 | | |
2449 | 1.37M | for i in 0..4 { |
2450 | 1.10M | a[pos..=pos + 3].copy_from_slice(&avgs[i..=i + 3]); |
2451 | 1.10M | pos += stride; |
2452 | 1.10M | } |
2453 | 275k | } |
2454 | | |
2455 | 234k | fn predict_brdpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { |
2456 | 234k | let (e0, e1, e2, e3, e4, e5, e6, e7, e8) = edge_pixels(a, x0, y0, stride); |
2457 | | |
2458 | 234k | let avgs = [ |
2459 | 234k | avg3(e0, e1, e2), |
2460 | 234k | avg3(e1, e2, e3), |
2461 | 234k | avg3(e2, e3, e4), |
2462 | 234k | avg3(e3, e4, e5), |
2463 | 234k | avg3(e4, e5, e6), |
2464 | 234k | avg3(e5, e6, e7), |
2465 | 234k | avg3(e6, e7, e8), |
2466 | 234k | ]; |
2467 | 234k | let mut pos = y0 * stride + x0; |
2468 | | |
2469 | 1.17M | for i in 0..4 { |
2470 | 939k | a[pos..=pos + 3].copy_from_slice(&avgs[3 - i..7 - i]); |
2471 | 939k | pos += stride; |
2472 | 939k | } |
2473 | 234k | } |
2474 | | |
2475 | 321k | fn predict_bvrpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { |
2476 | 321k | let (_, e1, e2, e3, e4, e5, e6, e7, e8) = edge_pixels(a, x0, y0, stride); |
2477 | | |
2478 | 321k | a[(y0 + 3) * stride + x0] = avg3(e1, e2, e3); |
2479 | 321k | a[(y0 + 2) * stride + x0] = avg3(e2, e3, e4); |
2480 | 321k | a[(y0 + 3) * stride + x0 + 1] = avg3(e3, e4, e5); |
2481 | 321k | a[(y0 + 1) * stride + x0] = avg3(e3, e4, e5); |
2482 | 321k | a[(y0 + 2) * stride + x0 + 1] = avg2(e4, e5); |
2483 | 321k | a[y0 * stride + x0] = avg2(e4, e5); |
2484 | 321k | a[(y0 + 3) * stride + x0 + 2] = avg3(e4, e5, e6); |
2485 | 321k | a[(y0 + 1) * stride + x0 + 1] = avg3(e4, e5, e6); |
2486 | 321k | a[(y0 + 2) * stride + x0 + 2] = avg2(e5, e6); |
2487 | 321k | a[y0 * stride + x0 + 1] = avg2(e5, e6); |
2488 | 321k | a[(y0 + 3) * stride + x0 + 3] = avg3(e5, e6, e7); |
2489 | 321k | a[(y0 + 1) * stride + x0 + 2] = avg3(e5, e6, e7); |
2490 | 321k | a[(y0 + 2) * stride + x0 + 3] = avg2(e6, e7); |
2491 | 321k | a[y0 * stride + x0 + 2] = avg2(e6, e7); |
2492 | 321k | a[(y0 + 1) * stride + x0 + 3] = avg3(e6, e7, e8); |
2493 | 321k | a[y0 * stride + x0 + 3] = avg2(e7, e8); |
2494 | 321k | } |
2495 | | |
2496 | 370k | fn predict_bvlpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { |
2497 | 370k | let (a0, a1, a2, a3, a4, a5, a6, a7) = top_pixels(a, x0, y0, stride); |
2498 | | |
2499 | 370k | a[y0 * stride + x0] = avg2(a0, a1); |
2500 | 370k | a[(y0 + 1) * stride + x0] = avg3(a0, a1, a2); |
2501 | 370k | a[(y0 + 2) * stride + x0] = avg2(a1, a2); |
2502 | 370k | a[y0 * stride + x0 + 1] = avg2(a1, a2); |
2503 | 370k | a[(y0 + 1) * stride + x0 + 1] = avg3(a1, a2, a3); |
2504 | 370k | a[(y0 + 3) * stride + x0] = avg3(a1, a2, a3); |
2505 | 370k | a[(y0 + 2) * stride + x0 + 1] = avg2(a2, a3); |
2506 | 370k | a[y0 * stride + x0 + 2] = avg2(a2, a3); |
2507 | 370k | a[(y0 + 3) * stride + x0 + 1] = avg3(a2, a3, a4); |
2508 | 370k | a[(y0 + 1) * stride + x0 + 2] = avg3(a2, a3, a4); |
2509 | 370k | a[(y0 + 2) * stride + x0 + 2] = avg2(a3, a4); |
2510 | 370k | a[y0 * stride + x0 + 3] = avg2(a3, a4); |
2511 | 370k | a[(y0 + 3) * stride + x0 + 2] = avg3(a3, a4, a5); |
2512 | 370k | a[(y0 + 1) * stride + x0 + 3] = avg3(a3, a4, a5); |
2513 | 370k | a[(y0 + 2) * stride + x0 + 3] = avg3(a4, a5, a6); |
2514 | 370k | a[(y0 + 3) * stride + x0 + 3] = avg3(a5, a6, a7); |
2515 | 370k | } |
2516 | | |
2517 | 295k | fn predict_bhdpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { |
2518 | 295k | let (e0, e1, e2, e3, e4, e5, e6, e7, _) = edge_pixels(a, x0, y0, stride); |
2519 | | |
2520 | 295k | a[(y0 + 3) * stride + x0] = avg2(e0, e1); |
2521 | 295k | a[(y0 + 3) * stride + x0 + 1] = avg3(e0, e1, e2); |
2522 | 295k | a[(y0 + 2) * stride + x0] = avg2(e1, e2); |
2523 | 295k | a[(y0 + 3) * stride + x0 + 2] = avg2(e1, e2); |
2524 | 295k | a[(y0 + 2) * stride + x0 + 1] = avg3(e1, e2, e3); |
2525 | 295k | a[(y0 + 3) * stride + x0 + 3] = avg3(e1, e2, e3); |
2526 | 295k | a[(y0 + 2) * stride + x0 + 2] = avg2(e2, e3); |
2527 | 295k | a[(y0 + 1) * stride + x0] = avg2(e2, e3); |
2528 | 295k | a[(y0 + 2) * stride + x0 + 3] = avg3(e2, e3, e4); |
2529 | 295k | a[(y0 + 1) * stride + x0 + 1] = avg3(e2, e3, e4); |
2530 | 295k | a[(y0 + 1) * stride + x0 + 2] = avg2(e3, e4); |
2531 | 295k | a[y0 * stride + x0] = avg2(e3, e4); |
2532 | 295k | a[(y0 + 1) * stride + x0 + 3] = avg3(e3, e4, e5); |
2533 | 295k | a[y0 * stride + x0 + 1] = avg3(e3, e4, e5); |
2534 | 295k | a[y0 * stride + x0 + 2] = avg3(e4, e5, e6); |
2535 | 295k | a[y0 * stride + x0 + 3] = avg3(e5, e6, e7); |
2536 | 295k | } |
2537 | | |
2538 | 377k | fn predict_bhupred(a: &mut [u8], x0: usize, y0: usize, stride: usize) { |
2539 | 377k | let (l0, l1, l2, l3) = left_pixels(a, x0, y0, stride); |
2540 | | |
2541 | 377k | a[y0 * stride + x0] = avg2(l0, l1); |
2542 | 377k | a[y0 * stride + x0 + 1] = avg3(l0, l1, l2); |
2543 | 377k | a[y0 * stride + x0 + 2] = avg2(l1, l2); |
2544 | 377k | a[(y0 + 1) * stride + x0] = avg2(l1, l2); |
2545 | 377k | a[y0 * stride + x0 + 3] = avg3(l1, l2, l3); |
2546 | 377k | a[(y0 + 1) * stride + x0 + 1] = avg3(l1, l2, l3); |
2547 | 377k | a[(y0 + 1) * stride + x0 + 2] = avg2(l2, l3); |
2548 | 377k | a[(y0 + 2) * stride + x0] = avg2(l2, l3); |
2549 | 377k | a[(y0 + 1) * stride + x0 + 3] = avg3(l2, l3, l3); |
2550 | 377k | a[(y0 + 2) * stride + x0 + 1] = avg3(l2, l3, l3); |
2551 | 377k | a[(y0 + 2) * stride + x0 + 2] = l3; |
2552 | 377k | a[(y0 + 2) * stride + x0 + 3] = l3; |
2553 | 377k | a[(y0 + 3) * stride + x0] = l3; |
2554 | 377k | a[(y0 + 3) * stride + x0 + 1] = l3; |
2555 | 377k | a[(y0 + 3) * stride + x0 + 2] = l3; |
2556 | 377k | a[(y0 + 3) * stride + x0 + 3] = l3; |
2557 | 377k | } |
2558 | | |
2559 | | #[cfg(all(test, feature = "_benchmarks"))] |
2560 | | mod benches { |
2561 | | use super::*; |
2562 | | use test::{black_box, Bencher}; |
2563 | | |
2564 | | const W: usize = 256; |
2565 | | const H: usize = 256; |
2566 | | |
2567 | | fn make_sample_image() -> Vec<u8> { |
2568 | | let mut v = Vec::with_capacity((W * H * 4) as usize); |
2569 | | for c in 0u8..=255 { |
2570 | | for k in 0u8..=255 { |
2571 | | v.push(c); |
2572 | | v.push(0); |
2573 | | v.push(0); |
2574 | | v.push(k); |
2575 | | } |
2576 | | } |
2577 | | v |
2578 | | } |
2579 | | |
2580 | | #[bench] |
2581 | | fn bench_predict_4x4(b: &mut Bencher) { |
2582 | | let mut v = black_box(make_sample_image()); |
2583 | | |
2584 | | let res_data = vec![1i32; W * H * 4]; |
2585 | | let modes = [ |
2586 | | IntraMode::TM, |
2587 | | IntraMode::VE, |
2588 | | IntraMode::HE, |
2589 | | IntraMode::DC, |
2590 | | IntraMode::LD, |
2591 | | IntraMode::RD, |
2592 | | IntraMode::VR, |
2593 | | IntraMode::VL, |
2594 | | IntraMode::HD, |
2595 | | IntraMode::HU, |
2596 | | IntraMode::TM, |
2597 | | IntraMode::VE, |
2598 | | IntraMode::HE, |
2599 | | IntraMode::DC, |
2600 | | IntraMode::LD, |
2601 | | IntraMode::RD, |
2602 | | ]; |
2603 | | |
2604 | | b.iter(|| { |
2605 | | black_box(predict_4x4(&mut v, W * 2, &modes, &res_data)); |
2606 | | }); |
2607 | | } |
2608 | | |
2609 | | #[bench] |
2610 | | fn bench_predict_bvepred(b: &mut Bencher) { |
2611 | | let mut v = make_sample_image(); |
2612 | | |
2613 | | b.iter(|| { |
2614 | | predict_bvepred(black_box(&mut v), 5, 5, W * 2); |
2615 | | }); |
2616 | | } |
2617 | | |
2618 | | #[bench] |
2619 | | fn bench_predict_bldpred(b: &mut Bencher) { |
2620 | | let mut v = black_box(make_sample_image()); |
2621 | | |
2622 | | b.iter(|| { |
2623 | | black_box(predict_bldpred(black_box(&mut v), 5, 5, W * 2)); |
2624 | | }); |
2625 | | } |
2626 | | |
2627 | | #[bench] |
2628 | | fn bench_predict_brdpred(b: &mut Bencher) { |
2629 | | let mut v = black_box(make_sample_image()); |
2630 | | |
2631 | | b.iter(|| { |
2632 | | black_box(predict_brdpred(black_box(&mut v), 5, 5, W * 2)); |
2633 | | }); |
2634 | | } |
2635 | | |
2636 | | #[bench] |
2637 | | fn bench_predict_bhepred(b: &mut Bencher) { |
2638 | | let mut v = black_box(make_sample_image()); |
2639 | | |
2640 | | b.iter(|| { |
2641 | | black_box(predict_bhepred(black_box(&mut v), 5, 5, W * 2)); |
2642 | | }); |
2643 | | } |
2644 | | |
2645 | | #[bench] |
2646 | | fn bench_top_pixels(b: &mut Bencher) { |
2647 | | let v = black_box(make_sample_image()); |
2648 | | |
2649 | | b.iter(|| { |
2650 | | black_box(top_pixels(black_box(&v), 5, 5, W * 2)); |
2651 | | }); |
2652 | | } |
2653 | | |
2654 | | #[bench] |
2655 | | fn bench_edge_pixels(b: &mut Bencher) { |
2656 | | let v = black_box(make_sample_image()); |
2657 | | |
2658 | | b.iter(|| { |
2659 | | black_box(edge_pixels(black_box(&v), 5, 5, W * 2)); |
2660 | | }); |
2661 | | } |
2662 | | } |
2663 | | |
2664 | | #[cfg(test)] |
2665 | | mod tests { |
2666 | | use super::*; |
2667 | | |
2668 | | #[test] |
2669 | | fn test_avg2() { |
2670 | | for i in 0u8..=255 { |
2671 | | for j in 0u8..=255 { |
2672 | | let ceil_avg = (f32::from(i) + f32::from(j)) / 2.0; |
2673 | | let ceil_avg = ceil_avg.ceil() as u8; |
2674 | | assert_eq!( |
2675 | | ceil_avg, |
2676 | | avg2(i, j), |
2677 | | "avg2({}, {}), expected {}, got {}.", |
2678 | | i, |
2679 | | j, |
2680 | | ceil_avg, |
2681 | | avg2(i, j) |
2682 | | ); |
2683 | | } |
2684 | | } |
2685 | | } |
2686 | | |
2687 | | #[test] |
2688 | | fn test_avg2_specific() { |
2689 | | assert_eq!( |
2690 | | 255, |
2691 | | avg2(255, 255), |
2692 | | "avg2(255, 255), expected 255, got {}.", |
2693 | | avg2(255, 255) |
2694 | | ); |
2695 | | assert_eq!(1, avg2(1, 1), "avg2(1, 1), expected 1, got {}.", avg2(1, 1)); |
2696 | | assert_eq!(2, avg2(2, 1), "avg2(2, 1), expected 2, got {}.", avg2(2, 1)); |
2697 | | } |
2698 | | |
2699 | | #[test] |
2700 | | fn test_avg3() { |
2701 | | for i in 0u8..=255 { |
2702 | | for j in 0u8..=255 { |
2703 | | for k in 0u8..=255 { |
2704 | | let floor_avg = |
2705 | | (2.0f32.mul_add(f32::from(j), f32::from(i)) + { f32::from(k) } + 2.0) / 4.0; |
2706 | | let floor_avg = floor_avg.floor() as u8; |
2707 | | assert_eq!( |
2708 | | floor_avg, |
2709 | | avg3(i, j, k), |
2710 | | "avg3({}, {}, {}), expected {}, got {}.", |
2711 | | i, |
2712 | | j, |
2713 | | k, |
2714 | | floor_avg, |
2715 | | avg3(i, j, k) |
2716 | | ); |
2717 | | } |
2718 | | } |
2719 | | } |
2720 | | } |
2721 | | |
2722 | | #[test] |
2723 | | fn test_edge_pixels() { |
2724 | | #[rustfmt::skip] |
2725 | | let im = vec![5, 6, 7, 8, 9, |
2726 | | 4, 0, 0, 0, 0, |
2727 | | 3, 0, 0, 0, 0, |
2728 | | 2, 0, 0, 0, 0, |
2729 | | 1, 0, 0, 0, 0]; |
2730 | | let (e0, e1, e2, e3, e4, e5, e6, e7, e8) = edge_pixels(&im, 1, 1, 5); |
2731 | | assert_eq!(e0, 1); |
2732 | | assert_eq!(e1, 2); |
2733 | | assert_eq!(e2, 3); |
2734 | | assert_eq!(e3, 4); |
2735 | | assert_eq!(e4, 5); |
2736 | | assert_eq!(e5, 6); |
2737 | | assert_eq!(e6, 7); |
2738 | | assert_eq!(e7, 8); |
2739 | | assert_eq!(e8, 9); |
2740 | | } |
2741 | | |
2742 | | #[test] |
2743 | | fn test_top_pixels() { |
2744 | | #[rustfmt::skip] |
2745 | | let im = vec![1, 2, 3, 4, 5, 6, 7, 8, |
2746 | | 0, 0, 0, 0, 0, 0, 0, 0, |
2747 | | 0, 0, 0, 0, 0, 0, 0, 0, |
2748 | | 0, 0, 0, 0, 0, 0, 0, 0, |
2749 | | 0, 0, 0, 0, 0, 0, 0, 0, |
2750 | | 0, 0, 0, 0, 0, 0, 0, 0, |
2751 | | 0, 0, 0, 0, 0, 0, 0, 0, |
2752 | | 0, 0, 0, 0, 0, 0, 0, 0]; |
2753 | | let (e0, e1, e2, e3, e4, e5, e6, e7) = top_pixels(&im, 0, 1, 8); |
2754 | | assert_eq!(e0, 1); |
2755 | | assert_eq!(e1, 2); |
2756 | | assert_eq!(e2, 3); |
2757 | | assert_eq!(e3, 4); |
2758 | | assert_eq!(e4, 5); |
2759 | | assert_eq!(e5, 6); |
2760 | | assert_eq!(e6, 7); |
2761 | | assert_eq!(e7, 8); |
2762 | | } |
2763 | | |
2764 | | #[test] |
2765 | | fn test_add_residue() { |
2766 | | let mut pblock = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; |
2767 | | let rblock = [ |
2768 | | -1, -2, -3, -4, 250, 249, 248, 250, -10, -18, -192, -17, -3, 15, 18, 9, |
2769 | | ]; |
2770 | | let expected: [u8; 16] = [0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 10, 29, 33, 25]; |
2771 | | |
2772 | | add_residue(&mut pblock, &rblock, 0, 0, 4); |
2773 | | |
2774 | | for (&e, &i) in expected.iter().zip(&pblock) { |
2775 | | assert_eq!(e, i); |
2776 | | } |
2777 | | } |
2778 | | |
2779 | | #[test] |
2780 | | fn test_predict_bhepred() { |
2781 | | #[rustfmt::skip] |
2782 | | let expected: Vec<u8> = vec![5, 0, 0, 0, 0, |
2783 | | 4, 4, 4, 4, 4, |
2784 | | 3, 3, 3, 3, 3, |
2785 | | 2, 2, 2, 2, 2, |
2786 | | 1, 1, 1, 1, 1]; |
2787 | | |
2788 | | #[rustfmt::skip] |
2789 | | let mut im = vec![5, 0, 0, 0, 0, |
2790 | | 4, 0, 0, 0, 0, |
2791 | | 3, 0, 0, 0, 0, |
2792 | | 2, 0, 0, 0, 0, |
2793 | | 1, 0, 0, 0, 0]; |
2794 | | predict_bhepred(&mut im, 1, 1, 5); |
2795 | | for (&e, i) in expected.iter().zip(im) { |
2796 | | assert_eq!(e, i); |
2797 | | } |
2798 | | } |
2799 | | |
2800 | | #[test] |
2801 | | fn test_predict_brdpred() { |
2802 | | #[rustfmt::skip] |
2803 | | let expected: Vec<u8> = vec![5, 6, 7, 8, 9, |
2804 | | 4, 5, 6, 7, 8, |
2805 | | 3, 4, 5, 6, 7, |
2806 | | 2, 3, 4, 5, 6, |
2807 | | 1, 2, 3, 4, 5]; |
2808 | | |
2809 | | #[rustfmt::skip] |
2810 | | let mut im = vec![5, 6, 7, 8, 9, |
2811 | | 4, 0, 0, 0, 0, |
2812 | | 3, 0, 0, 0, 0, |
2813 | | 2, 0, 0, 0, 0, |
2814 | | 1, 0, 0, 0, 0]; |
2815 | | predict_brdpred(&mut im, 1, 1, 5); |
2816 | | for (&e, i) in expected.iter().zip(im) { |
2817 | | assert_eq!(e, i); |
2818 | | } |
2819 | | } |
2820 | | |
2821 | | #[test] |
2822 | | fn test_predict_bldpred() { |
2823 | | #[rustfmt::skip] |
2824 | | let mut im: Vec<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8, |
2825 | | 0, 0, 0, 0, 0, 0, 0, 0, |
2826 | | 0, 0, 0, 0, 0, 0, 0, 0, |
2827 | | 0, 0, 0, 0, 0, 0, 0, 0, |
2828 | | 0, 0, 0, 0, 0, 0, 0, 0, |
2829 | | 0, 0, 0, 0, 0, 0, 0, 0, |
2830 | | 0, 0, 0, 0, 0, 0, 0, 0, |
2831 | | 0, 0, 0, 0, 0, 0, 0, 0, |
2832 | | 0, 0, 0, 0, 0, 0, 0, 0]; |
2833 | | let avg_1 = 2u8; |
2834 | | let avg_2 = 3u8; |
2835 | | let avg_3 = 4u8; |
2836 | | let avg_4 = 5u8; |
2837 | | let avg_5 = 6u8; |
2838 | | let avg_6 = 7u8; |
2839 | | let avg_7 = 8u8; |
2840 | | |
2841 | | predict_bldpred(&mut im, 0, 1, 8); |
2842 | | |
2843 | | assert_eq!(im[8], avg_1); |
2844 | | assert_eq!(im[9], avg_2); |
2845 | | assert_eq!(im[10], avg_3); |
2846 | | assert_eq!(im[11], avg_4); |
2847 | | assert_eq!(im[16], avg_2); |
2848 | | assert_eq!(im[17], avg_3); |
2849 | | assert_eq!(im[18], avg_4); |
2850 | | assert_eq!(im[19], avg_5); |
2851 | | assert_eq!(im[24], avg_3); |
2852 | | assert_eq!(im[25], avg_4); |
2853 | | assert_eq!(im[26], avg_5); |
2854 | | assert_eq!(im[27], avg_6); |
2855 | | assert_eq!(im[32], avg_4); |
2856 | | assert_eq!(im[33], avg_5); |
2857 | | assert_eq!(im[34], avg_6); |
2858 | | assert_eq!(im[35], avg_7); |
2859 | | } |
2860 | | |
2861 | | #[test] |
2862 | | fn test_predict_bvepred() { |
2863 | | #[rustfmt::skip] |
2864 | | let mut im: Vec<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, |
2865 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, |
2866 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, |
2867 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, |
2868 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, |
2869 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, |
2870 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, |
2871 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, |
2872 | | 0, 0, 0, 0, 0, 0, 0, 0, 0]; |
2873 | | let avg_1 = 2u8; |
2874 | | let avg_2 = 3u8; |
2875 | | let avg_3 = 4u8; |
2876 | | let avg_4 = 5u8; |
2877 | | |
2878 | | predict_bvepred(&mut im, 1, 1, 9); |
2879 | | |
2880 | | assert_eq!(im[10], avg_1); |
2881 | | assert_eq!(im[11], avg_2); |
2882 | | assert_eq!(im[12], avg_3); |
2883 | | assert_eq!(im[13], avg_4); |
2884 | | assert_eq!(im[19], avg_1); |
2885 | | assert_eq!(im[20], avg_2); |
2886 | | assert_eq!(im[21], avg_3); |
2887 | | assert_eq!(im[22], avg_4); |
2888 | | assert_eq!(im[28], avg_1); |
2889 | | assert_eq!(im[29], avg_2); |
2890 | | assert_eq!(im[30], avg_3); |
2891 | | assert_eq!(im[31], avg_4); |
2892 | | assert_eq!(im[37], avg_1); |
2893 | | assert_eq!(im[38], avg_2); |
2894 | | assert_eq!(im[39], avg_3); |
2895 | | assert_eq!(im[40], avg_4); |
2896 | | } |
2897 | | } |