image_webp/
vp8.rs

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 = -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::UNINIT; M];
138    let mut i = 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::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
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::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
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 = (width + 15) / 16;
2219
2220    let mb = 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::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::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 = y0 * stride + x0;
2304    for row in rblock.chunks(4) {
2305        for (p, &a) 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, curr) = a.split_at_mut(stride * y0);
2341    let above_slice = &above[x0..];
2342
2343    for curr_chunk in curr.chunks_exact_mut(stride).take(size) {
2344        for (curr, &above) 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 in a.chunks_exact_mut(stride).skip(y0).take(size) {
2353        let left = chunk[x0 - 1];
2354        chunk[x0..].iter_mut().for_each(|a| *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 = 4;
2426
2427    a[(y0 - 1) * stride + x0..][..4]
2428        .iter()
2429        .for_each(|&a| v += u32::from(a));
2430
2431    for i in 0usize..4 {
2432        v += u32::from(a[(y0 + i) * stride + x0 - 1]);
2433    }
2434
2435    v >>= 3;
2436    for chunk in a.chunks_exact_mut(stride).skip(y0).take(4) {
2437        for ch 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 = (y0 - 1) * stride + x0;
2449    let a_slice = &a[pos..pos + 8];
2450    let a0 = a_slice[0];
2451    let a1 = a_slice[1];
2452    let a2 = a_slice[2];
2453    let a3 = a_slice[3];
2454    let a4 = a_slice[4];
2455    let a5 = a_slice[5];
2456    let a6 = a_slice[6];
2457    let a7 = 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 = a[y0 * stride + x0 - 1];
2464    let l1 = a[(y0 + 1) * stride + x0 - 1];
2465    let l2 = a[(y0 + 2) * stride + x0 - 1];
2466    let l3 = 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 = (y0 - 1) * stride + x0 - 1;
2478    let a_slice = &a[pos..=pos + 4];
2479    let e0 = a[pos + 4 * stride];
2480    let e1 = a[pos + 3 * stride];
2481    let e2 = a[pos + 2 * stride];
2482    let e3 = a[pos + stride];
2483    let e4 = a_slice[0];
2484    let e5 = a_slice[1];
2485    let e6 = a_slice[2];
2486    let e7 = a_slice[3];
2487    let e8 = 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 = topleft_pixel(a, x0, y0, stride);
2494    let (a0, a1, a2, a3, a4, ..) = top_pixels(a, x0, y0, stride);
2495    let avg_1 = avg3(p, a0, a1);
2496    let avg_2 = avg3(a0, a1, a2);
2497    let avg_3 = avg3(a1, a2, a3);
2498    let avg_4 = avg3(a2, a3, a4);
2499
2500    let avg = [avg_1, avg_2, avg_3, avg_4];
2501
2502    let mut pos = 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 = topleft_pixel(a, x0, y0, stride);
2511    let (l0, l1, l2, l3) = left_pixels(a, x0, y0, stride);
2512
2513    let avgs = [
2514        avg3(p, l0, l1),
2515        avg3(l0, l1, l2),
2516        avg3(l1, l2, l3),
2517        avg3(l2, l3, l3),
2518    ];
2519
2520    let mut pos = y0 * stride + x0;
2521    for avg in avgs {
2522        for a_p 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, a1, a2, a3, a4, a5, a6, a7) = top_pixels(a, x0, y0, stride);
2531
2532    let avgs = [
2533        avg3(a0, a1, a2),
2534        avg3(a1, a2, a3),
2535        avg3(a2, a3, a4),
2536        avg3(a3, a4, a5),
2537        avg3(a4, a5, a6),
2538        avg3(a5, a6, a7),
2539        avg3(a6, a7, a7),
2540    ];
2541
2542    let mut pos = y0 * stride + x0;
2543
2544    for i 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, e1, e2, e3, e4, e5, e6, e7, e8) = edge_pixels(a, x0, y0, stride);
2552
2553    let avgs = [
2554        avg3(e0, e1, e2),
2555        avg3(e1, e2, e3),
2556        avg3(e2, e3, e4),
2557        avg3(e3, e4, e5),
2558        avg3(e4, e5, e6),
2559        avg3(e5, e6, e7),
2560        avg3(e6, e7, e8),
2561    ];
2562    let mut pos = y0 * stride + x0;
2563
2564    for i 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, e2, e3, e4, e5, e6, e7, e8) = edge_pixels(a, x0, y0, stride);
2572
2573    a[(y0 + 3) * stride + x0] = avg3(e1, e2, e3);
2574    a[(y0 + 2) * stride + x0] = avg3(e2, e3, e4);
2575    a[(y0 + 3) * stride + x0 + 1] = avg3(e3, e4, e5);
2576    a[(y0 + 1) * stride + x0] = avg3(e3, e4, e5);
2577    a[(y0 + 2) * stride + x0 + 1] = avg2(e4, e5);
2578    a[y0 * stride + x0] = avg2(e4, e5);
2579    a[(y0 + 3) * stride + x0 + 2] = avg3(e4, e5, e6);
2580    a[(y0 + 1) * stride + x0 + 1] = avg3(e4, e5, e6);
2581    a[(y0 + 2) * stride + x0 + 2] = avg2(e5, e6);
2582    a[y0 * stride + x0 + 1] = avg2(e5, e6);
2583    a[(y0 + 3) * stride + x0 + 3] = avg3(e5, e6, e7);
2584    a[(y0 + 1) * stride + x0 + 2] = avg3(e5, e6, e7);
2585    a[(y0 + 2) * stride + x0 + 3] = avg2(e6, e7);
2586    a[y0 * stride + x0 + 2] = avg2(e6, e7);
2587    a[(y0 + 1) * stride + x0 + 3] = avg3(e6, e7, e8);
2588    a[y0 * stride + x0 + 3] = avg2(e7, e8);
2589}
2590
2591fn predict_bvlpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2592    let (a0, a1, a2, a3, a4, a5, a6, a7) = top_pixels(a, x0, y0, stride);
2593
2594    a[y0 * stride + x0] = avg2(a0, a1);
2595    a[(y0 + 1) * stride + x0] = avg3(a0, a1, a2);
2596    a[(y0 + 2) * stride + x0] = avg2(a1, a2);
2597    a[y0 * stride + x0 + 1] = avg2(a1, a2);
2598    a[(y0 + 1) * stride + x0 + 1] = avg3(a1, a2, a3);
2599    a[(y0 + 3) * stride + x0] = avg3(a1, a2, a3);
2600    a[(y0 + 2) * stride + x0 + 1] = avg2(a2, a3);
2601    a[y0 * stride + x0 + 2] = avg2(a2, a3);
2602    a[(y0 + 3) * stride + x0 + 1] = avg3(a2, a3, a4);
2603    a[(y0 + 1) * stride + x0 + 2] = avg3(a2, a3, a4);
2604    a[(y0 + 2) * stride + x0 + 2] = avg2(a3, a4);
2605    a[y0 * stride + x0 + 3] = avg2(a3, a4);
2606    a[(y0 + 3) * stride + x0 + 2] = avg3(a3, a4, a5);
2607    a[(y0 + 1) * stride + x0 + 3] = avg3(a3, a4, a5);
2608    a[(y0 + 2) * stride + x0 + 3] = avg3(a4, a5, a6);
2609    a[(y0 + 3) * stride + x0 + 3] = avg3(a5, a6, a7);
2610}
2611
2612fn predict_bhdpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2613    let (e0, e1, e2, e3, e4, e5, e6, e7, _) = edge_pixels(a, x0, y0, stride);
2614
2615    a[(y0 + 3) * stride + x0] = avg2(e0, e1);
2616    a[(y0 + 3) * stride + x0 + 1] = avg3(e0, e1, e2);
2617    a[(y0 + 2) * stride + x0] = avg2(e1, e2);
2618    a[(y0 + 3) * stride + x0 + 2] = avg2(e1, e2);
2619    a[(y0 + 2) * stride + x0 + 1] = avg3(e1, e2, e3);
2620    a[(y0 + 3) * stride + x0 + 3] = avg3(e1, e2, e3);
2621    a[(y0 + 2) * stride + x0 + 2] = avg2(e2, e3);
2622    a[(y0 + 1) * stride + x0] = avg2(e2, e3);
2623    a[(y0 + 2) * stride + x0 + 3] = avg3(e2, e3, e4);
2624    a[(y0 + 1) * stride + x0 + 1] = avg3(e2, e3, e4);
2625    a[(y0 + 1) * stride + x0 + 2] = avg2(e3, e4);
2626    a[y0 * stride + x0] = avg2(e3, e4);
2627    a[(y0 + 1) * stride + x0 + 3] = avg3(e3, e4, e5);
2628    a[y0 * stride + x0 + 1] = avg3(e3, e4, e5);
2629    a[y0 * stride + x0 + 2] = avg3(e4, e5, e6);
2630    a[y0 * stride + x0 + 3] = avg3(e5, e6, e7);
2631}
2632
2633fn predict_bhupred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2634    let (l0, l1, l2, l3) = left_pixels(a, x0, y0, stride);
2635
2636    a[y0 * stride + x0] = avg2(l0, l1);
2637    a[y0 * stride + x0 + 1] = avg3(l0, l1, l2);
2638    a[y0 * stride + x0 + 2] = avg2(l1, l2);
2639    a[(y0 + 1) * stride + x0] = avg2(l1, l2);
2640    a[y0 * stride + x0 + 3] = avg3(l1, l2, l3);
2641    a[(y0 + 1) * stride + x0 + 1] = avg3(l1, l2, l3);
2642    a[(y0 + 1) * stride + x0 + 2] = avg2(l2, l3);
2643    a[(y0 + 2) * stride + x0] = avg2(l2, l3);
2644    a[(y0 + 1) * stride + x0 + 3] = avg3(l2, l3, l3);
2645    a[(y0 + 2) * stride + x0 + 1] = avg3(l2, l3, 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}