Coverage Report

Created: 2026-01-22 07:28

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