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
13use byteorder_lite::{LittleEndian, ReadBytesExt};
14use std::cmp;
15use std::default::Default;
16use std::io::Read;
17
18use crate::decoder::DecodingError;
19
20use super::vp8_arithmetic_decoder::ArithmeticDecoder;
21use super::{loop_filter, transform};
22
23const MAX_SEGMENTS: usize = 4;
24const NUM_DCT_TOKENS: usize = 12;
25
26// Prediction modes
27const DC_PRED: i8 = 0;
28const V_PRED: i8 = 1;
29const H_PRED: i8 = 2;
30const TM_PRED: i8 = 3;
31const B_PRED: i8 = 4;
32
33const B_DC_PRED: i8 = 0;
34const B_TM_PRED: i8 = 1;
35const B_VE_PRED: i8 = 2;
36const B_HE_PRED: i8 = 3;
37const B_LD_PRED: i8 = 4;
38const B_RD_PRED: i8 = 5;
39const B_VR_PRED: i8 = 6;
40const B_VL_PRED: i8 = 7;
41const B_HD_PRED: i8 = 8;
42const B_HU_PRED: i8 = 9;
43
44// Prediction mode enum
45#[repr(i8)]
46#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
47enum 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)]
67enum 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)]
84enum 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
98type Prob = u8;
99
100#[derive(Clone, Copy)]
101pub(crate) struct TreeNode {
102 pub left: u8,
103 pub right: u8,
104 pub prob: Prob,
105 pub index: u8,
106}
107
108impl TreeNode {
109 const UNINIT: TreeNode = TreeNode {
110 left: 0,
111 right: 0,
112 prob: 0,
113 index: 0,
114 };
115
116 const fn prepare_branch(t: i8) -> u8 {
117 if t > 0 {
118 (t as u8) / 2
119 } else {
120 let value: i8 = -t;
121 0x80 | (value as u8)
122 }
123 }
124
125 pub(crate) const fn value_from_branch(t: u8) -> i8 {
126 (t & !0x80) as i8
127 }
128}
129
130const fn tree_nodes_from<const N: usize, const M: usize>(
131 tree: [i8; N],
132 probs: [Prob; M],
133) -> [TreeNode; M] {
134 if N != 2 * M {
135 panic!("invalid tree with probs");
136 }
137 let mut nodes: [TreeNode; M] = [TreeNode::UNINIT; M];
138 let mut i: usize = 0;
139 while i < M {
140 nodes[i].left = TreeNode::prepare_branch(tree[2 * i]);
141 nodes[i].right = TreeNode::prepare_branch(tree[2 * i + 1]);
142 nodes[i].prob = probs[i];
143 nodes[i].index = i as u8;
144 i += 1;
145 }
146 nodes
147}
148
149const SEGMENT_ID_TREE: [i8; 6] = [2, 4, -0, -1, -2, -3];
150
151const 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:
155const 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
158const KEYFRAME_YMODE_PROBS: [Prob; 4] = [145, 156, 163, 128];
159
160const 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:
164const 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
170const 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
293const KEYFRAME_BPRED_MODE_NODES: [[[TreeNode; 9]; 10]; 10] = {
294 let mut output: [[[TreeNode; 9]; 10]; 10] = [[[TreeNode::UNINIT; 9]; 10]; 10];
295 let mut i: usize = 0;
296 while i < output.len() {
297 let mut j: usize = 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
309const KEYFRAME_UV_MODE_TREE: [i8; 6] = [-DC_PRED, 2, -V_PRED, 4, -H_PRED, -TM_PRED];
310
311// Probabilities for determining macroblock mode
312const KEYFRAME_UV_MODE_PROBS: [Prob; 3] = [142, 114, 183];
313
314const KEYFRAME_UV_MODE_NODES: [TreeNode; 3] =
315 tree_nodes_from(KEYFRAME_UV_MODE_TREE, KEYFRAME_UV_MODE_PROBS);
316
317// Section 13.4
318type TokenProbTables = [[[[Prob; NUM_DCT_TOKENS - 1]; 3]; 8]; 4];
319type TokenProbTreeNodes = [[[[TreeNode; NUM_DCT_TOKENS - 1]; 3]; 8]; 4];
320
321// Probabilities that a token's probability will be updated
322const 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
495const 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
666const COEFF_PROB_NODES: TokenProbTreeNodes = {
667 let mut output: [[[[TreeNode; 11]; 3]; 8]; 4] = [[[[TreeNode::UNINIT; 11]; 3]; 8]; 4];
668 let mut i: usize = 0;
669 while i < output.len() {
670 let mut j: usize = 0;
671 while j < output[i].len() {
672 let mut k: usize = 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
685const DCT_0: i8 = 0;
686const DCT_1: i8 = 1;
687const DCT_2: i8 = 2;
688const DCT_3: i8 = 3;
689const DCT_4: i8 = 4;
690const DCT_CAT1: i8 = 5;
691const DCT_CAT2: i8 = 6;
692const DCT_CAT3: i8 = 7;
693const DCT_CAT4: i8 = 8;
694const DCT_CAT5: i8 = 9;
695const DCT_CAT6: i8 = 10;
696const DCT_EOB: i8 = 11;
697
698const 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
703const 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
712const DCT_CAT_BASE: [u8; 6] = [5, 7, 11, 19, 35, 67];
713const COEFF_BANDS: [u8; 16] = [0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7];
714
715#[rustfmt::skip]
716const 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]
736const 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
755const 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)]
758struct 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}
766
767/// A Representation of the last decoded video frame
768#[derive(Default, Debug, Clone)]
769pub struct Frame {
770 /// The width of the luma plane
771 pub width: u16,
772
773 /// The height of the luma plane
774 pub height: u16,
775
776 /// The luma plane of the frame
777 pub ybuf: Vec<u8>,
778
779 /// The blue plane of the frame
780 pub ubuf: Vec<u8>,
781
782 /// The red plane of the frame
783 pub vbuf: Vec<u8>,
784
785 /// Indicates whether this frame is a keyframe
786 pub keyframe: bool,
787
788 version: u8,
789
790 /// Indicates whether this frame is intended for display
791 pub for_display: bool,
792
793 // Section 9.2
794 /// The pixel type of the frame as defined by Section 9.2
795 /// of the VP8 Specification
796 pub pixel_type: u8,
797
798 // Section 9.4 and 15
799 filter_type: bool, //if true uses simple filter // if false uses normal filter
800 filter_level: u8,
801 sharpness_level: u8,
802}
803
804impl Frame {
805 /// Chroma plane is half the size of the Luma plane
806 const fn chroma_width(&self) -> u16 {
807 (self.width + 1) / 2
808 }
809
810 const fn chroma_height(&self) -> u16 {
811 (self.height + 1) / 2
812 }
813
814 /// Fills an rgb buffer with the image
815 pub(crate) fn fill_rgb(&self, buf: &mut [u8]) {
816 const BPP: usize = 3;
817
818 let mut index = 0_usize;
819
820 for (y, row) in buf
821 .chunks_exact_mut(usize::from(self.width) * BPP)
822 .enumerate()
823 {
824 let chroma_index = usize::from(self.chroma_width()) * (y / 2);
825
826 let next_index = index + usize::from(self.width);
827 Self::fill_rgb_row(
828 &self.ybuf[index..next_index],
829 &self.ubuf[chroma_index..],
830 &self.vbuf[chroma_index..],
831 row,
832 );
833
834 index = next_index;
835 }
836 }
837
838 fn fill_rgb_row(y_vec: &[u8], u_vec: &[u8], v_vec: &[u8], rgb: &mut [u8]) {
839 // Fill 2 pixels per iteration: these pixels share `u` and `v` components
840 let mut rgb_chunks = rgb.chunks_exact_mut(6);
841 let mut y_chunks = y_vec.chunks_exact(2);
842 let mut u_iter = u_vec.iter();
843 let mut v_iter = v_vec.iter();
844
845 for (((rgb, y), &u), &v) in (&mut rgb_chunks)
846 .zip(&mut y_chunks)
847 .zip(&mut u_iter)
848 .zip(&mut v_iter)
849 {
850 let coeffs = [
851 mulhi(v, 26149),
852 mulhi(u, 6419),
853 mulhi(v, 13320),
854 mulhi(u, 33050),
855 ];
856
857 rgb[0] = clip(mulhi(y[0], 19077) + coeffs[0] - 14234);
858 rgb[1] = clip(mulhi(y[0], 19077) - coeffs[1] - coeffs[2] + 8708);
859 rgb[2] = clip(mulhi(y[0], 19077) + coeffs[3] - 17685);
860
861 rgb[3] = clip(mulhi(y[1], 19077) + coeffs[0] - 14234);
862 rgb[4] = clip(mulhi(y[1], 19077) - coeffs[1] - coeffs[2] + 8708);
863 rgb[5] = clip(mulhi(y[1], 19077) + coeffs[3] - 17685);
864 }
865
866 let remainder = rgb_chunks.into_remainder();
867 if remainder.len() >= 3 {
868 if let (Some(&y), Some(&u), Some(&v)) = (
869 y_chunks.remainder().iter().next(),
870 u_iter.next(),
871 v_iter.next(),
872 ) {
873 let coeffs = [
874 mulhi(v, 26149),
875 mulhi(u, 6419),
876 mulhi(v, 13320),
877 mulhi(u, 33050),
878 ];
879
880 remainder[0] = clip(mulhi(y, 19077) + coeffs[0] - 14234);
881 remainder[1] = clip(mulhi(y, 19077) - coeffs[1] - coeffs[2] + 8708);
882 remainder[2] = clip(mulhi(y, 19077) + coeffs[3] - 17685);
883 }
884 }
885 }
886
887 /// Fills an rgba buffer by skipping the alpha values
888 pub(crate) fn fill_rgba(&self, buf: &mut [u8]) {
889 const BPP: usize = 4;
890
891 let mut index = 0_usize;
892
893 for (y, row) in buf
894 .chunks_exact_mut(usize::from(self.width) * BPP)
895 .enumerate()
896 {
897 let chroma_index = usize::from(self.chroma_width()) * (y / 2);
898
899 let next_index = index + usize::from(self.width);
900 Self::fill_rgba_row(
901 &self.ybuf[index..next_index],
902 &self.ubuf[chroma_index..],
903 &self.vbuf[chroma_index..],
904 row,
905 );
906
907 index = next_index;
908 }
909 }
910
911 fn fill_rgba_row(y_vec: &[u8], u_vec: &[u8], v_vec: &[u8], rgba: &mut [u8]) {
912 // Fill 2 pixels per iteration: these pixels share `u` and `v` components
913 let mut rgb_chunks = rgba.chunks_exact_mut(8);
914 let mut y_chunks = y_vec.chunks_exact(2);
915 let mut u_iter = u_vec.iter();
916 let mut v_iter = v_vec.iter();
917
918 for (((rgb, y), &u), &v) in (&mut rgb_chunks)
919 .zip(&mut y_chunks)
920 .zip(&mut u_iter)
921 .zip(&mut v_iter)
922 {
923 let coeffs = [
924 mulhi(v, 26149),
925 mulhi(u, 6419),
926 mulhi(v, 13320),
927 mulhi(u, 33050),
928 ];
929
930 let to_copy = [
931 clip(mulhi(y[0], 19077) + coeffs[0] - 14234),
932 clip(mulhi(y[0], 19077) - coeffs[1] - coeffs[2] + 8708),
933 clip(mulhi(y[0], 19077) + coeffs[3] - 17685),
934 rgb[3],
935 clip(mulhi(y[1], 19077) + coeffs[0] - 14234),
936 clip(mulhi(y[1], 19077) - coeffs[1] - coeffs[2] + 8708),
937 clip(mulhi(y[1], 19077) + coeffs[3] - 17685),
938 rgb[7],
939 ];
940 rgb.copy_from_slice(&to_copy);
941 }
942
943 let remainder = rgb_chunks.into_remainder();
944 if remainder.len() >= 4 {
945 if let (Some(&y), Some(&u), Some(&v)) = (
946 y_chunks.remainder().iter().next(),
947 u_iter.next(),
948 v_iter.next(),
949 ) {
950 let coeffs = [
951 mulhi(v, 26149),
952 mulhi(u, 6419),
953 mulhi(v, 13320),
954 mulhi(u, 33050),
955 ];
956
957 remainder[0] = clip(mulhi(y, 19077) + coeffs[0] - 14234);
958 remainder[1] = clip(mulhi(y, 19077) - coeffs[1] - coeffs[2] + 8708);
959 remainder[2] = clip(mulhi(y, 19077) + coeffs[3] - 17685);
960 }
961 }
962 }
963
964 /// Gets the buffer size
965 #[must_use]
966 pub fn get_buf_size(&self) -> usize {
967 self.ybuf.len() * 3
968 }
969}
970
971/// `_mm_mulhi_epu16` emulation used in `Frame::fill_rgb` and `Frame::fill_rgba`.
972fn mulhi(v: u8, coeff: u16) -> i32 {
973 ((u32::from(v) * u32::from(coeff)) >> 8) as i32
974}
975
976/// Used in `Frame::fill_rgb` and `Frame::fill_rgba`.
977/// This function has been rewritten to encourage auto-vectorization.
978///
979/// Based on [src/dsp/yuv.h](https://github.com/webmproject/libwebp/blob/8534f53960befac04c9631e6e50d21dcb42dfeaf/src/dsp/yuv.h#L79)
980/// from the libwebp source.
981/// ```text
982/// const YUV_FIX2: i32 = 6;
983/// const YUV_MASK2: i32 = (256 << YUV_FIX2) - 1;
984/// fn clip(v: i32) -> u8 {
985/// if (v & !YUV_MASK2) == 0 {
986/// (v >> YUV_FIX2) as u8
987/// } else if v < 0 {
988/// 0
989/// } else {
990/// 255
991/// }
992/// }
993/// ```
994// Clippy suggests the clamp method, but it seems to optimize worse as of rustc 1.82.0 nightly.
995#[allow(clippy::manual_clamp)]
996fn clip(v: i32) -> u8 {
997 const YUV_FIX2: i32 = 6;
998 (v >> YUV_FIX2).max(0).min(255) as u8
999}
1000
1001#[derive(Clone, Copy, Default)]
1002struct Segment {
1003 ydc: i16,
1004 yac: i16,
1005
1006 y2dc: i16,
1007 y2ac: i16,
1008
1009 uvdc: i16,
1010 uvac: i16,
1011
1012 delta_values: bool,
1013
1014 quantizer_level: i8,
1015 loopfilter_level: i8,
1016}
1017
1018/// VP8 Decoder
1019///
1020/// Only decodes keyframes
1021pub struct Vp8Decoder<R> {
1022 r: R,
1023 b: ArithmeticDecoder,
1024
1025 mbwidth: u16,
1026 mbheight: u16,
1027 macroblocks: Vec<MacroBlock>,
1028
1029 frame: Frame,
1030
1031 segments_enabled: bool,
1032 segments_update_map: bool,
1033 segment: [Segment; MAX_SEGMENTS],
1034
1035 ref_delta: [i32; 4],
1036 mode_delta: [i32; 4],
1037
1038 partitions: [ArithmeticDecoder; 8],
1039 num_partitions: u8,
1040
1041 segment_tree_nodes: [TreeNode; 3],
1042 token_probs: Box<TokenProbTreeNodes>,
1043
1044 // Section 9.10
1045 prob_intra: Prob,
1046
1047 // Section 9.11
1048 prob_skip_false: Option<Prob>,
1049
1050 top: Vec<MacroBlock>,
1051 left: MacroBlock,
1052
1053 top_border: Vec<u8>,
1054 left_border: Vec<u8>,
1055}
1056
1057impl<R: Read> Vp8Decoder<R> {
1058 /// Create a new decoder.
1059 /// The reader must present a raw vp8 bitstream to the decoder
1060 fn new(r: R) -> Self {
1061 let f = Frame::default();
1062 let s = Segment::default();
1063 let m = MacroBlock::default();
1064
1065 Self {
1066 r,
1067 b: ArithmeticDecoder::new(),
1068
1069 mbwidth: 0,
1070 mbheight: 0,
1071 macroblocks: Vec::new(),
1072
1073 frame: f,
1074 segments_enabled: false,
1075 segments_update_map: false,
1076 segment: [s; MAX_SEGMENTS],
1077
1078 ref_delta: [0; 4],
1079 mode_delta: [0; 4],
1080
1081 partitions: [
1082 ArithmeticDecoder::new(),
1083 ArithmeticDecoder::new(),
1084 ArithmeticDecoder::new(),
1085 ArithmeticDecoder::new(),
1086 ArithmeticDecoder::new(),
1087 ArithmeticDecoder::new(),
1088 ArithmeticDecoder::new(),
1089 ArithmeticDecoder::new(),
1090 ],
1091
1092 num_partitions: 1,
1093
1094 segment_tree_nodes: SEGMENT_TREE_NODE_DEFAULTS,
1095 token_probs: Box::new(COEFF_PROB_NODES),
1096
1097 // Section 9.10
1098 prob_intra: 0u8,
1099
1100 // Section 9.11
1101 prob_skip_false: None,
1102
1103 top: Vec::new(),
1104 left: m,
1105
1106 top_border: Vec::new(),
1107 left_border: Vec::new(),
1108 }
1109 }
1110
1111 fn update_token_probabilities(&mut self) -> Result<(), DecodingError> {
1112 let mut res = self.b.start_accumulated_result();
1113 for (i, is) in COEFF_UPDATE_PROBS.iter().enumerate() {
1114 for (j, js) in is.iter().enumerate() {
1115 for (k, ks) in js.iter().enumerate() {
1116 for (t, prob) in ks.iter().enumerate().take(NUM_DCT_TOKENS - 1) {
1117 if self.b.read_bool(*prob).or_accumulate(&mut res) {
1118 let v = self.b.read_literal(8).or_accumulate(&mut res);
1119 self.token_probs[i][j][k][t].prob = v;
1120 }
1121 }
1122 }
1123 }
1124 }
1125 self.b.check(res, ())
1126 }
1127
1128 fn init_partitions(&mut self, n: usize) -> Result<(), DecodingError> {
1129 if n > 1 {
1130 let mut sizes = vec![0; 3 * n - 3];
1131 self.r.read_exact(sizes.as_mut_slice())?;
1132
1133 for (i, s) in sizes.chunks(3).enumerate() {
1134 let size = { s }
1135 .read_u24::<LittleEndian>()
1136 .expect("Reading from &[u8] can't fail and the chunk is complete");
1137
1138 let size = size as usize;
1139 let mut buf = vec![[0; 4]; (size + 3) / 4];
1140 let bytes: &mut [u8] = buf.as_mut_slice().as_flattened_mut();
1141 self.r.read_exact(&mut bytes[..size])?;
1142 self.partitions[i].init(buf, size)?;
1143 }
1144 }
1145
1146 let mut buf = Vec::new();
1147 self.r.read_to_end(&mut buf)?;
1148 let size = buf.len();
1149 let mut chunks = vec![[0; 4]; (size + 3) / 4];
1150 chunks.as_mut_slice().as_flattened_mut()[..size].copy_from_slice(&buf);
1151 self.partitions[n - 1].init(chunks, size)?;
1152
1153 Ok(())
1154 }
1155
1156 fn read_quantization_indices(&mut self) -> Result<(), DecodingError> {
1157 fn dc_quant(index: i32) -> i16 {
1158 DC_QUANT[index.clamp(0, 127) as usize]
1159 }
1160
1161 fn ac_quant(index: i32) -> i16 {
1162 AC_QUANT[index.clamp(0, 127) as usize]
1163 }
1164
1165 let mut res = self.b.start_accumulated_result();
1166
1167 let yac_abs = self.b.read_literal(7).or_accumulate(&mut res);
1168 let ydc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1169 let y2dc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1170 let y2ac_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1171 let uvdc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1172 let uvac_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1173
1174 let n = if self.segments_enabled {
1175 MAX_SEGMENTS
1176 } else {
1177 1
1178 };
1179 for i in 0usize..n {
1180 let base = i32::from(if self.segments_enabled {
1181 if self.segment[i].delta_values {
1182 i16::from(self.segment[i].quantizer_level) + i16::from(yac_abs)
1183 } else {
1184 i16::from(self.segment[i].quantizer_level)
1185 }
1186 } else {
1187 i16::from(yac_abs)
1188 });
1189
1190 self.segment[i].ydc = dc_quant(base + ydc_delta);
1191 self.segment[i].yac = ac_quant(base);
1192
1193 self.segment[i].y2dc = dc_quant(base + y2dc_delta) * 2;
1194 // The intermediate result (max`284*155`) can be larger than the `i16` range.
1195 self.segment[i].y2ac = (i32::from(ac_quant(base + y2ac_delta)) * 155 / 100) as i16;
1196
1197 self.segment[i].uvdc = dc_quant(base + uvdc_delta);
1198 self.segment[i].uvac = ac_quant(base + uvac_delta);
1199
1200 if self.segment[i].y2ac < 8 {
1201 self.segment[i].y2ac = 8;
1202 }
1203
1204 if self.segment[i].uvdc > 132 {
1205 self.segment[i].uvdc = 132;
1206 }
1207 }
1208
1209 self.b.check(res, ())
1210 }
1211
1212 fn read_loop_filter_adjustments(&mut self) -> Result<(), DecodingError> {
1213 let mut res = self.b.start_accumulated_result();
1214
1215 if self.b.read_flag().or_accumulate(&mut res) {
1216 for i in 0usize..4 {
1217 self.ref_delta[i] = self.b.read_optional_signed_value(6).or_accumulate(&mut res);
1218 }
1219
1220 for i in 0usize..4 {
1221 self.mode_delta[i] = self.b.read_optional_signed_value(6).or_accumulate(&mut res);
1222 }
1223 }
1224
1225 self.b.check(res, ())
1226 }
1227
1228 fn read_segment_updates(&mut self) -> Result<(), DecodingError> {
1229 let mut res = self.b.start_accumulated_result();
1230
1231 // Section 9.3
1232 self.segments_update_map = self.b.read_flag().or_accumulate(&mut res);
1233 let update_segment_feature_data = self.b.read_flag().or_accumulate(&mut res);
1234
1235 if update_segment_feature_data {
1236 let segment_feature_mode = self.b.read_flag().or_accumulate(&mut res);
1237
1238 for i in 0usize..MAX_SEGMENTS {
1239 self.segment[i].delta_values = !segment_feature_mode;
1240 }
1241
1242 for i in 0usize..MAX_SEGMENTS {
1243 self.segment[i].quantizer_level =
1244 self.b.read_optional_signed_value(7).or_accumulate(&mut res) as i8;
1245 }
1246
1247 for i in 0usize..MAX_SEGMENTS {
1248 self.segment[i].loopfilter_level =
1249 self.b.read_optional_signed_value(6).or_accumulate(&mut res) as i8;
1250 }
1251 }
1252
1253 if self.segments_update_map {
1254 for i in 0usize..3 {
1255 let update = self.b.read_flag().or_accumulate(&mut res);
1256
1257 let prob = if update {
1258 self.b.read_literal(8).or_accumulate(&mut res)
1259 } else {
1260 255
1261 };
1262 self.segment_tree_nodes[i].prob = prob;
1263 }
1264 }
1265
1266 self.b.check(res, ())
1267 }
1268
1269 fn read_frame_header(&mut self) -> Result<(), DecodingError> {
1270 let tag = self.r.read_u24::<LittleEndian>()?;
1271
1272 self.frame.keyframe = tag & 1 == 0;
1273 self.frame.version = ((tag >> 1) & 7) as u8;
1274 self.frame.for_display = (tag >> 4) & 1 != 0;
1275
1276 let first_partition_size = tag >> 5;
1277
1278 if self.frame.keyframe {
1279 let mut tag = [0u8; 3];
1280 self.r.read_exact(&mut tag)?;
1281
1282 if tag != [0x9d, 0x01, 0x2a] {
1283 return Err(DecodingError::Vp8MagicInvalid(tag));
1284 }
1285
1286 let w = self.r.read_u16::<LittleEndian>()?;
1287 let h = self.r.read_u16::<LittleEndian>()?;
1288
1289 self.frame.width = w & 0x3FFF;
1290 self.frame.height = h & 0x3FFF;
1291
1292 self.top = init_top_macroblocks(self.frame.width as usize);
1293 // Almost always the first macro block, except when non exists (i.e. `width == 0`)
1294 self.left = self.top.first().copied().unwrap_or_default();
1295
1296 self.mbwidth = (self.frame.width + 15) / 16;
1297 self.mbheight = (self.frame.height + 15) / 16;
1298
1299 self.frame.ybuf = vec![0u8; self.frame.width as usize * self.frame.height as usize];
1300 self.frame.ubuf =
1301 vec![0u8; self.frame.chroma_width() as usize * self.frame.chroma_height() as usize];
1302 self.frame.vbuf =
1303 vec![0u8; self.frame.chroma_width() as usize * self.frame.chroma_height() as usize];
1304
1305 self.top_border = vec![127u8; self.frame.width as usize + 4 + 16];
1306 self.left_border = vec![129u8; 1 + 16];
1307 }
1308
1309 let size = first_partition_size as usize;
1310 let mut buf = vec![[0; 4]; (size + 3) / 4];
1311 let bytes: &mut [u8] = buf.as_mut_slice().as_flattened_mut();
1312 self.r.read_exact(&mut bytes[..size])?;
1313
1314 // initialise binary decoder
1315 self.b.init(buf, size)?;
1316
1317 let mut res = self.b.start_accumulated_result();
1318 if self.frame.keyframe {
1319 let color_space = self.b.read_literal(1).or_accumulate(&mut res);
1320 self.frame.pixel_type = self.b.read_literal(1).or_accumulate(&mut res);
1321
1322 if color_space != 0 {
1323 return Err(DecodingError::ColorSpaceInvalid(color_space));
1324 }
1325 }
1326
1327 self.segments_enabled = self.b.read_flag().or_accumulate(&mut res);
1328 if self.segments_enabled {
1329 self.read_segment_updates()?;
1330 }
1331
1332 self.frame.filter_type = self.b.read_flag().or_accumulate(&mut res);
1333 self.frame.filter_level = self.b.read_literal(6).or_accumulate(&mut res);
1334 self.frame.sharpness_level = self.b.read_literal(3).or_accumulate(&mut res);
1335
1336 let lf_adjust_enable = self.b.read_flag().or_accumulate(&mut res);
1337 if lf_adjust_enable {
1338 self.read_loop_filter_adjustments()?;
1339 }
1340
1341 let num_partitions = 1 << self.b.read_literal(2).or_accumulate(&mut res) as usize;
1342 self.b.check(res, ())?;
1343
1344 self.num_partitions = num_partitions as u8;
1345 self.init_partitions(num_partitions)?;
1346
1347 self.read_quantization_indices()?;
1348
1349 if !self.frame.keyframe {
1350 // 9.7 refresh golden frame and altref frame
1351 // FIXME: support this?
1352 return Err(DecodingError::UnsupportedFeature(
1353 "Non-keyframe frames".to_owned(),
1354 ));
1355 }
1356
1357 // Refresh entropy probs ?????
1358 let _ = self.b.read_literal(1);
1359
1360 self.update_token_probabilities()?;
1361
1362 let mut res = self.b.start_accumulated_result();
1363 let mb_no_skip_coeff = self.b.read_literal(1).or_accumulate(&mut res);
1364 self.prob_skip_false = if mb_no_skip_coeff == 1 {
1365 Some(self.b.read_literal(8).or_accumulate(&mut res))
1366 } else {
1367 None
1368 };
1369 self.b.check(res, ())?;
1370
1371 if !self.frame.keyframe {
1372 // 9.10 remaining frame data
1373 self.prob_intra = 0;
1374
1375 // FIXME: support this?
1376 return Err(DecodingError::UnsupportedFeature(
1377 "Non-keyframe frames".to_owned(),
1378 ));
1379 } else {
1380 // Reset motion vectors
1381 }
1382
1383 Ok(())
1384 }
1385
1386 fn read_macroblock_header(&mut self, mbx: usize) -> Result<MacroBlock, DecodingError> {
1387 let mut mb = MacroBlock::default();
1388 let mut res = self.b.start_accumulated_result();
1389
1390 if self.segments_enabled && self.segments_update_map {
1391 mb.segmentid =
1392 (self.b.read_with_tree(&self.segment_tree_nodes)).or_accumulate(&mut res) as u8;
1393 };
1394
1395 mb.coeffs_skipped = if let Some(prob) = self.prob_skip_false {
1396 self.b.read_bool(prob).or_accumulate(&mut res)
1397 } else {
1398 false
1399 };
1400
1401 let inter_predicted = if !self.frame.keyframe {
1402 self.b.read_bool(self.prob_intra).or_accumulate(&mut res)
1403 } else {
1404 false
1405 };
1406
1407 if inter_predicted {
1408 return Err(DecodingError::UnsupportedFeature(
1409 "VP8 inter-prediction".to_owned(),
1410 ));
1411 }
1412
1413 if self.frame.keyframe {
1414 // intra prediction
1415 let luma = (self.b.read_with_tree(&KEYFRAME_YMODE_NODES)).or_accumulate(&mut res);
1416 mb.luma_mode =
1417 LumaMode::from_i8(luma).ok_or(DecodingError::LumaPredictionModeInvalid(luma))?;
1418
1419 match mb.luma_mode.into_intra() {
1420 // `LumaMode::B` - This is predicted individually
1421 None => {
1422 for y in 0usize..4 {
1423 for x in 0usize..4 {
1424 let top = self.top[mbx].bpred[12 + x];
1425 let left = self.left.bpred[y];
1426 let intra = self.b.read_with_tree(
1427 &KEYFRAME_BPRED_MODE_NODES[top as usize][left as usize],
1428 );
1429 let intra = intra.or_accumulate(&mut res);
1430 let bmode = IntraMode::from_i8(intra)
1431 .ok_or(DecodingError::IntraPredictionModeInvalid(intra))?;
1432 mb.bpred[x + y * 4] = bmode;
1433
1434 self.top[mbx].bpred[12 + x] = bmode;
1435 self.left.bpred[y] = bmode;
1436 }
1437 }
1438 }
1439 Some(mode) => {
1440 for i in 0usize..4 {
1441 mb.bpred[12 + i] = mode;
1442 self.left.bpred[i] = mode;
1443 }
1444 }
1445 }
1446
1447 let chroma = (self.b.read_with_tree(&KEYFRAME_UV_MODE_NODES)).or_accumulate(&mut res);
1448 mb.chroma_mode = ChromaMode::from_i8(chroma)
1449 .ok_or(DecodingError::ChromaPredictionModeInvalid(chroma))?;
1450 }
1451
1452 self.top[mbx].chroma_mode = mb.chroma_mode;
1453 self.top[mbx].luma_mode = mb.luma_mode;
1454 self.top[mbx].bpred = mb.bpred;
1455
1456 self.b.check(res, mb)
1457 }
1458
1459 fn intra_predict_luma(&mut self, mbx: usize, mby: usize, mb: &MacroBlock, resdata: &[i32]) {
1460 let stride = 1usize + 16 + 4;
1461 let w = self.frame.width as usize;
1462 let mw = self.mbwidth as usize;
1463 let mut ws = create_border_luma(mbx, mby, mw, &self.top_border, &self.left_border);
1464
1465 match mb.luma_mode {
1466 LumaMode::V => predict_vpred(&mut ws, 16, 1, 1, stride),
1467 LumaMode::H => predict_hpred(&mut ws, 16, 1, 1, stride),
1468 LumaMode::TM => predict_tmpred(&mut ws, 16, 1, 1, stride),
1469 LumaMode::DC => predict_dcpred(&mut ws, 16, stride, mby != 0, mbx != 0),
1470 LumaMode::B => predict_4x4(&mut ws, stride, &mb.bpred, resdata),
1471 }
1472
1473 if mb.luma_mode != LumaMode::B {
1474 for y in 0usize..4 {
1475 for x in 0usize..4 {
1476 let i = x + y * 4;
1477 // Create a reference to a [i32; 16] array for add_residue (slices of size 16 do not work).
1478 let rb: &[i32; 16] = resdata[i * 16..][..16].try_into().unwrap();
1479 let y0 = 1 + y * 4;
1480 let x0 = 1 + x * 4;
1481
1482 add_residue(&mut ws, rb, y0, x0, stride);
1483 }
1484 }
1485 }
1486
1487 self.left_border[0] = ws[16];
1488
1489 for (i, left) in self.left_border[1..][..16].iter_mut().enumerate() {
1490 *left = ws[(i + 1) * stride + 16];
1491 }
1492
1493 for (top, &w) in self.top_border[mbx * 16..][..16]
1494 .iter_mut()
1495 .zip(&ws[16 * stride + 1..][..16])
1496 {
1497 *top = w;
1498 }
1499
1500 // Length is the remainder to the border, but maximally the current chunk.
1501 let ylength = cmp::min(self.frame.height as usize - mby * 16, 16);
1502 let xlength = cmp::min(self.frame.width as usize - mbx * 16, 16);
1503
1504 for y in 0usize..ylength {
1505 for (ybuf, &ws) in self.frame.ybuf[(mby * 16 + y) * w + mbx * 16..][..xlength]
1506 .iter_mut()
1507 .zip(ws[(1 + y) * stride + 1..][..xlength].iter())
1508 {
1509 *ybuf = ws;
1510 }
1511 }
1512 }
1513
1514 fn intra_predict_chroma(&mut self, mbx: usize, mby: usize, mb: &MacroBlock, resdata: &[i32]) {
1515 let stride = 1usize + 8;
1516
1517 let w = self.frame.chroma_width() as usize;
1518
1519 //8x8 with left top border of 1
1520 let mut uws = [0u8; (8 + 1) * (8 + 1)];
1521 let mut vws = [0u8; (8 + 1) * (8 + 1)];
1522
1523 let ylength = cmp::min(self.frame.chroma_height() as usize - mby * 8, 8);
1524 let xlength = cmp::min(self.frame.chroma_width() as usize - mbx * 8, 8);
1525
1526 //left border
1527 for y in 0usize..8 {
1528 let (uy, vy) = if mbx == 0 || y >= ylength {
1529 (129, 129)
1530 } else {
1531 let index = (mby * 8 + y) * w + ((mbx - 1) * 8 + 7);
1532 (self.frame.ubuf[index], self.frame.vbuf[index])
1533 };
1534
1535 uws[(y + 1) * stride] = uy;
1536 vws[(y + 1) * stride] = vy;
1537 }
1538 //top border
1539 for x in 0usize..8 {
1540 let (ux, vx) = if mby == 0 || x >= xlength {
1541 (127, 127)
1542 } else {
1543 let index = ((mby - 1) * 8 + 7) * w + (mbx * 8 + x);
1544 (self.frame.ubuf[index], self.frame.vbuf[index])
1545 };
1546
1547 uws[x + 1] = ux;
1548 vws[x + 1] = vx;
1549 }
1550
1551 //top left point
1552 let (u1, v1) = if mby == 0 {
1553 (127, 127)
1554 } else if mbx == 0 {
1555 (129, 129)
1556 } else {
1557 let index = ((mby - 1) * 8 + 7) * w + (mbx - 1) * 8 + 7;
1558 if index >= self.frame.ubuf.len() {
1559 (127, 127)
1560 } else {
1561 (self.frame.ubuf[index], self.frame.vbuf[index])
1562 }
1563 };
1564
1565 uws[0] = u1;
1566 vws[0] = v1;
1567
1568 match mb.chroma_mode {
1569 ChromaMode::DC => {
1570 predict_dcpred(&mut uws, 8, stride, mby != 0, mbx != 0);
1571 predict_dcpred(&mut vws, 8, stride, mby != 0, mbx != 0);
1572 }
1573 ChromaMode::V => {
1574 predict_vpred(&mut uws, 8, 1, 1, stride);
1575 predict_vpred(&mut vws, 8, 1, 1, stride);
1576 }
1577 ChromaMode::H => {
1578 predict_hpred(&mut uws, 8, 1, 1, stride);
1579 predict_hpred(&mut vws, 8, 1, 1, stride);
1580 }
1581 ChromaMode::TM => {
1582 predict_tmpred(&mut uws, 8, 1, 1, stride);
1583 predict_tmpred(&mut vws, 8, 1, 1, stride);
1584 }
1585 }
1586
1587 for y in 0usize..2 {
1588 for x in 0usize..2 {
1589 let i = x + y * 2;
1590 let urb: &[i32; 16] = resdata[16 * 16 + i * 16..][..16].try_into().unwrap();
1591
1592 let y0 = 1 + y * 4;
1593 let x0 = 1 + x * 4;
1594 add_residue(&mut uws, urb, y0, x0, stride);
1595
1596 let vrb: &[i32; 16] = resdata[20 * 16 + i * 16..][..16].try_into().unwrap();
1597
1598 add_residue(&mut vws, vrb, y0, x0, stride);
1599 }
1600 }
1601
1602 for y in 0usize..ylength {
1603 let uv_buf_index = (mby * 8 + y) * w + mbx * 8;
1604 let ws_index = (1 + y) * stride + 1;
1605
1606 for (((ub, vb), &uw), &vw) in self.frame.ubuf[uv_buf_index..][..xlength]
1607 .iter_mut()
1608 .zip(self.frame.vbuf[uv_buf_index..][..xlength].iter_mut())
1609 .zip(uws[ws_index..][..xlength].iter())
1610 .zip(vws[ws_index..][..xlength].iter())
1611 {
1612 *ub = uw;
1613 *vb = vw;
1614 }
1615 }
1616 }
1617
1618 fn read_coefficients(
1619 &mut self,
1620 block: &mut [i32; 16],
1621 p: usize,
1622 plane: usize,
1623 complexity: usize,
1624 dcq: i16,
1625 acq: i16,
1626 ) -> Result<bool, DecodingError> {
1627 // perform bounds checks once up front,
1628 // so that the compiler doesn't have to insert them in the hot loop below
1629 assert!(complexity <= 2);
1630
1631 let first = if plane == 0 { 1usize } else { 0usize };
1632 let probs = &self.token_probs[plane];
1633 let decoder = &mut self.partitions[p];
1634
1635 let mut res = decoder.start_accumulated_result();
1636
1637 let mut complexity = complexity;
1638 let mut has_coefficients = false;
1639 let mut skip = false;
1640
1641 for i in first..16usize {
1642 let band = COEFF_BANDS[i] as usize;
1643 let tree = &probs[band][complexity];
1644
1645 let token = decoder
1646 .read_with_tree_with_first_node(tree, tree[skip as usize])
1647 .or_accumulate(&mut res);
1648
1649 let mut abs_value = i32::from(match token {
1650 DCT_EOB => break,
1651
1652 DCT_0 => {
1653 skip = true;
1654 has_coefficients = true;
1655 complexity = 0;
1656 continue;
1657 }
1658
1659 literal @ DCT_1..=DCT_4 => i16::from(literal),
1660
1661 category @ DCT_CAT1..=DCT_CAT6 => {
1662 let probs = PROB_DCT_CAT[(category - DCT_CAT1) as usize];
1663
1664 let mut extra = 0i16;
1665
1666 for t in probs.iter().copied() {
1667 if t == 0 {
1668 break;
1669 }
1670 let b = decoder.read_bool(t).or_accumulate(&mut res);
1671 extra = extra + extra + i16::from(b);
1672 }
1673
1674 i16::from(DCT_CAT_BASE[(category - DCT_CAT1) as usize]) + extra
1675 }
1676
1677 c => panic!("unknown token: {c}"),
1678 });
1679
1680 skip = false;
1681
1682 complexity = if abs_value == 0 {
1683 0
1684 } else if abs_value == 1 {
1685 1
1686 } else {
1687 2
1688 };
1689
1690 if decoder.read_flag().or_accumulate(&mut res) {
1691 abs_value = -abs_value;
1692 }
1693
1694 let zigzag = ZIGZAG[i] as usize;
1695 block[zigzag] = abs_value * i32::from(if zigzag > 0 { acq } else { dcq });
1696
1697 has_coefficients = true;
1698 }
1699
1700 decoder.check(res, has_coefficients)
1701 }
1702
1703 fn read_residual_data(
1704 &mut self,
1705 mb: &MacroBlock,
1706 mbx: usize,
1707 p: usize,
1708 ) -> Result<[i32; 384], DecodingError> {
1709 let sindex = mb.segmentid as usize;
1710 let mut blocks = [0i32; 384];
1711 let mut plane = if mb.luma_mode == LumaMode::B { 3 } else { 1 };
1712
1713 if plane == 1 {
1714 let complexity = self.top[mbx].complexity[0] + self.left.complexity[0];
1715 let mut block = [0i32; 16];
1716 let dcq = self.segment[sindex].y2dc;
1717 let acq = self.segment[sindex].y2ac;
1718 let n = self.read_coefficients(&mut block, p, plane, complexity as usize, dcq, acq)?;
1719
1720 self.left.complexity[0] = if n { 1 } else { 0 };
1721 self.top[mbx].complexity[0] = if n { 1 } else { 0 };
1722
1723 transform::iwht4x4(&mut block);
1724
1725 for k in 0usize..16 {
1726 blocks[16 * k] = block[k];
1727 }
1728
1729 plane = 0;
1730 }
1731
1732 for y in 0usize..4 {
1733 let mut left = self.left.complexity[y + 1];
1734 for x in 0usize..4 {
1735 let i = x + y * 4;
1736 let block = &mut blocks[i * 16..][..16];
1737 let block: &mut [i32; 16] = block.try_into().unwrap();
1738
1739 let complexity = self.top[mbx].complexity[x + 1] + left;
1740 let dcq = self.segment[sindex].ydc;
1741 let acq = self.segment[sindex].yac;
1742
1743 let n = self.read_coefficients(block, p, plane, complexity as usize, dcq, acq)?;
1744
1745 if block[0] != 0 || n {
1746 transform::idct4x4(block);
1747 }
1748
1749 left = if n { 1 } else { 0 };
1750 self.top[mbx].complexity[x + 1] = if n { 1 } else { 0 };
1751 }
1752
1753 self.left.complexity[y + 1] = left;
1754 }
1755
1756 plane = 2;
1757
1758 for &j in &[5usize, 7usize] {
1759 for y in 0usize..2 {
1760 let mut left = self.left.complexity[y + j];
1761
1762 for x in 0usize..2 {
1763 let i = x + y * 2 + if j == 5 { 16 } else { 20 };
1764 let block = &mut blocks[i * 16..][..16];
1765 let block: &mut [i32; 16] = block.try_into().unwrap();
1766
1767 let complexity = self.top[mbx].complexity[x + j] + left;
1768 let dcq = self.segment[sindex].uvdc;
1769 let acq = self.segment[sindex].uvac;
1770
1771 let n =
1772 self.read_coefficients(block, p, plane, complexity as usize, dcq, acq)?;
1773 if block[0] != 0 || n {
1774 transform::idct4x4(block);
1775 }
1776
1777 left = if n { 1 } else { 0 };
1778 self.top[mbx].complexity[x + j] = if n { 1 } else { 0 };
1779 }
1780
1781 self.left.complexity[y + j] = left;
1782 }
1783 }
1784
1785 Ok(blocks)
1786 }
1787
1788 /// Does loop filtering on the macroblock
1789 fn loop_filter(&mut self, mbx: usize, mby: usize, mb: &MacroBlock) {
1790 let luma_w = self.frame.width as usize;
1791 let luma_h = self.frame.height as usize;
1792 let chroma_w = self.frame.chroma_width() as usize;
1793 let chroma_h = self.frame.chroma_height() as usize;
1794
1795 let (filter_level, interior_limit, hev_threshold) = self.calculate_filter_parameters(mb);
1796
1797 if filter_level > 0 {
1798 let mbedge_limit = (filter_level + 2) * 2 + interior_limit;
1799 let sub_bedge_limit = (filter_level * 2) + interior_limit;
1800
1801 let luma_ylength = cmp::min(luma_h - 16 * mby, 16);
1802 let luma_xlength = cmp::min(luma_w - 16 * mbx, 16);
1803
1804 let chroma_ylength = cmp::min(chroma_h - 8 * mby, 8);
1805 let chroma_xlength = cmp::min(chroma_w - 8 * mbx, 8);
1806
1807 //filter across left of macroblock
1808 if mbx > 0 {
1809 //simple loop filtering
1810 if self.frame.filter_type {
1811 if luma_xlength >= 2 {
1812 for y in 0usize..luma_ylength {
1813 let y0 = mby * 16 + y;
1814 let x0 = mbx * 16;
1815
1816 loop_filter::simple_segment(
1817 mbedge_limit,
1818 &mut self.frame.ybuf[..],
1819 y0 * luma_w + x0,
1820 1,
1821 );
1822 }
1823 }
1824 } else {
1825 if luma_xlength >= 4 {
1826 for y in 0usize..luma_ylength {
1827 let y0 = mby * 16 + y;
1828 let x0 = mbx * 16;
1829
1830 loop_filter::macroblock_filter(
1831 hev_threshold,
1832 interior_limit,
1833 mbedge_limit,
1834 &mut self.frame.ybuf[..],
1835 y0 * luma_w + x0,
1836 1,
1837 );
1838 }
1839 }
1840
1841 if chroma_xlength >= 4 {
1842 for y in 0usize..chroma_ylength {
1843 let y0 = mby * 8 + y;
1844 let x0 = mbx * 8;
1845
1846 loop_filter::macroblock_filter(
1847 hev_threshold,
1848 interior_limit,
1849 mbedge_limit,
1850 &mut self.frame.ubuf[..],
1851 y0 * chroma_w + x0,
1852 1,
1853 );
1854 loop_filter::macroblock_filter(
1855 hev_threshold,
1856 interior_limit,
1857 mbedge_limit,
1858 &mut self.frame.vbuf[..],
1859 y0 * chroma_w + x0,
1860 1,
1861 );
1862 }
1863 }
1864 }
1865 }
1866
1867 //filter across vertical subblocks in macroblock
1868 if mb.luma_mode == LumaMode::B || !mb.coeffs_skipped {
1869 if self.frame.filter_type {
1870 for x in (4usize..luma_xlength - 1).step_by(4) {
1871 for y in 0..luma_ylength {
1872 let y0 = mby * 16 + y;
1873 let x0 = mbx * 16 + x;
1874
1875 loop_filter::simple_segment(
1876 sub_bedge_limit,
1877 &mut self.frame.ybuf[..],
1878 y0 * luma_w + x0,
1879 1,
1880 );
1881 }
1882 }
1883 } else {
1884 if luma_xlength > 3 {
1885 for x in (4usize..luma_xlength - 3).step_by(4) {
1886 for y in 0..luma_ylength {
1887 let y0 = mby * 16 + y;
1888 let x0 = mbx * 16 + x;
1889
1890 loop_filter::subblock_filter(
1891 hev_threshold,
1892 interior_limit,
1893 sub_bedge_limit,
1894 &mut self.frame.ybuf[..],
1895 y0 * luma_w + x0,
1896 1,
1897 );
1898 }
1899 }
1900 }
1901
1902 if chroma_xlength == 8 {
1903 for y in 0usize..chroma_ylength {
1904 let y0 = mby * 8 + y;
1905 let x0 = mbx * 8 + 4;
1906
1907 loop_filter::subblock_filter(
1908 hev_threshold,
1909 interior_limit,
1910 sub_bedge_limit,
1911 &mut self.frame.ubuf[..],
1912 y0 * chroma_w + x0,
1913 1,
1914 );
1915
1916 loop_filter::subblock_filter(
1917 hev_threshold,
1918 interior_limit,
1919 sub_bedge_limit,
1920 &mut self.frame.vbuf[..],
1921 y0 * chroma_w + x0,
1922 1,
1923 );
1924 }
1925 }
1926 }
1927 }
1928
1929 //filter across top of macroblock
1930 if mby > 0 {
1931 if self.frame.filter_type {
1932 if luma_ylength >= 2 {
1933 for x in 0usize..luma_xlength {
1934 let y0 = mby * 16;
1935 let x0 = mbx * 16 + x;
1936
1937 loop_filter::simple_segment(
1938 mbedge_limit,
1939 &mut self.frame.ybuf[..],
1940 y0 * luma_w + x0,
1941 luma_w,
1942 );
1943 }
1944 }
1945 } else {
1946 //if bottom macroblock, can only filter if there is 3 pixels below
1947 if luma_ylength >= 4 {
1948 for x in 0usize..luma_xlength {
1949 let y0 = mby * 16;
1950 let x0 = mbx * 16 + x;
1951
1952 loop_filter::macroblock_filter(
1953 hev_threshold,
1954 interior_limit,
1955 mbedge_limit,
1956 &mut self.frame.ybuf[..],
1957 y0 * luma_w + x0,
1958 luma_w,
1959 );
1960 }
1961 }
1962
1963 if chroma_ylength >= 4 {
1964 for x in 0usize..chroma_xlength {
1965 let y0 = mby * 8;
1966 let x0 = mbx * 8 + x;
1967
1968 loop_filter::macroblock_filter(
1969 hev_threshold,
1970 interior_limit,
1971 mbedge_limit,
1972 &mut self.frame.ubuf[..],
1973 y0 * chroma_w + x0,
1974 chroma_w,
1975 );
1976 loop_filter::macroblock_filter(
1977 hev_threshold,
1978 interior_limit,
1979 mbedge_limit,
1980 &mut self.frame.vbuf[..],
1981 y0 * chroma_w + x0,
1982 chroma_w,
1983 );
1984 }
1985 }
1986 }
1987 }
1988
1989 //filter across horizontal subblock edges within the macroblock
1990 if mb.luma_mode == LumaMode::B || !mb.coeffs_skipped {
1991 if self.frame.filter_type {
1992 for y in (4usize..luma_ylength - 1).step_by(4) {
1993 for x in 0..luma_xlength {
1994 let y0 = mby * 16 + y;
1995 let x0 = mbx * 16 + x;
1996
1997 loop_filter::simple_segment(
1998 sub_bedge_limit,
1999 &mut self.frame.ybuf[..],
2000 y0 * luma_w + x0,
2001 luma_w,
2002 );
2003 }
2004 }
2005 } else {
2006 if luma_ylength > 3 {
2007 for y in (4usize..luma_ylength - 3).step_by(4) {
2008 for x in 0..luma_xlength {
2009 let y0 = mby * 16 + y;
2010 let x0 = mbx * 16 + x;
2011
2012 loop_filter::subblock_filter(
2013 hev_threshold,
2014 interior_limit,
2015 sub_bedge_limit,
2016 &mut self.frame.ybuf[..],
2017 y0 * luma_w + x0,
2018 luma_w,
2019 );
2020 }
2021 }
2022 }
2023
2024 if chroma_ylength == 8 {
2025 for x in 0..chroma_xlength {
2026 let y0 = mby * 8 + 4;
2027 let x0 = mbx * 8 + x;
2028
2029 loop_filter::subblock_filter(
2030 hev_threshold,
2031 interior_limit,
2032 sub_bedge_limit,
2033 &mut self.frame.ubuf[..],
2034 y0 * chroma_w + x0,
2035 chroma_w,
2036 );
2037
2038 loop_filter::subblock_filter(
2039 hev_threshold,
2040 interior_limit,
2041 sub_bedge_limit,
2042 &mut self.frame.vbuf[..],
2043 y0 * chroma_w + x0,
2044 chroma_w,
2045 );
2046 }
2047 }
2048 }
2049 }
2050 }
2051 }
2052
2053 //return values are the filter level, interior limit and hev threshold
2054 fn calculate_filter_parameters(&self, macroblock: &MacroBlock) -> (u8, u8, u8) {
2055 let segment = self.segment[macroblock.segmentid as usize];
2056 let mut filter_level = i32::from(self.frame.filter_level);
2057
2058 if self.segments_enabled {
2059 if segment.delta_values {
2060 filter_level += i32::from(segment.loopfilter_level);
2061 } else {
2062 filter_level = i32::from(segment.loopfilter_level);
2063 }
2064 }
2065
2066 filter_level = filter_level.clamp(0, 63);
2067
2068 if macroblock.luma_mode == LumaMode::B {
2069 filter_level += self.mode_delta[0];
2070 }
2071
2072 let filter_level = filter_level.clamp(0, 63) as u8;
2073
2074 //interior limit
2075 let mut interior_limit = filter_level;
2076
2077 if self.frame.sharpness_level > 0 {
2078 interior_limit >>= if self.frame.sharpness_level > 4 { 2 } else { 1 };
2079
2080 if interior_limit > 9 - self.frame.sharpness_level {
2081 interior_limit = 9 - self.frame.sharpness_level;
2082 }
2083 }
2084
2085 if interior_limit == 0 {
2086 interior_limit = 1;
2087 }
2088
2089 //high edge variance threshold
2090 let mut hev_threshold = 0;
2091
2092 #[allow(clippy::collapsible_else_if)]
2093 if self.frame.keyframe {
2094 if filter_level >= 40 {
2095 hev_threshold = 2;
2096 } else {
2097 hev_threshold = 1;
2098 }
2099 } else {
2100 if filter_level >= 40 {
2101 hev_threshold = 3;
2102 } else if filter_level >= 20 {
2103 hev_threshold = 2;
2104 } else if filter_level >= 15 {
2105 hev_threshold = 1;
2106 }
2107 }
2108
2109 (filter_level, interior_limit, hev_threshold)
2110 }
2111
2112 /// Decodes the current frame
2113 pub fn decode_frame(r: R) -> Result<Frame, DecodingError> {
2114 let decoder = Self::new(r);
2115 decoder.decode_frame_()
2116 }
2117
2118 fn decode_frame_(mut self) -> Result<Frame, DecodingError> {
2119 self.read_frame_header()?;
2120
2121 for mby in 0..self.mbheight as usize {
2122 let p = mby % self.num_partitions as usize;
2123 self.left = MacroBlock::default();
2124
2125 for mbx in 0..self.mbwidth as usize {
2126 let mb = self.read_macroblock_header(mbx)?;
2127 let blocks = if !mb.coeffs_skipped {
2128 self.read_residual_data(&mb, mbx, p)?
2129 } else {
2130 if mb.luma_mode != LumaMode::B {
2131 self.left.complexity[0] = 0;
2132 self.top[mbx].complexity[0] = 0;
2133 }
2134
2135 for i in 1usize..9 {
2136 self.left.complexity[i] = 0;
2137 self.top[mbx].complexity[i] = 0;
2138 }
2139
2140 [0i32; 384]
2141 };
2142
2143 self.intra_predict_luma(mbx, mby, &mb, &blocks);
2144 self.intra_predict_chroma(mbx, mby, &mb, &blocks);
2145
2146 self.macroblocks.push(mb);
2147 }
2148
2149 self.left_border = vec![129u8; 1 + 16];
2150 }
2151
2152 //do loop filtering
2153 for mby in 0..self.mbheight as usize {
2154 for mbx in 0..self.mbwidth as usize {
2155 let mb = self.macroblocks[mby * self.mbwidth as usize + mbx];
2156 self.loop_filter(mbx, mby, &mb);
2157 }
2158 }
2159
2160 Ok(self.frame)
2161 }
2162}
2163
2164impl LumaMode {
2165 const fn from_i8(val: i8) -> Option<Self> {
2166 Some(match val {
2167 DC_PRED => Self::DC,
2168 V_PRED => Self::V,
2169 H_PRED => Self::H,
2170 TM_PRED => Self::TM,
2171 B_PRED => Self::B,
2172 _ => return None,
2173 })
2174 }
2175
2176 const fn into_intra(self) -> Option<IntraMode> {
2177 Some(match self {
2178 Self::DC => IntraMode::DC,
2179 Self::V => IntraMode::VE,
2180 Self::H => IntraMode::HE,
2181 Self::TM => IntraMode::TM,
2182 Self::B => return None,
2183 })
2184 }
2185}
2186
2187impl ChromaMode {
2188 const fn from_i8(val: i8) -> Option<Self> {
2189 Some(match val {
2190 DC_PRED => Self::DC,
2191 V_PRED => Self::V,
2192 H_PRED => Self::H,
2193 TM_PRED => Self::TM,
2194 _ => return None,
2195 })
2196 }
2197}
2198
2199impl IntraMode {
2200 const fn from_i8(val: i8) -> Option<Self> {
2201 Some(match val {
2202 B_DC_PRED => Self::DC,
2203 B_TM_PRED => Self::TM,
2204 B_VE_PRED => Self::VE,
2205 B_HE_PRED => Self::HE,
2206 B_LD_PRED => Self::LD,
2207 B_RD_PRED => Self::RD,
2208 B_VR_PRED => Self::VR,
2209 B_VL_PRED => Self::VL,
2210 B_HD_PRED => Self::HD,
2211 B_HU_PRED => Self::HU,
2212 _ => return None,
2213 })
2214 }
2215}
2216
2217fn init_top_macroblocks(width: usize) -> Vec<MacroBlock> {
2218 let mb_width: usize = (width + 15) / 16;
2219
2220 let mb: MacroBlock = MacroBlock {
2221 // Section 11.3 #3
2222 bpred: [IntraMode::DC; 16],
2223 luma_mode: LumaMode::DC,
2224 ..MacroBlock::default()
2225 };
2226
2227 vec![mb; mb_width]
2228}
2229
2230fn create_border_luma(mbx: usize, mby: usize, mbw: usize, top: &[u8], left: &[u8]) -> [u8; 357] {
2231 let stride = 1usize + 16 + 4;
2232 let mut ws = [0u8; (1 + 16) * (1 + 16 + 4)];
2233
2234 // A
2235 {
2236 let above = &mut ws[1..stride];
2237 if mby == 0 {
2238 for above in above.iter_mut() {
2239 *above = 127;
2240 }
2241 } else {
2242 for (above, &top) in above[..16].iter_mut().zip(&top[mbx * 16..]) {
2243 *above = top;
2244 }
2245
2246 if mbx == mbw - 1 {
2247 for above in &mut above[16..] {
2248 *above = top[mbx * 16 + 15];
2249 }
2250 } else {
2251 for (above, &top) in above[16..].iter_mut().zip(&top[mbx * 16 + 16..]) {
2252 *above = top;
2253 }
2254 }
2255 }
2256 }
2257
2258 for i in 17usize..stride {
2259 ws[4 * stride + i] = ws[i];
2260 ws[8 * stride + i] = ws[i];
2261 ws[12 * stride + i] = ws[i];
2262 }
2263
2264 // L
2265 if mbx == 0 {
2266 for i in 0usize..16 {
2267 ws[(i + 1) * stride] = 129;
2268 }
2269 } else {
2270 for (i, &left) in (0usize..16).zip(&left[1..]) {
2271 ws[(i + 1) * stride] = left;
2272 }
2273 }
2274
2275 // P
2276 ws[0] = if mby == 0 {
2277 127
2278 } else if mbx == 0 {
2279 129
2280 } else {
2281 left[0]
2282 };
2283
2284 ws
2285}
2286
2287fn avg3(left: u8, this: u8, right: u8) -> u8 {
2288 let avg: u16 = (u16::from(left) + 2 * u16::from(this) + u16::from(right) + 2) >> 2;
2289 avg as u8
2290}
2291
2292fn avg2(this: u8, right: u8) -> u8 {
2293 let avg: u16 = (u16::from(this) + u16::from(right) + 1) >> 1;
2294 avg as u8
2295}
2296
2297// Only 16 elements from rblock are used to add residue, so it is restricted to 16 elements
2298// to enable SIMD and other optimizations.
2299//
2300// Clippy suggests the clamp method, but it seems to optimize worse as of rustc 1.82.0 nightly.
2301#[allow(clippy::manual_clamp)]
2302fn add_residue(pblock: &mut [u8], rblock: &[i32; 16], y0: usize, x0: usize, stride: usize) {
2303 let mut pos: usize = y0 * stride + x0;
2304 for row: &[i32] in rblock.chunks(chunk_size:4) {
2305 for (p: &mut u8, &a: i32) in pblock[pos..][..4].iter_mut().zip(row.iter()) {
2306 *p = (a + i32::from(*p)).max(0).min(255) as u8;
2307 }
2308 pos += stride;
2309 }
2310}
2311
2312fn predict_4x4(ws: &mut [u8], stride: usize, modes: &[IntraMode], resdata: &[i32]) {
2313 for sby in 0usize..4 {
2314 for sbx in 0usize..4 {
2315 let i = sbx + sby * 4;
2316 let y0 = sby * 4 + 1;
2317 let x0 = sbx * 4 + 1;
2318
2319 match modes[i] {
2320 IntraMode::TM => predict_tmpred(ws, 4, x0, y0, stride),
2321 IntraMode::VE => predict_bvepred(ws, x0, y0, stride),
2322 IntraMode::HE => predict_bhepred(ws, x0, y0, stride),
2323 IntraMode::DC => predict_bdcpred(ws, x0, y0, stride),
2324 IntraMode::LD => predict_bldpred(ws, x0, y0, stride),
2325 IntraMode::RD => predict_brdpred(ws, x0, y0, stride),
2326 IntraMode::VR => predict_bvrpred(ws, x0, y0, stride),
2327 IntraMode::VL => predict_bvlpred(ws, x0, y0, stride),
2328 IntraMode::HD => predict_bhdpred(ws, x0, y0, stride),
2329 IntraMode::HU => predict_bhupred(ws, x0, y0, stride),
2330 }
2331
2332 let rb: &[i32; 16] = resdata[i * 16..][..16].try_into().unwrap();
2333 add_residue(ws, rb, y0, x0, stride);
2334 }
2335 }
2336}
2337
2338fn predict_vpred(a: &mut [u8], size: usize, x0: usize, y0: usize, stride: usize) {
2339 // This pass copies the top row to the rows below it.
2340 let (above: &mut [u8], curr: &mut [u8]) = a.split_at_mut(mid:stride * y0);
2341 let above_slice: &[u8] = &above[x0..];
2342
2343 for curr_chunk: &mut [u8] in curr.chunks_exact_mut(chunk_size:stride).take(size) {
2344 for (curr: &mut u8, &above: u8) in curr_chunk[1..].iter_mut().zip(above_slice) {
2345 *curr = above;
2346 }
2347 }
2348}
2349
2350fn predict_hpred(a: &mut [u8], size: usize, x0: usize, y0: usize, stride: usize) {
2351 // This pass copies the first value of a row to the values right of it.
2352 for chunk: &mut [u8] in a.chunks_exact_mut(chunk_size:stride).skip(y0).take(size) {
2353 let left: u8 = chunk[x0 - 1];
2354 chunk[x0..].iter_mut().for_each(|a: &mut u8| *a = left);
2355 }
2356}
2357
2358fn predict_dcpred(a: &mut [u8], size: usize, stride: usize, above: bool, left: bool) {
2359 let mut sum = 0;
2360 let mut shf = if size == 8 { 2 } else { 3 };
2361
2362 if left {
2363 for y in 0usize..size {
2364 sum += u32::from(a[(y + 1) * stride]);
2365 }
2366
2367 shf += 1;
2368 }
2369
2370 if above {
2371 sum += a[1..=size].iter().fold(0, |acc, &x| acc + u32::from(x));
2372
2373 shf += 1;
2374 }
2375
2376 let dcval = if !left && !above {
2377 128
2378 } else {
2379 (sum + (1 << (shf - 1))) >> shf
2380 };
2381
2382 for y in 0usize..size {
2383 a[1 + stride * (y + 1)..][..size]
2384 .iter_mut()
2385 .for_each(|a| *a = dcval as u8);
2386 }
2387}
2388
2389// Clippy suggests the clamp method, but it seems to optimize worse as of rustc 1.82.0 nightly.
2390#[allow(clippy::manual_clamp)]
2391fn predict_tmpred(a: &mut [u8], size: usize, x0: usize, y0: usize, stride: usize) {
2392 // The formula for tmpred is:
2393 // X_ij = L_i + A_j - P (i, j=0, 1, 2, 3)
2394 //
2395 // |-----|-----|-----|-----|-----|
2396 // | P | A0 | A1 | A2 | A3 |
2397 // |-----|-----|-----|-----|-----|
2398 // | L0 | X00 | X01 | X02 | X03 |
2399 // |-----|-----|-----|-----|-----|
2400 // | L1 | X10 | X11 | X12 | X13 |
2401 // |-----|-----|-----|-----|-----|
2402 // | L2 | X20 | X21 | X22 | X23 |
2403 // |-----|-----|-----|-----|-----|
2404 // | L3 | X30 | X31 | X32 | X33 |
2405 // |-----|-----|-----|-----|-----|
2406 // Diagram from p. 52 of RFC 6386
2407
2408 // Split at L0
2409 let (above, x_block) = a.split_at_mut(y0 * stride + (x0 - 1));
2410 let p = i32::from(above[(y0 - 1) * stride + x0 - 1]);
2411 let above_slice = &above[(y0 - 1) * stride + x0..];
2412
2413 for y in 0usize..size {
2414 let left_minus_p = i32::from(x_block[y * stride]) - p;
2415
2416 // Add 1 to skip over L0 byte
2417 x_block[y * stride + 1..][..size]
2418 .iter_mut()
2419 .zip(above_slice)
2420 .for_each(|(cur, &abv)| *cur = (left_minus_p + i32::from(abv)).max(0).min(255) as u8);
2421 }
2422}
2423
2424fn predict_bdcpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2425 let mut v: u32 = 4;
2426
2427 aIter<'_, u8>[(y0 - 1) * stride + x0..][..4]
2428 .iter()
2429 .for_each(|&a: u8| v += u32::from(a));
2430
2431 for i: usize in 0usize..4 {
2432 v += u32::from(a[(y0 + i) * stride + x0 - 1]);
2433 }
2434
2435 v >>= 3;
2436 for chunk: &mut [u8] in a.chunks_exact_mut(chunk_size:stride).skip(y0).take(4) {
2437 for ch: &mut u8 in &mut chunk[x0..][..4] {
2438 *ch = v as u8;
2439 }
2440 }
2441}
2442
2443fn topleft_pixel(a: &[u8], x0: usize, y0: usize, stride: usize) -> u8 {
2444 a[(y0 - 1) * stride + x0 - 1]
2445}
2446
2447fn top_pixels(a: &[u8], x0: usize, y0: usize, stride: usize) -> (u8, u8, u8, u8, u8, u8, u8, u8) {
2448 let pos: usize = (y0 - 1) * stride + x0;
2449 let a_slice: &[u8] = &a[pos..pos + 8];
2450 let a0: u8 = a_slice[0];
2451 let a1: u8 = a_slice[1];
2452 let a2: u8 = a_slice[2];
2453 let a3: u8 = a_slice[3];
2454 let a4: u8 = a_slice[4];
2455 let a5: u8 = a_slice[5];
2456 let a6: u8 = a_slice[6];
2457 let a7: u8 = a_slice[7];
2458
2459 (a0, a1, a2, a3, a4, a5, a6, a7)
2460}
2461
2462fn left_pixels(a: &[u8], x0: usize, y0: usize, stride: usize) -> (u8, u8, u8, u8) {
2463 let l0: u8 = a[y0 * stride + x0 - 1];
2464 let l1: u8 = a[(y0 + 1) * stride + x0 - 1];
2465 let l2: u8 = a[(y0 + 2) * stride + x0 - 1];
2466 let l3: u8 = a[(y0 + 3) * stride + x0 - 1];
2467
2468 (l0, l1, l2, l3)
2469}
2470
2471fn edge_pixels(
2472 a: &[u8],
2473 x0: usize,
2474 y0: usize,
2475 stride: usize,
2476) -> (u8, u8, u8, u8, u8, u8, u8, u8, u8) {
2477 let pos: usize = (y0 - 1) * stride + x0 - 1;
2478 let a_slice: &[u8] = &a[pos..=pos + 4];
2479 let e0: u8 = a[pos + 4 * stride];
2480 let e1: u8 = a[pos + 3 * stride];
2481 let e2: u8 = a[pos + 2 * stride];
2482 let e3: u8 = a[pos + stride];
2483 let e4: u8 = a_slice[0];
2484 let e5: u8 = a_slice[1];
2485 let e6: u8 = a_slice[2];
2486 let e7: u8 = a_slice[3];
2487 let e8: u8 = a_slice[4];
2488
2489 (e0, e1, e2, e3, e4, e5, e6, e7, e8)
2490}
2491
2492fn predict_bvepred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2493 let p: u8 = topleft_pixel(a, x0, y0, stride);
2494 let (a0: u8, a1: u8, a2: u8, a3: u8, a4: u8, ..) = top_pixels(a, x0, y0, stride);
2495 let avg_1: u8 = avg3(left:p, this:a0, right:a1);
2496 let avg_2: u8 = avg3(left:a0, this:a1, right:a2);
2497 let avg_3: u8 = avg3(left:a1, this:a2, right:a3);
2498 let avg_4: u8 = avg3(left:a2, this:a3, right:a4);
2499
2500 let avg: [u8; 4] = [avg_1, avg_2, avg_3, avg_4];
2501
2502 let mut pos: usize = y0 * stride + x0;
2503 for _ in 0..4 {
2504 a[pos..=pos + 3].copy_from_slice(&avg);
2505 pos += stride;
2506 }
2507}
2508
2509fn predict_bhepred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2510 let p: u8 = topleft_pixel(a, x0, y0, stride);
2511 let (l0: u8, l1: u8, l2: u8, l3: u8) = left_pixels(a, x0, y0, stride);
2512
2513 let avgs: [u8; 4] = [
2514 avg3(left:p, this:l0, right:l1),
2515 avg3(left:l0, this:l1, right:l2),
2516 avg3(left:l1, this:l2, right:l3),
2517 avg3(left:l2, this:l3, right:l3),
2518 ];
2519
2520 let mut pos: usize = y0 * stride + x0;
2521 for avg: u8 in avgs {
2522 for a_p: &mut u8 in &mut a[pos..=pos + 3] {
2523 *a_p = avg;
2524 }
2525 pos += stride;
2526 }
2527}
2528
2529fn predict_bldpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2530 let (a0: u8, a1: u8, a2: u8, a3: u8, a4: u8, a5: u8, a6: u8, a7: u8) = top_pixels(a, x0, y0, stride);
2531
2532 let avgs: [u8; 7] = [
2533 avg3(left:a0, this:a1, right:a2),
2534 avg3(left:a1, this:a2, right:a3),
2535 avg3(left:a2, this:a3, right:a4),
2536 avg3(left:a3, this:a4, right:a5),
2537 avg3(left:a4, this:a5, right:a6),
2538 avg3(left:a5, this:a6, right:a7),
2539 avg3(left:a6, this:a7, right:a7),
2540 ];
2541
2542 let mut pos: usize = y0 * stride + x0;
2543
2544 for i: usize in 0..4 {
2545 a[pos..=pos + 3].copy_from_slice(&avgs[i..=i + 3]);
2546 pos += stride;
2547 }
2548}
2549
2550fn predict_brdpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2551 let (e0: u8, e1: u8, e2: u8, e3: u8, e4: u8, e5: u8, e6: u8, e7: u8, e8: u8) = edge_pixels(a, x0, y0, stride);
2552
2553 let avgs: [u8; 7] = [
2554 avg3(left:e0, this:e1, right:e2),
2555 avg3(left:e1, this:e2, right:e3),
2556 avg3(left:e2, this:e3, right:e4),
2557 avg3(left:e3, this:e4, right:e5),
2558 avg3(left:e4, this:e5, right:e6),
2559 avg3(left:e5, this:e6, right:e7),
2560 avg3(left:e6, this:e7, right:e8),
2561 ];
2562 let mut pos: usize = y0 * stride + x0;
2563
2564 for i: usize in 0..4 {
2565 a[pos..=pos + 3].copy_from_slice(&avgs[3 - i..7 - i]);
2566 pos += stride;
2567 }
2568}
2569
2570fn predict_bvrpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2571 let (_, e1: u8, e2: u8, e3: u8, e4: u8, e5: u8, e6: u8, e7: u8, e8: u8) = edge_pixels(a, x0, y0, stride);
2572
2573 a[(y0 + 3) * stride + x0] = avg3(left:e1, this:e2, right:e3);
2574 a[(y0 + 2) * stride + x0] = avg3(left:e2, this:e3, right:e4);
2575 a[(y0 + 3) * stride + x0 + 1] = avg3(left:e3, this:e4, right:e5);
2576 a[(y0 + 1) * stride + x0] = avg3(left:e3, this:e4, right:e5);
2577 a[(y0 + 2) * stride + x0 + 1] = avg2(this:e4, right:e5);
2578 a[y0 * stride + x0] = avg2(this:e4, right:e5);
2579 a[(y0 + 3) * stride + x0 + 2] = avg3(left:e4, this:e5, right:e6);
2580 a[(y0 + 1) * stride + x0 + 1] = avg3(left:e4, this:e5, right:e6);
2581 a[(y0 + 2) * stride + x0 + 2] = avg2(this:e5, right:e6);
2582 a[y0 * stride + x0 + 1] = avg2(this:e5, right:e6);
2583 a[(y0 + 3) * stride + x0 + 3] = avg3(left:e5, this:e6, right:e7);
2584 a[(y0 + 1) * stride + x0 + 2] = avg3(left:e5, this:e6, right:e7);
2585 a[(y0 + 2) * stride + x0 + 3] = avg2(this:e6, right:e7);
2586 a[y0 * stride + x0 + 2] = avg2(this:e6, right:e7);
2587 a[(y0 + 1) * stride + x0 + 3] = avg3(left:e6, this:e7, right:e8);
2588 a[y0 * stride + x0 + 3] = avg2(this:e7, right:e8);
2589}
2590
2591fn predict_bvlpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2592 let (a0: u8, a1: u8, a2: u8, a3: u8, a4: u8, a5: u8, a6: u8, a7: u8) = top_pixels(a, x0, y0, stride);
2593
2594 a[y0 * stride + x0] = avg2(this:a0, right:a1);
2595 a[(y0 + 1) * stride + x0] = avg3(left:a0, this:a1, right:a2);
2596 a[(y0 + 2) * stride + x0] = avg2(this:a1, right:a2);
2597 a[y0 * stride + x0 + 1] = avg2(this:a1, right:a2);
2598 a[(y0 + 1) * stride + x0 + 1] = avg3(left:a1, this:a2, right:a3);
2599 a[(y0 + 3) * stride + x0] = avg3(left:a1, this:a2, right:a3);
2600 a[(y0 + 2) * stride + x0 + 1] = avg2(this:a2, right:a3);
2601 a[y0 * stride + x0 + 2] = avg2(this:a2, right:a3);
2602 a[(y0 + 3) * stride + x0 + 1] = avg3(left:a2, this:a3, right:a4);
2603 a[(y0 + 1) * stride + x0 + 2] = avg3(left:a2, this:a3, right:a4);
2604 a[(y0 + 2) * stride + x0 + 2] = avg2(this:a3, right:a4);
2605 a[y0 * stride + x0 + 3] = avg2(this:a3, right:a4);
2606 a[(y0 + 3) * stride + x0 + 2] = avg3(left:a3, this:a4, right:a5);
2607 a[(y0 + 1) * stride + x0 + 3] = avg3(left:a3, this:a4, right:a5);
2608 a[(y0 + 2) * stride + x0 + 3] = avg3(left:a4, this:a5, right:a6);
2609 a[(y0 + 3) * stride + x0 + 3] = avg3(left:a5, this:a6, right:a7);
2610}
2611
2612fn predict_bhdpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2613 let (e0: u8, e1: u8, e2: u8, e3: u8, e4: u8, e5: u8, e6: u8, e7: u8, _) = edge_pixels(a, x0, y0, stride);
2614
2615 a[(y0 + 3) * stride + x0] = avg2(this:e0, right:e1);
2616 a[(y0 + 3) * stride + x0 + 1] = avg3(left:e0, this:e1, right:e2);
2617 a[(y0 + 2) * stride + x0] = avg2(this:e1, right:e2);
2618 a[(y0 + 3) * stride + x0 + 2] = avg2(this:e1, right:e2);
2619 a[(y0 + 2) * stride + x0 + 1] = avg3(left:e1, this:e2, right:e3);
2620 a[(y0 + 3) * stride + x0 + 3] = avg3(left:e1, this:e2, right:e3);
2621 a[(y0 + 2) * stride + x0 + 2] = avg2(this:e2, right:e3);
2622 a[(y0 + 1) * stride + x0] = avg2(this:e2, right:e3);
2623 a[(y0 + 2) * stride + x0 + 3] = avg3(left:e2, this:e3, right:e4);
2624 a[(y0 + 1) * stride + x0 + 1] = avg3(left:e2, this:e3, right:e4);
2625 a[(y0 + 1) * stride + x0 + 2] = avg2(this:e3, right:e4);
2626 a[y0 * stride + x0] = avg2(this:e3, right:e4);
2627 a[(y0 + 1) * stride + x0 + 3] = avg3(left:e3, this:e4, right:e5);
2628 a[y0 * stride + x0 + 1] = avg3(left:e3, this:e4, right:e5);
2629 a[y0 * stride + x0 + 2] = avg3(left:e4, this:e5, right:e6);
2630 a[y0 * stride + x0 + 3] = avg3(left:e5, this:e6, right:e7);
2631}
2632
2633fn predict_bhupred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2634 let (l0: u8, l1: u8, l2: u8, l3: u8) = left_pixels(a, x0, y0, stride);
2635
2636 a[y0 * stride + x0] = avg2(this:l0, right:l1);
2637 a[y0 * stride + x0 + 1] = avg3(left:l0, this:l1, right:l2);
2638 a[y0 * stride + x0 + 2] = avg2(this:l1, right:l2);
2639 a[(y0 + 1) * stride + x0] = avg2(this:l1, right:l2);
2640 a[y0 * stride + x0 + 3] = avg3(left:l1, this:l2, right:l3);
2641 a[(y0 + 1) * stride + x0 + 1] = avg3(left:l1, this:l2, right:l3);
2642 a[(y0 + 1) * stride + x0 + 2] = avg2(this:l2, right:l3);
2643 a[(y0 + 2) * stride + x0] = avg2(this:l2, right:l3);
2644 a[(y0 + 1) * stride + x0 + 3] = avg3(left:l2, this:l3, right:l3);
2645 a[(y0 + 2) * stride + x0 + 1] = avg3(left:l2, this:l3, right:l3);
2646 a[(y0 + 2) * stride + x0 + 2] = l3;
2647 a[(y0 + 2) * stride + x0 + 3] = l3;
2648 a[(y0 + 3) * stride + x0] = l3;
2649 a[(y0 + 3) * stride + x0 + 1] = l3;
2650 a[(y0 + 3) * stride + x0 + 2] = l3;
2651 a[(y0 + 3) * stride + x0 + 3] = l3;
2652}
2653
2654#[cfg(all(test, feature = "_benchmarks"))]
2655mod benches {
2656 use super::*;
2657 use test::{black_box, Bencher};
2658
2659 const W: usize = 256;
2660 const H: usize = 256;
2661
2662 fn make_sample_image() -> Vec<u8> {
2663 let mut v = Vec::with_capacity((W * H * 4) as usize);
2664 for c in 0u8..=255 {
2665 for k in 0u8..=255 {
2666 v.push(c);
2667 v.push(0);
2668 v.push(0);
2669 v.push(k);
2670 }
2671 }
2672 v
2673 }
2674
2675 #[bench]
2676 fn bench_predict_4x4(b: &mut Bencher) {
2677 let mut v = black_box(make_sample_image());
2678
2679 let res_data = vec![1i32; W * H * 4];
2680 let modes = [
2681 IntraMode::TM,
2682 IntraMode::VE,
2683 IntraMode::HE,
2684 IntraMode::DC,
2685 IntraMode::LD,
2686 IntraMode::RD,
2687 IntraMode::VR,
2688 IntraMode::VL,
2689 IntraMode::HD,
2690 IntraMode::HU,
2691 IntraMode::TM,
2692 IntraMode::VE,
2693 IntraMode::HE,
2694 IntraMode::DC,
2695 IntraMode::LD,
2696 IntraMode::RD,
2697 ];
2698
2699 b.iter(|| {
2700 black_box(predict_4x4(&mut v, W * 2, &modes, &res_data));
2701 });
2702 }
2703
2704 #[bench]
2705 fn bench_predict_bvepred(b: &mut Bencher) {
2706 let mut v = make_sample_image();
2707
2708 b.iter(|| {
2709 predict_bvepred(black_box(&mut v), 5, 5, W * 2);
2710 });
2711 }
2712
2713 #[bench]
2714 fn bench_predict_bldpred(b: &mut Bencher) {
2715 let mut v = black_box(make_sample_image());
2716
2717 b.iter(|| {
2718 black_box(predict_bldpred(black_box(&mut v), 5, 5, W * 2));
2719 });
2720 }
2721
2722 #[bench]
2723 fn bench_predict_brdpred(b: &mut Bencher) {
2724 let mut v = black_box(make_sample_image());
2725
2726 b.iter(|| {
2727 black_box(predict_brdpred(black_box(&mut v), 5, 5, W * 2));
2728 });
2729 }
2730
2731 #[bench]
2732 fn bench_predict_bhepred(b: &mut Bencher) {
2733 let mut v = black_box(make_sample_image());
2734
2735 b.iter(|| {
2736 black_box(predict_bhepred(black_box(&mut v), 5, 5, W * 2));
2737 });
2738 }
2739
2740 #[bench]
2741 fn bench_top_pixels(b: &mut Bencher) {
2742 let v = black_box(make_sample_image());
2743
2744 b.iter(|| {
2745 black_box(top_pixels(black_box(&v), 5, 5, W * 2));
2746 });
2747 }
2748
2749 #[bench]
2750 fn bench_edge_pixels(b: &mut Bencher) {
2751 let v = black_box(make_sample_image());
2752
2753 b.iter(|| {
2754 black_box(edge_pixels(black_box(&v), 5, 5, W * 2));
2755 });
2756 }
2757}
2758
2759#[cfg(test)]
2760mod tests {
2761 use super::*;
2762
2763 #[test]
2764 fn test_avg2() {
2765 for i in 0u8..=255 {
2766 for j in 0u8..=255 {
2767 let ceil_avg = (f32::from(i) + f32::from(j)) / 2.0;
2768 let ceil_avg = ceil_avg.ceil() as u8;
2769 assert_eq!(
2770 ceil_avg,
2771 avg2(i, j),
2772 "avg2({}, {}), expected {}, got {}.",
2773 i,
2774 j,
2775 ceil_avg,
2776 avg2(i, j)
2777 );
2778 }
2779 }
2780 }
2781
2782 #[test]
2783 fn test_avg2_specific() {
2784 assert_eq!(
2785 255,
2786 avg2(255, 255),
2787 "avg2(255, 255), expected 255, got {}.",
2788 avg2(255, 255)
2789 );
2790 assert_eq!(1, avg2(1, 1), "avg2(1, 1), expected 1, got {}.", avg2(1, 1));
2791 assert_eq!(2, avg2(2, 1), "avg2(2, 1), expected 2, got {}.", avg2(2, 1));
2792 }
2793
2794 #[test]
2795 fn test_avg3() {
2796 for i in 0u8..=255 {
2797 for j in 0u8..=255 {
2798 for k in 0u8..=255 {
2799 let floor_avg =
2800 (2.0f32.mul_add(f32::from(j), f32::from(i)) + { f32::from(k) } + 2.0) / 4.0;
2801 let floor_avg = floor_avg.floor() as u8;
2802 assert_eq!(
2803 floor_avg,
2804 avg3(i, j, k),
2805 "avg3({}, {}, {}), expected {}, got {}.",
2806 i,
2807 j,
2808 k,
2809 floor_avg,
2810 avg3(i, j, k)
2811 );
2812 }
2813 }
2814 }
2815 }
2816
2817 #[test]
2818 fn test_edge_pixels() {
2819 #[rustfmt::skip]
2820 let im = vec![5, 6, 7, 8, 9,
2821 4, 0, 0, 0, 0,
2822 3, 0, 0, 0, 0,
2823 2, 0, 0, 0, 0,
2824 1, 0, 0, 0, 0];
2825 let (e0, e1, e2, e3, e4, e5, e6, e7, e8) = edge_pixels(&im, 1, 1, 5);
2826 assert_eq!(e0, 1);
2827 assert_eq!(e1, 2);
2828 assert_eq!(e2, 3);
2829 assert_eq!(e3, 4);
2830 assert_eq!(e4, 5);
2831 assert_eq!(e5, 6);
2832 assert_eq!(e6, 7);
2833 assert_eq!(e7, 8);
2834 assert_eq!(e8, 9);
2835 }
2836
2837 #[test]
2838 fn test_top_pixels() {
2839 #[rustfmt::skip]
2840 let im = vec![1, 2, 3, 4, 5, 6, 7, 8,
2841 0, 0, 0, 0, 0, 0, 0, 0,
2842 0, 0, 0, 0, 0, 0, 0, 0,
2843 0, 0, 0, 0, 0, 0, 0, 0,
2844 0, 0, 0, 0, 0, 0, 0, 0,
2845 0, 0, 0, 0, 0, 0, 0, 0,
2846 0, 0, 0, 0, 0, 0, 0, 0,
2847 0, 0, 0, 0, 0, 0, 0, 0];
2848 let (e0, e1, e2, e3, e4, e5, e6, e7) = top_pixels(&im, 0, 1, 8);
2849 assert_eq!(e0, 1);
2850 assert_eq!(e1, 2);
2851 assert_eq!(e2, 3);
2852 assert_eq!(e3, 4);
2853 assert_eq!(e4, 5);
2854 assert_eq!(e5, 6);
2855 assert_eq!(e6, 7);
2856 assert_eq!(e7, 8);
2857 }
2858
2859 #[test]
2860 fn test_add_residue() {
2861 let mut pblock = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
2862 let rblock = [
2863 -1, -2, -3, -4, 250, 249, 248, 250, -10, -18, -192, -17, -3, 15, 18, 9,
2864 ];
2865 let expected: [u8; 16] = [0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 10, 29, 33, 25];
2866
2867 add_residue(&mut pblock, &rblock, 0, 0, 4);
2868
2869 for (&e, &i) in expected.iter().zip(&pblock) {
2870 assert_eq!(e, i);
2871 }
2872 }
2873
2874 #[test]
2875 fn test_predict_bhepred() {
2876 #[rustfmt::skip]
2877 let expected: Vec<u8> = vec![5, 0, 0, 0, 0,
2878 4, 4, 4, 4, 4,
2879 3, 3, 3, 3, 3,
2880 2, 2, 2, 2, 2,
2881 1, 1, 1, 1, 1];
2882
2883 #[rustfmt::skip]
2884 let mut im = vec![5, 0, 0, 0, 0,
2885 4, 0, 0, 0, 0,
2886 3, 0, 0, 0, 0,
2887 2, 0, 0, 0, 0,
2888 1, 0, 0, 0, 0];
2889 predict_bhepred(&mut im, 1, 1, 5);
2890 for (&e, i) in expected.iter().zip(im) {
2891 assert_eq!(e, i);
2892 }
2893 }
2894
2895 #[test]
2896 fn test_predict_brdpred() {
2897 #[rustfmt::skip]
2898 let expected: Vec<u8> = vec![5, 6, 7, 8, 9,
2899 4, 5, 6, 7, 8,
2900 3, 4, 5, 6, 7,
2901 2, 3, 4, 5, 6,
2902 1, 2, 3, 4, 5];
2903
2904 #[rustfmt::skip]
2905 let mut im = vec![5, 6, 7, 8, 9,
2906 4, 0, 0, 0, 0,
2907 3, 0, 0, 0, 0,
2908 2, 0, 0, 0, 0,
2909 1, 0, 0, 0, 0];
2910 predict_brdpred(&mut im, 1, 1, 5);
2911 for (&e, i) in expected.iter().zip(im) {
2912 assert_eq!(e, i);
2913 }
2914 }
2915
2916 #[test]
2917 fn test_predict_bldpred() {
2918 #[rustfmt::skip]
2919 let mut im: Vec<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8,
2920 0, 0, 0, 0, 0, 0, 0, 0,
2921 0, 0, 0, 0, 0, 0, 0, 0,
2922 0, 0, 0, 0, 0, 0, 0, 0,
2923 0, 0, 0, 0, 0, 0, 0, 0,
2924 0, 0, 0, 0, 0, 0, 0, 0,
2925 0, 0, 0, 0, 0, 0, 0, 0,
2926 0, 0, 0, 0, 0, 0, 0, 0,
2927 0, 0, 0, 0, 0, 0, 0, 0];
2928 let avg_1 = 2u8;
2929 let avg_2 = 3u8;
2930 let avg_3 = 4u8;
2931 let avg_4 = 5u8;
2932 let avg_5 = 6u8;
2933 let avg_6 = 7u8;
2934 let avg_7 = 8u8;
2935
2936 predict_bldpred(&mut im, 0, 1, 8);
2937
2938 assert_eq!(im[8], avg_1);
2939 assert_eq!(im[9], avg_2);
2940 assert_eq!(im[10], avg_3);
2941 assert_eq!(im[11], avg_4);
2942 assert_eq!(im[16], avg_2);
2943 assert_eq!(im[17], avg_3);
2944 assert_eq!(im[18], avg_4);
2945 assert_eq!(im[19], avg_5);
2946 assert_eq!(im[24], avg_3);
2947 assert_eq!(im[25], avg_4);
2948 assert_eq!(im[26], avg_5);
2949 assert_eq!(im[27], avg_6);
2950 assert_eq!(im[32], avg_4);
2951 assert_eq!(im[33], avg_5);
2952 assert_eq!(im[34], avg_6);
2953 assert_eq!(im[35], avg_7);
2954 }
2955
2956 #[test]
2957 fn test_predict_bvepred() {
2958 #[rustfmt::skip]
2959 let mut im: Vec<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9,
2960 0, 0, 0, 0, 0, 0, 0, 0, 0,
2961 0, 0, 0, 0, 0, 0, 0, 0, 0,
2962 0, 0, 0, 0, 0, 0, 0, 0, 0,
2963 0, 0, 0, 0, 0, 0, 0, 0, 0,
2964 0, 0, 0, 0, 0, 0, 0, 0, 0,
2965 0, 0, 0, 0, 0, 0, 0, 0, 0,
2966 0, 0, 0, 0, 0, 0, 0, 0, 0,
2967 0, 0, 0, 0, 0, 0, 0, 0, 0];
2968 let avg_1 = 2u8;
2969 let avg_2 = 3u8;
2970 let avg_3 = 4u8;
2971 let avg_4 = 5u8;
2972
2973 predict_bvepred(&mut im, 1, 1, 9);
2974
2975 assert_eq!(im[10], avg_1);
2976 assert_eq!(im[11], avg_2);
2977 assert_eq!(im[12], avg_3);
2978 assert_eq!(im[13], avg_4);
2979 assert_eq!(im[19], avg_1);
2980 assert_eq!(im[20], avg_2);
2981 assert_eq!(im[21], avg_3);
2982 assert_eq!(im[22], avg_4);
2983 assert_eq!(im[28], avg_1);
2984 assert_eq!(im[29], avg_2);
2985 assert_eq!(im[30], avg_3);
2986 assert_eq!(im[31], avg_4);
2987 assert_eq!(im[37], avg_1);
2988 assert_eq!(im[38], avg_2);
2989 assert_eq!(im[39], avg_3);
2990 assert_eq!(im[40], avg_4);
2991 }
2992}
2993