Skip to main content

atmos/os_lib/webp/
vp8.rs

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