Coverage Report

Created: 2026-02-26 07:34

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