Coverage Report

Created: 2025-11-09 06:56

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
37.6M
    pub(crate) const fn value_from_branch(t: u8) -> i8 {
126
37.6M
        (t & !0x80) as i8
127
37.6M
    }
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
721
    const fn buffer_width(&self) -> u16 {
811
721
        let difference = self.width % 16;
812
721
        if difference > 0 {
813
624
            self.width + (16 - difference % 16)
814
        } else {
815
97
            self.width
816
        }
817
721
    }
818
819
    /// Fills an rgb buffer from the YUV buffers
820
285
    pub(crate) fn fill_rgb(&self, buf: &mut [u8], upsampling_method: UpsamplingMethod) {
821
        const BPP: usize = 3;
822
823
285
        match upsampling_method {
824
285
            UpsamplingMethod::Bilinear => {
825
285
                yuv::fill_rgb_buffer_fancy::<BPP>(
826
285
                    buf,
827
285
                    &self.ybuf,
828
285
                    &self.ubuf,
829
285
                    &self.vbuf,
830
285
                    usize::from(self.width),
831
285
                    usize::from(self.height),
832
285
                    usize::from(self.buffer_width()),
833
285
                );
834
285
            }
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
285
    }
848
849
    /// Fills an rgba buffer from the YUV buffers
850
436
    pub(crate) fn fill_rgba(&self, buf: &mut [u8], upsampling_method: UpsamplingMethod) {
851
        const BPP: usize = 4;
852
853
436
        match upsampling_method {
854
436
            UpsamplingMethod::Bilinear => {
855
436
                yuv::fill_rgb_buffer_fancy::<BPP>(
856
436
                    buf,
857
436
                    &self.ybuf,
858
436
                    &self.ubuf,
859
436
                    &self.vbuf,
860
436
                    usize::from(self.width),
861
436
                    usize::from(self.height),
862
436
                    usize::from(self.buffer_width()),
863
436
                );
864
436
            }
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
436
    }
878
    /// Gets the buffer size
879
    #[must_use]
880
0
    pub fn get_buf_size(&self) -> usize {
881
0
        self.ybuf.len() * 3
882
0
    }
883
}
884
885
#[derive(Clone, Copy, Default)]
886
struct Segment {
887
    ydc: i16,
888
    yac: i16,
889
890
    y2dc: i16,
891
    y2ac: i16,
892
893
    uvdc: i16,
894
    uvac: i16,
895
896
    delta_values: bool,
897
898
    quantizer_level: i8,
899
    loopfilter_level: i8,
900
}
901
902
/// VP8 Decoder
903
///
904
/// Only decodes keyframes
905
pub struct Vp8Decoder<R> {
906
    r: R,
907
    b: ArithmeticDecoder,
908
909
    mbwidth: u16,
910
    mbheight: u16,
911
    macroblocks: Vec<MacroBlock>,
912
913
    frame: Frame,
914
915
    segments_enabled: bool,
916
    segments_update_map: bool,
917
    segment: [Segment; MAX_SEGMENTS],
918
919
    loop_filter_adjustments_enabled: bool,
920
    ref_delta: [i32; 4],
921
    mode_delta: [i32; 4],
922
923
    partitions: [ArithmeticDecoder; 8],
924
    num_partitions: u8,
925
926
    segment_tree_nodes: [TreeNode; 3],
927
    token_probs: Box<TokenProbTreeNodes>,
928
929
    // Section 9.10
930
    prob_intra: Prob,
931
932
    // Section 9.11
933
    prob_skip_false: Option<Prob>,
934
935
    top: Vec<MacroBlock>,
936
    left: MacroBlock,
937
938
    // The borders from the previous macroblock, used for predictions
939
    // See Section 12
940
    // Note that the left border contains the top left pixel
941
    top_border_y: Vec<u8>,
942
    left_border_y: Vec<u8>,
943
944
    top_border_u: Vec<u8>,
945
    left_border_u: Vec<u8>,
946
947
    top_border_v: Vec<u8>,
948
    left_border_v: Vec<u8>,
949
}
950
951
impl<R: Read> Vp8Decoder<R> {
952
    /// Create a new decoder.
953
    /// The reader must present a raw vp8 bitstream to the decoder
954
1.34k
    fn new(r: R) -> Self {
955
1.34k
        let f = Frame::default();
956
1.34k
        let s = Segment::default();
957
1.34k
        let m = MacroBlock::default();
958
959
1.34k
        Self {
960
1.34k
            r,
961
1.34k
            b: ArithmeticDecoder::new(),
962
1.34k
963
1.34k
            mbwidth: 0,
964
1.34k
            mbheight: 0,
965
1.34k
            macroblocks: Vec::new(),
966
1.34k
967
1.34k
            frame: f,
968
1.34k
            segments_enabled: false,
969
1.34k
            segments_update_map: false,
970
1.34k
            segment: [s; MAX_SEGMENTS],
971
1.34k
972
1.34k
            loop_filter_adjustments_enabled: false,
973
1.34k
            ref_delta: [0; 4],
974
1.34k
            mode_delta: [0; 4],
975
1.34k
976
1.34k
            partitions: [
977
1.34k
                ArithmeticDecoder::new(),
978
1.34k
                ArithmeticDecoder::new(),
979
1.34k
                ArithmeticDecoder::new(),
980
1.34k
                ArithmeticDecoder::new(),
981
1.34k
                ArithmeticDecoder::new(),
982
1.34k
                ArithmeticDecoder::new(),
983
1.34k
                ArithmeticDecoder::new(),
984
1.34k
                ArithmeticDecoder::new(),
985
1.34k
            ],
986
1.34k
987
1.34k
            num_partitions: 1,
988
1.34k
989
1.34k
            segment_tree_nodes: SEGMENT_TREE_NODE_DEFAULTS,
990
1.34k
            token_probs: Box::new(COEFF_PROB_NODES),
991
1.34k
992
1.34k
            // Section 9.10
993
1.34k
            prob_intra: 0u8,
994
1.34k
995
1.34k
            // Section 9.11
996
1.34k
            prob_skip_false: None,
997
1.34k
998
1.34k
            top: Vec::new(),
999
1.34k
            left: m,
1000
1.34k
1001
1.34k
            top_border_y: Vec::new(),
1002
1.34k
            left_border_y: Vec::new(),
1003
1.34k
1004
1.34k
            top_border_u: Vec::new(),
1005
1.34k
            left_border_u: Vec::new(),
1006
1.34k
1007
1.34k
            top_border_v: Vec::new(),
1008
1.34k
            left_border_v: Vec::new(),
1009
1.34k
        }
1010
1.34k
    }
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Line
Count
Source
954
813
    fn new(r: R) -> Self {
955
813
        let f = Frame::default();
956
813
        let s = Segment::default();
957
813
        let m = MacroBlock::default();
958
959
813
        Self {
960
813
            r,
961
813
            b: ArithmeticDecoder::new(),
962
813
963
813
            mbwidth: 0,
964
813
            mbheight: 0,
965
813
            macroblocks: Vec::new(),
966
813
967
813
            frame: f,
968
813
            segments_enabled: false,
969
813
            segments_update_map: false,
970
813
            segment: [s; MAX_SEGMENTS],
971
813
972
813
            loop_filter_adjustments_enabled: false,
973
813
            ref_delta: [0; 4],
974
813
            mode_delta: [0; 4],
975
813
976
813
            partitions: [
977
813
                ArithmeticDecoder::new(),
978
813
                ArithmeticDecoder::new(),
979
813
                ArithmeticDecoder::new(),
980
813
                ArithmeticDecoder::new(),
981
813
                ArithmeticDecoder::new(),
982
813
                ArithmeticDecoder::new(),
983
813
                ArithmeticDecoder::new(),
984
813
                ArithmeticDecoder::new(),
985
813
            ],
986
813
987
813
            num_partitions: 1,
988
813
989
813
            segment_tree_nodes: SEGMENT_TREE_NODE_DEFAULTS,
990
813
            token_probs: Box::new(COEFF_PROB_NODES),
991
813
992
813
            // Section 9.10
993
813
            prob_intra: 0u8,
994
813
995
813
            // Section 9.11
996
813
            prob_skip_false: None,
997
813
998
813
            top: Vec::new(),
999
813
            left: m,
1000
813
1001
813
            top_border_y: Vec::new(),
1002
813
            left_border_y: Vec::new(),
1003
813
1004
813
            top_border_u: Vec::new(),
1005
813
            left_border_u: Vec::new(),
1006
813
1007
813
            top_border_v: Vec::new(),
1008
813
            left_border_v: Vec::new(),
1009
813
        }
1010
813
    }
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::new
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Line
Count
Source
954
535
    fn new(r: R) -> Self {
955
535
        let f = Frame::default();
956
535
        let s = Segment::default();
957
535
        let m = MacroBlock::default();
958
959
535
        Self {
960
535
            r,
961
535
            b: ArithmeticDecoder::new(),
962
535
963
535
            mbwidth: 0,
964
535
            mbheight: 0,
965
535
            macroblocks: Vec::new(),
966
535
967
535
            frame: f,
968
535
            segments_enabled: false,
969
535
            segments_update_map: false,
970
535
            segment: [s; MAX_SEGMENTS],
971
535
972
535
            loop_filter_adjustments_enabled: false,
973
535
            ref_delta: [0; 4],
974
535
            mode_delta: [0; 4],
975
535
976
535
            partitions: [
977
535
                ArithmeticDecoder::new(),
978
535
                ArithmeticDecoder::new(),
979
535
                ArithmeticDecoder::new(),
980
535
                ArithmeticDecoder::new(),
981
535
                ArithmeticDecoder::new(),
982
535
                ArithmeticDecoder::new(),
983
535
                ArithmeticDecoder::new(),
984
535
                ArithmeticDecoder::new(),
985
535
            ],
986
535
987
535
            num_partitions: 1,
988
535
989
535
            segment_tree_nodes: SEGMENT_TREE_NODE_DEFAULTS,
990
535
            token_probs: Box::new(COEFF_PROB_NODES),
991
535
992
535
            // Section 9.10
993
535
            prob_intra: 0u8,
994
535
995
535
            // Section 9.11
996
535
            prob_skip_false: None,
997
535
998
535
            top: Vec::new(),
999
535
            left: m,
1000
535
1001
535
            top_border_y: Vec::new(),
1002
535
            left_border_y: Vec::new(),
1003
535
1004
535
            top_border_u: Vec::new(),
1005
535
            left_border_u: Vec::new(),
1006
535
1007
535
            top_border_v: Vec::new(),
1008
535
            left_border_v: Vec::new(),
1009
535
        }
1010
535
    }
1011
1012
1.23k
    fn update_token_probabilities(&mut self) -> Result<(), DecodingError> {
1013
1.23k
        let mut res = self.b.start_accumulated_result();
1014
4.95k
        for (i, is) in COEFF_UPDATE_PROBS.iter().enumerate() {
1015
39.6k
            for (j, js) in is.iter().enumerate() {
1016
118k
                for (k, ks) in js.iter().enumerate() {
1017
1.30M
                    for (t, prob) in ks.iter().enumerate().take(NUM_DCT_TOKENS - 1) {
1018
1.30M
                        if self.b.read_bool(*prob).or_accumulate(&mut res) {
1019
31.9k
                            let v = self.b.read_literal(8).or_accumulate(&mut res);
1020
31.9k
                            self.token_probs[i][j][k][t].prob = v;
1021
1.27M
                        }
1022
                    }
1023
                }
1024
            }
1025
        }
1026
1.23k
        self.b.check(res, ())
1027
1.23k
    }
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::update_token_probabilities
Line
Count
Source
1012
729
    fn update_token_probabilities(&mut self) -> Result<(), DecodingError> {
1013
729
        let mut res = self.b.start_accumulated_result();
1014
2.91k
        for (i, is) in COEFF_UPDATE_PROBS.iter().enumerate() {
1015
23.3k
            for (j, js) in is.iter().enumerate() {
1016
69.9k
                for (k, ks) in js.iter().enumerate() {
1017
769k
                    for (t, prob) in ks.iter().enumerate().take(NUM_DCT_TOKENS - 1) {
1018
769k
                        if self.b.read_bool(*prob).or_accumulate(&mut res) {
1019
23.4k
                            let v = self.b.read_literal(8).or_accumulate(&mut res);
1020
23.4k
                            self.token_probs[i][j][k][t].prob = v;
1021
746k
                        }
1022
                    }
1023
                }
1024
            }
1025
        }
1026
729
        self.b.check(res, ())
1027
729
    }
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::update_token_probabilities
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::update_token_probabilities
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::update_token_probabilities
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::update_token_probabilities
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::update_token_probabilities
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::update_token_probabilities
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::update_token_probabilities
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::update_token_probabilities
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::update_token_probabilities
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::update_token_probabilities
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::update_token_probabilities
Line
Count
Source
1012
510
    fn update_token_probabilities(&mut self) -> Result<(), DecodingError> {
1013
510
        let mut res = self.b.start_accumulated_result();
1014
2.04k
        for (i, is) in COEFF_UPDATE_PROBS.iter().enumerate() {
1015
16.3k
            for (j, js) in is.iter().enumerate() {
1016
48.9k
                for (k, ks) in js.iter().enumerate() {
1017
538k
                    for (t, prob) in ks.iter().enumerate().take(NUM_DCT_TOKENS - 1) {
1018
538k
                        if self.b.read_bool(*prob).or_accumulate(&mut res) {
1019
8.47k
                            let v = self.b.read_literal(8).or_accumulate(&mut res);
1020
8.47k
                            self.token_probs[i][j][k][t].prob = v;
1021
530k
                        }
1022
                    }
1023
                }
1024
            }
1025
        }
1026
510
        self.b.check(res, ())
1027
510
    }
1028
1029
1.32k
    fn init_partitions(&mut self, n: usize) -> Result<(), DecodingError> {
1030
1.32k
        if n > 1 {
1031
38
            let mut sizes = vec![0; 3 * n - 3];
1032
38
            self.r.read_exact(sizes.as_mut_slice())?;
1033
1034
93
            for (i, s) in sizes.chunks(3).enumerate() {
1035
93
                let size = { s }
1036
93
                    .read_u24::<LittleEndian>()
1037
93
                    .expect("Reading from &[u8] can't fail and the chunk is complete");
1038
1039
93
                let size = size as usize;
1040
93
                let mut buf = vec![[0; 4]; size.div_ceil(4)];
1041
93
                let bytes: &mut [u8] = buf.as_mut_slice().as_flattened_mut();
1042
93
                self.r.read_exact(&mut bytes[..size])?;
1043
69
                self.partitions[i].init(buf, size)?;
1044
            }
1045
1.28k
        }
1046
1047
1.29k
        let mut buf = Vec::new();
1048
1.29k
        self.r.read_to_end(&mut buf)?;
1049
1.29k
        let size = buf.len();
1050
1.29k
        let mut chunks = vec![[0; 4]; size.div_ceil(4)];
1051
1.29k
        chunks.as_mut_slice().as_flattened_mut()[..size].copy_from_slice(&buf);
1052
1.29k
        self.partitions[n - 1].init(chunks, size)?;
1053
1054
1.29k
        Ok(())
1055
1.32k
    }
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::init_partitions
Line
Count
Source
1029
802
    fn init_partitions(&mut self, n: usize) -> Result<(), DecodingError> {
1030
802
        if n > 1 {
1031
30
            let mut sizes = vec![0; 3 * n - 3];
1032
30
            self.r.read_exact(sizes.as_mut_slice())?;
1033
1034
62
            for (i, s) in sizes.chunks(3).enumerate() {
1035
62
                let size = { s }
1036
62
                    .read_u24::<LittleEndian>()
1037
62
                    .expect("Reading from &[u8] can't fail and the chunk is complete");
1038
1039
62
                let size = size as usize;
1040
62
                let mut buf = vec![[0; 4]; size.div_ceil(4)];
1041
62
                let bytes: &mut [u8] = buf.as_mut_slice().as_flattened_mut();
1042
62
                self.r.read_exact(&mut bytes[..size])?;
1043
44
                self.partitions[i].init(buf, size)?;
1044
            }
1045
772
        }
1046
1047
783
        let mut buf = Vec::new();
1048
783
        self.r.read_to_end(&mut buf)?;
1049
783
        let size = buf.len();
1050
783
        let mut chunks = vec![[0; 4]; size.div_ceil(4)];
1051
783
        chunks.as_mut_slice().as_flattened_mut()[..size].copy_from_slice(&buf);
1052
783
        self.partitions[n - 1].init(chunks, size)?;
1053
1054
783
        Ok(())
1055
802
    }
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::init_partitions
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::init_partitions
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::init_partitions
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::init_partitions
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::init_partitions
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::init_partitions
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::init_partitions
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::init_partitions
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::init_partitions
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::init_partitions
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::init_partitions
Line
Count
Source
1029
518
    fn init_partitions(&mut self, n: usize) -> Result<(), DecodingError> {
1030
518
        if n > 1 {
1031
8
            let mut sizes = vec![0; 3 * n - 3];
1032
8
            self.r.read_exact(sizes.as_mut_slice())?;
1033
1034
31
            for (i, s) in sizes.chunks(3).enumerate() {
1035
31
                let size = { s }
1036
31
                    .read_u24::<LittleEndian>()
1037
31
                    .expect("Reading from &[u8] can't fail and the chunk is complete");
1038
1039
31
                let size = size as usize;
1040
31
                let mut buf = vec![[0; 4]; size.div_ceil(4)];
1041
31
                let bytes: &mut [u8] = buf.as_mut_slice().as_flattened_mut();
1042
31
                self.r.read_exact(&mut bytes[..size])?;
1043
25
                self.partitions[i].init(buf, size)?;
1044
            }
1045
510
        }
1046
1047
512
        let mut buf = Vec::new();
1048
512
        self.r.read_to_end(&mut buf)?;
1049
512
        let size = buf.len();
1050
512
        let mut chunks = vec![[0; 4]; size.div_ceil(4)];
1051
512
        chunks.as_mut_slice().as_flattened_mut()[..size].copy_from_slice(&buf);
1052
512
        self.partitions[n - 1].init(chunks, size)?;
1053
1054
512
        Ok(())
1055
518
    }
1056
1057
1.29k
    fn read_quantization_indices(&mut self) -> Result<(), DecodingError> {
1058
7.56k
        fn dc_quant(index: i32) -> i16 {
1059
7.56k
            DC_QUANT[index.clamp(0, 127) as usize]
1060
7.56k
        }
1061
1062
7.56k
        fn ac_quant(index: i32) -> i16 {
1063
7.56k
            AC_QUANT[index.clamp(0, 127) as usize]
1064
7.56k
        }
1065
1066
1.29k
        let mut res = self.b.start_accumulated_result();
1067
1068
1.29k
        let yac_abs = self.b.read_literal(7).or_accumulate(&mut res);
1069
1.29k
        let ydc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1070
1.29k
        let y2dc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1071
1.29k
        let y2ac_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1072
1.29k
        let uvdc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1073
1.29k
        let uvac_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1074
1075
1.29k
        let n = if self.segments_enabled {
1076
409
            MAX_SEGMENTS
1077
        } else {
1078
886
            1
1079
        };
1080
2.52k
        for i in 0usize..n {
1081
2.52k
            let base = i32::from(if self.segments_enabled {
1082
1.63k
                if self.segment[i].delta_values {
1083
384
                    i16::from(self.segment[i].quantizer_level) + i16::from(yac_abs)
1084
                } else {
1085
1.25k
                    i16::from(self.segment[i].quantizer_level)
1086
                }
1087
            } else {
1088
886
                i16::from(yac_abs)
1089
            });
1090
1091
2.52k
            self.segment[i].ydc = dc_quant(base + ydc_delta);
1092
2.52k
            self.segment[i].yac = ac_quant(base);
1093
1094
2.52k
            self.segment[i].y2dc = dc_quant(base + y2dc_delta) * 2;
1095
            // The intermediate result (max`284*155`) can be larger than the `i16` range.
1096
2.52k
            self.segment[i].y2ac = (i32::from(ac_quant(base + y2ac_delta)) * 155 / 100) as i16;
1097
1098
2.52k
            self.segment[i].uvdc = dc_quant(base + uvdc_delta);
1099
2.52k
            self.segment[i].uvac = ac_quant(base + uvac_delta);
1100
1101
2.52k
            if self.segment[i].y2ac < 8 {
1102
791
                self.segment[i].y2ac = 8;
1103
1.73k
            }
1104
1105
2.52k
            if self.segment[i].uvdc > 132 {
1106
214
                self.segment[i].uvdc = 132;
1107
2.30k
            }
1108
        }
1109
1110
1.29k
        self.b.check(res, ())
1111
1.29k
    }
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_quantization_indices
Line
Count
Source
1057
783
    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
783
        let mut res = self.b.start_accumulated_result();
1067
1068
783
        let yac_abs = self.b.read_literal(7).or_accumulate(&mut res);
1069
783
        let ydc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1070
783
        let y2dc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1071
783
        let y2ac_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1072
783
        let uvdc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1073
783
        let uvac_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1074
1075
783
        let n = if self.segments_enabled {
1076
248
            MAX_SEGMENTS
1077
        } else {
1078
535
            1
1079
        };
1080
1.52k
        for i in 0usize..n {
1081
1.52k
            let base = i32::from(if self.segments_enabled {
1082
992
                if self.segment[i].delta_values {
1083
284
                    i16::from(self.segment[i].quantizer_level) + i16::from(yac_abs)
1084
                } else {
1085
708
                    i16::from(self.segment[i].quantizer_level)
1086
                }
1087
            } else {
1088
535
                i16::from(yac_abs)
1089
            });
1090
1091
1.52k
            self.segment[i].ydc = dc_quant(base + ydc_delta);
1092
1.52k
            self.segment[i].yac = ac_quant(base);
1093
1094
1.52k
            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
1.52k
            self.segment[i].y2ac = (i32::from(ac_quant(base + y2ac_delta)) * 155 / 100) as i16;
1097
1098
1.52k
            self.segment[i].uvdc = dc_quant(base + uvdc_delta);
1099
1.52k
            self.segment[i].uvac = ac_quant(base + uvac_delta);
1100
1101
1.52k
            if self.segment[i].y2ac < 8 {
1102
532
                self.segment[i].y2ac = 8;
1103
995
            }
1104
1105
1.52k
            if self.segment[i].uvdc > 132 {
1106
86
                self.segment[i].uvdc = 132;
1107
1.44k
            }
1108
        }
1109
1110
783
        self.b.check(res, ())
1111
783
    }
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::read_quantization_indices
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_quantization_indices
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_quantization_indices
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_quantization_indices
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_quantization_indices
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_quantization_indices
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_quantization_indices
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_quantization_indices
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_quantization_indices
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_quantization_indices
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_quantization_indices
Line
Count
Source
1057
512
    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
512
        let mut res = self.b.start_accumulated_result();
1067
1068
512
        let yac_abs = self.b.read_literal(7).or_accumulate(&mut res);
1069
512
        let ydc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1070
512
        let y2dc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1071
512
        let y2ac_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1072
512
        let uvdc_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1073
512
        let uvac_delta = self.b.read_optional_signed_value(4).or_accumulate(&mut res);
1074
1075
512
        let n = if self.segments_enabled {
1076
161
            MAX_SEGMENTS
1077
        } else {
1078
351
            1
1079
        };
1080
995
        for i in 0usize..n {
1081
995
            let base = i32::from(if self.segments_enabled {
1082
644
                if self.segment[i].delta_values {
1083
100
                    i16::from(self.segment[i].quantizer_level) + i16::from(yac_abs)
1084
                } else {
1085
544
                    i16::from(self.segment[i].quantizer_level)
1086
                }
1087
            } else {
1088
351
                i16::from(yac_abs)
1089
            });
1090
1091
995
            self.segment[i].ydc = dc_quant(base + ydc_delta);
1092
995
            self.segment[i].yac = ac_quant(base);
1093
1094
995
            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
995
            self.segment[i].y2ac = (i32::from(ac_quant(base + y2ac_delta)) * 155 / 100) as i16;
1097
1098
995
            self.segment[i].uvdc = dc_quant(base + uvdc_delta);
1099
995
            self.segment[i].uvac = ac_quant(base + uvac_delta);
1100
1101
995
            if self.segment[i].y2ac < 8 {
1102
259
                self.segment[i].y2ac = 8;
1103
736
            }
1104
1105
995
            if self.segment[i].uvdc > 132 {
1106
128
                self.segment[i].uvdc = 132;
1107
867
            }
1108
        }
1109
1110
512
        self.b.check(res, ())
1111
512
    }
1112
1113
270
    fn read_loop_filter_adjustments(&mut self) -> Result<(), DecodingError> {
1114
270
        let mut res = self.b.start_accumulated_result();
1115
1116
270
        if self.b.read_flag().or_accumulate(&mut res) {
1117
970
            for i in 0usize..4 {
1118
776
                self.ref_delta[i] = self.b.read_optional_signed_value(6).or_accumulate(&mut res);
1119
776
            }
1120
1121
970
            for i in 0usize..4 {
1122
776
                self.mode_delta[i] = self.b.read_optional_signed_value(6).or_accumulate(&mut res);
1123
776
            }
1124
76
        }
1125
1126
270
        self.b.check(res, ())
1127
270
    }
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_loop_filter_adjustments
Line
Count
Source
1113
163
    fn read_loop_filter_adjustments(&mut self) -> Result<(), DecodingError> {
1114
163
        let mut res = self.b.start_accumulated_result();
1115
1116
163
        if self.b.read_flag().or_accumulate(&mut res) {
1117
560
            for i in 0usize..4 {
1118
448
                self.ref_delta[i] = self.b.read_optional_signed_value(6).or_accumulate(&mut res);
1119
448
            }
1120
1121
560
            for i in 0usize..4 {
1122
448
                self.mode_delta[i] = self.b.read_optional_signed_value(6).or_accumulate(&mut res);
1123
448
            }
1124
51
        }
1125
1126
163
        self.b.check(res, ())
1127
163
    }
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::read_loop_filter_adjustments
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_loop_filter_adjustments
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_loop_filter_adjustments
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_loop_filter_adjustments
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_loop_filter_adjustments
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_loop_filter_adjustments
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_loop_filter_adjustments
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_loop_filter_adjustments
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_loop_filter_adjustments
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_loop_filter_adjustments
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_loop_filter_adjustments
Line
Count
Source
1113
107
    fn read_loop_filter_adjustments(&mut self) -> Result<(), DecodingError> {
1114
107
        let mut res = self.b.start_accumulated_result();
1115
1116
107
        if self.b.read_flag().or_accumulate(&mut res) {
1117
410
            for i in 0usize..4 {
1118
328
                self.ref_delta[i] = self.b.read_optional_signed_value(6).or_accumulate(&mut res);
1119
328
            }
1120
1121
410
            for i in 0usize..4 {
1122
328
                self.mode_delta[i] = self.b.read_optional_signed_value(6).or_accumulate(&mut res);
1123
328
            }
1124
25
        }
1125
1126
107
        self.b.check(res, ())
1127
107
    }
1128
1129
429
    fn read_segment_updates(&mut self) -> Result<(), DecodingError> {
1130
429
        let mut res = self.b.start_accumulated_result();
1131
1132
        // Section 9.3
1133
429
        self.segments_update_map = self.b.read_flag().or_accumulate(&mut res);
1134
429
        let update_segment_feature_data = self.b.read_flag().or_accumulate(&mut res);
1135
1136
429
        if update_segment_feature_data {
1137
397
            let segment_feature_mode = self.b.read_flag().or_accumulate(&mut res);
1138
1139
1.98k
            for i in 0usize..MAX_SEGMENTS {
1140
1.58k
                self.segment[i].delta_values = !segment_feature_mode;
1141
1.58k
            }
1142
1143
1.98k
            for i in 0usize..MAX_SEGMENTS {
1144
1.58k
                self.segment[i].quantizer_level =
1145
1.58k
                    self.b.read_optional_signed_value(7).or_accumulate(&mut res) as i8;
1146
1.58k
            }
1147
1148
1.98k
            for i in 0usize..MAX_SEGMENTS {
1149
1.58k
                self.segment[i].loopfilter_level =
1150
1.58k
                    self.b.read_optional_signed_value(6).or_accumulate(&mut res) as i8;
1151
1.58k
            }
1152
32
        }
1153
1154
429
        if self.segments_update_map {
1155
1.36k
            for i in 0usize..3 {
1156
1.02k
                let update = self.b.read_flag().or_accumulate(&mut res);
1157
1158
1.02k
                let prob = if update {
1159
685
                    self.b.read_literal(8).or_accumulate(&mut res)
1160
                } else {
1161
338
                    255
1162
                };
1163
1.02k
                self.segment_tree_nodes[i].prob = prob;
1164
            }
1165
88
        }
1166
1167
429
        self.b.check(res, ())
1168
429
    }
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_segment_updates
Line
Count
Source
1129
251
    fn read_segment_updates(&mut self) -> Result<(), DecodingError> {
1130
251
        let mut res = self.b.start_accumulated_result();
1131
1132
        // Section 9.3
1133
251
        self.segments_update_map = self.b.read_flag().or_accumulate(&mut res);
1134
251
        let update_segment_feature_data = self.b.read_flag().or_accumulate(&mut res);
1135
1136
251
        if update_segment_feature_data {
1137
230
            let segment_feature_mode = self.b.read_flag().or_accumulate(&mut res);
1138
1139
1.15k
            for i in 0usize..MAX_SEGMENTS {
1140
920
                self.segment[i].delta_values = !segment_feature_mode;
1141
920
            }
1142
1143
1.15k
            for i in 0usize..MAX_SEGMENTS {
1144
920
                self.segment[i].quantizer_level =
1145
920
                    self.b.read_optional_signed_value(7).or_accumulate(&mut res) as i8;
1146
920
            }
1147
1148
1.15k
            for i in 0usize..MAX_SEGMENTS {
1149
920
                self.segment[i].loopfilter_level =
1150
920
                    self.b.read_optional_signed_value(6).or_accumulate(&mut res) as i8;
1151
920
            }
1152
21
        }
1153
1154
251
        if self.segments_update_map {
1155
792
            for i in 0usize..3 {
1156
594
                let update = self.b.read_flag().or_accumulate(&mut res);
1157
1158
594
                let prob = if update {
1159
370
                    self.b.read_literal(8).or_accumulate(&mut res)
1160
                } else {
1161
224
                    255
1162
                };
1163
594
                self.segment_tree_nodes[i].prob = prob;
1164
            }
1165
53
        }
1166
1167
251
        self.b.check(res, ())
1168
251
    }
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::read_segment_updates
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_segment_updates
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_segment_updates
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_segment_updates
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_segment_updates
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_segment_updates
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_segment_updates
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_segment_updates
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_segment_updates
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_segment_updates
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_segment_updates
Line
Count
Source
1129
178
    fn read_segment_updates(&mut self) -> Result<(), DecodingError> {
1130
178
        let mut res = self.b.start_accumulated_result();
1131
1132
        // Section 9.3
1133
178
        self.segments_update_map = self.b.read_flag().or_accumulate(&mut res);
1134
178
        let update_segment_feature_data = self.b.read_flag().or_accumulate(&mut res);
1135
1136
178
        if update_segment_feature_data {
1137
167
            let segment_feature_mode = self.b.read_flag().or_accumulate(&mut res);
1138
1139
835
            for i in 0usize..MAX_SEGMENTS {
1140
668
                self.segment[i].delta_values = !segment_feature_mode;
1141
668
            }
1142
1143
835
            for i in 0usize..MAX_SEGMENTS {
1144
668
                self.segment[i].quantizer_level =
1145
668
                    self.b.read_optional_signed_value(7).or_accumulate(&mut res) as i8;
1146
668
            }
1147
1148
835
            for i in 0usize..MAX_SEGMENTS {
1149
668
                self.segment[i].loopfilter_level =
1150
668
                    self.b.read_optional_signed_value(6).or_accumulate(&mut res) as i8;
1151
668
            }
1152
11
        }
1153
1154
178
        if self.segments_update_map {
1155
572
            for i in 0usize..3 {
1156
429
                let update = self.b.read_flag().or_accumulate(&mut res);
1157
1158
429
                let prob = if update {
1159
315
                    self.b.read_literal(8).or_accumulate(&mut res)
1160
                } else {
1161
114
                    255
1162
                };
1163
429
                self.segment_tree_nodes[i].prob = prob;
1164
            }
1165
35
        }
1166
1167
178
        self.b.check(res, ())
1168
178
    }
1169
1170
1.34k
    fn read_frame_header(&mut self) -> Result<(), DecodingError> {
1171
1.34k
        let tag = self.r.read_u24::<LittleEndian>()?;
1172
1173
1.34k
        self.frame.keyframe = tag & 1 == 0;
1174
1.34k
        self.frame.version = ((tag >> 1) & 7) as u8;
1175
1.34k
        self.frame.for_display = (tag >> 4) & 1 != 0;
1176
1177
1.34k
        let first_partition_size = tag >> 5;
1178
1179
1.34k
        if self.frame.keyframe {
1180
1.32k
            let mut tag = [0u8; 3];
1181
1.32k
            self.r.read_exact(&mut tag)?;
1182
1183
1.32k
            if tag != [0x9d, 0x01, 0x2a] {
1184
2
                return Err(DecodingError::Vp8MagicInvalid(tag));
1185
1.32k
            }
1186
1187
1.32k
            let w = self.r.read_u16::<LittleEndian>()?;
1188
1.32k
            let h = self.r.read_u16::<LittleEndian>()?;
1189
1190
1.32k
            self.frame.width = w & 0x3FFF;
1191
1.32k
            self.frame.height = h & 0x3FFF;
1192
1193
1.32k
            self.top = init_top_macroblocks(self.frame.width as usize);
1194
            // Almost always the first macro block, except when non exists (i.e. `width == 0`)
1195
1.32k
            self.left = self.top.first().copied().unwrap_or_default();
1196
1197
1.32k
            self.mbwidth = self.frame.width.div_ceil(16);
1198
1.32k
            self.mbheight = self.frame.height.div_ceil(16);
1199
1200
1.32k
            self.frame.ybuf =
1201
1.32k
                vec![0u8; usize::from(self.mbwidth) * 16 * usize::from(self.mbheight) * 16];
1202
1.32k
            self.frame.ubuf =
1203
1.32k
                vec![0u8; usize::from(self.mbwidth) * 8 * usize::from(self.mbheight) * 8];
1204
1.32k
            self.frame.vbuf =
1205
1.32k
                vec![0u8; usize::from(self.mbwidth) * 8 * usize::from(self.mbheight) * 8];
1206
1207
1.32k
            self.top_border_y = vec![127u8; self.frame.width as usize + 4 + 16];
1208
1.32k
            self.left_border_y = vec![129u8; 1 + 16];
1209
1210
            // 8 pixels per macroblock
1211
1.32k
            self.top_border_u = vec![127u8; 8 * self.mbwidth as usize];
1212
1.32k
            self.left_border_u = vec![129u8; 1 + 8];
1213
1214
1.32k
            self.top_border_v = vec![127u8; 8 * self.mbwidth as usize];
1215
1.32k
            self.left_border_v = vec![129u8; 1 + 8];
1216
20
        }
1217
1218
1.34k
        let size = first_partition_size as usize;
1219
1.34k
        let mut buf = vec![[0; 4]; size.div_ceil(4)];
1220
1.34k
        let bytes: &mut [u8] = buf.as_mut_slice().as_flattened_mut();
1221
1.34k
        self.r.read_exact(&mut bytes[..size])?;
1222
1223
        // initialise binary decoder
1224
1.33k
        self.b.init(buf, size)?;
1225
1226
1.33k
        let mut res = self.b.start_accumulated_result();
1227
1.33k
        if self.frame.keyframe {
1228
1.31k
            let color_space = self.b.read_literal(1).or_accumulate(&mut res);
1229
1.31k
            self.frame.pixel_type = self.b.read_literal(1).or_accumulate(&mut res);
1230
1231
1.31k
            if color_space != 0 {
1232
0
                return Err(DecodingError::ColorSpaceInvalid(color_space));
1233
1.31k
            }
1234
20
        }
1235
1236
1.33k
        self.segments_enabled = self.b.read_flag().or_accumulate(&mut res);
1237
1.33k
        if self.segments_enabled {
1238
429
            self.read_segment_updates()?;
1239
907
        }
1240
1241
1.33k
        self.frame.filter_type = self.b.read_flag().or_accumulate(&mut res);
1242
1.33k
        self.frame.filter_level = self.b.read_literal(6).or_accumulate(&mut res);
1243
1.33k
        self.frame.sharpness_level = self.b.read_literal(3).or_accumulate(&mut res);
1244
1245
1.33k
        self.loop_filter_adjustments_enabled = self.b.read_flag().or_accumulate(&mut res);
1246
1.33k
        if self.loop_filter_adjustments_enabled {
1247
270
            self.read_loop_filter_adjustments()?;
1248
1.06k
        }
1249
1250
1.32k
        let num_partitions = 1 << self.b.read_literal(2).or_accumulate(&mut res) as usize;
1251
1.32k
        self.b.check(res, ())?;
1252
1253
1.32k
        self.num_partitions = num_partitions as u8;
1254
1.32k
        self.init_partitions(num_partitions)?;
1255
1256
1.29k
        self.read_quantization_indices()?;
1257
1258
1.24k
        if !self.frame.keyframe {
1259
            // 9.7 refresh golden frame and altref frame
1260
            // FIXME: support this?
1261
1
            return Err(DecodingError::UnsupportedFeature(
1262
1
                "Non-keyframe frames".to_owned(),
1263
1
            ));
1264
1.23k
        }
1265
1266
        // Refresh entropy probs ?????
1267
1.23k
        let _ = self.b.read_literal(1);
1268
1269
1.23k
        self.update_token_probabilities()?;
1270
1271
1.22k
        let mut res = self.b.start_accumulated_result();
1272
1.22k
        let mb_no_skip_coeff = self.b.read_literal(1).or_accumulate(&mut res);
1273
1.22k
        self.prob_skip_false = if mb_no_skip_coeff == 1 {
1274
457
            Some(self.b.read_literal(8).or_accumulate(&mut res))
1275
        } else {
1276
763
            None
1277
        };
1278
1.22k
        self.b.check(res, ())?;
1279
1280
1.22k
        if !self.frame.keyframe {
1281
            // 9.10 remaining frame data
1282
0
            self.prob_intra = 0;
1283
1284
            // FIXME: support this?
1285
0
            return Err(DecodingError::UnsupportedFeature(
1286
0
                "Non-keyframe frames".to_owned(),
1287
0
            ));
1288
1.22k
        } else {
1289
1.22k
            // Reset motion vectors
1290
1.22k
        }
1291
1292
1.22k
        Ok(())
1293
1.34k
    }
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_frame_header
Line
Count
Source
1170
813
    fn read_frame_header(&mut self) -> Result<(), DecodingError> {
1171
813
        let tag = self.r.read_u24::<LittleEndian>()?;
1172
1173
813
        self.frame.keyframe = tag & 1 == 0;
1174
813
        self.frame.version = ((tag >> 1) & 7) as u8;
1175
813
        self.frame.for_display = (tag >> 4) & 1 != 0;
1176
1177
813
        let first_partition_size = tag >> 5;
1178
1179
813
        if self.frame.keyframe {
1180
812
            let mut tag = [0u8; 3];
1181
812
            self.r.read_exact(&mut tag)?;
1182
1183
812
            if tag != [0x9d, 0x01, 0x2a] {
1184
2
                return Err(DecodingError::Vp8MagicInvalid(tag));
1185
810
            }
1186
1187
810
            let w = self.r.read_u16::<LittleEndian>()?;
1188
810
            let h = self.r.read_u16::<LittleEndian>()?;
1189
1190
810
            self.frame.width = w & 0x3FFF;
1191
810
            self.frame.height = h & 0x3FFF;
1192
1193
810
            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
810
            self.left = self.top.first().copied().unwrap_or_default();
1196
1197
810
            self.mbwidth = self.frame.width.div_ceil(16);
1198
810
            self.mbheight = self.frame.height.div_ceil(16);
1199
1200
810
            self.frame.ybuf =
1201
810
                vec![0u8; usize::from(self.mbwidth) * 16 * usize::from(self.mbheight) * 16];
1202
810
            self.frame.ubuf =
1203
810
                vec![0u8; usize::from(self.mbwidth) * 8 * usize::from(self.mbheight) * 8];
1204
810
            self.frame.vbuf =
1205
810
                vec![0u8; usize::from(self.mbwidth) * 8 * usize::from(self.mbheight) * 8];
1206
1207
810
            self.top_border_y = vec![127u8; self.frame.width as usize + 4 + 16];
1208
810
            self.left_border_y = vec![129u8; 1 + 16];
1209
1210
            // 8 pixels per macroblock
1211
810
            self.top_border_u = vec![127u8; 8 * self.mbwidth as usize];
1212
810
            self.left_border_u = vec![129u8; 1 + 8];
1213
1214
810
            self.top_border_v = vec![127u8; 8 * self.mbwidth as usize];
1215
810
            self.left_border_v = vec![129u8; 1 + 8];
1216
1
        }
1217
1218
811
        let size = first_partition_size as usize;
1219
811
        let mut buf = vec![[0; 4]; size.div_ceil(4)];
1220
811
        let bytes: &mut [u8] = buf.as_mut_slice().as_flattened_mut();
1221
811
        self.r.read_exact(&mut bytes[..size])?;
1222
1223
        // initialise binary decoder
1224
802
        self.b.init(buf, size)?;
1225
1226
802
        let mut res = self.b.start_accumulated_result();
1227
802
        if self.frame.keyframe {
1228
801
            let color_space = self.b.read_literal(1).or_accumulate(&mut res);
1229
801
            self.frame.pixel_type = self.b.read_literal(1).or_accumulate(&mut res);
1230
1231
801
            if color_space != 0 {
1232
0
                return Err(DecodingError::ColorSpaceInvalid(color_space));
1233
801
            }
1234
1
        }
1235
1236
802
        self.segments_enabled = self.b.read_flag().or_accumulate(&mut res);
1237
802
        if self.segments_enabled {
1238
251
            self.read_segment_updates()?;
1239
551
        }
1240
1241
802
        self.frame.filter_type = self.b.read_flag().or_accumulate(&mut res);
1242
802
        self.frame.filter_level = self.b.read_literal(6).or_accumulate(&mut res);
1243
802
        self.frame.sharpness_level = self.b.read_literal(3).or_accumulate(&mut res);
1244
1245
802
        self.loop_filter_adjustments_enabled = self.b.read_flag().or_accumulate(&mut res);
1246
802
        if self.loop_filter_adjustments_enabled {
1247
163
            self.read_loop_filter_adjustments()?;
1248
639
        }
1249
1250
802
        let num_partitions = 1 << self.b.read_literal(2).or_accumulate(&mut res) as usize;
1251
802
        self.b.check(res, ())?;
1252
1253
802
        self.num_partitions = num_partitions as u8;
1254
802
        self.init_partitions(num_partitions)?;
1255
1256
783
        self.read_quantization_indices()?;
1257
1258
730
        if !self.frame.keyframe {
1259
            // 9.7 refresh golden frame and altref frame
1260
            // FIXME: support this?
1261
1
            return Err(DecodingError::UnsupportedFeature(
1262
1
                "Non-keyframe frames".to_owned(),
1263
1
            ));
1264
729
        }
1265
1266
        // Refresh entropy probs ?????
1267
729
        let _ = self.b.read_literal(1);
1268
1269
729
        self.update_token_probabilities()?;
1270
1271
716
        let mut res = self.b.start_accumulated_result();
1272
716
        let mb_no_skip_coeff = self.b.read_literal(1).or_accumulate(&mut res);
1273
716
        self.prob_skip_false = if mb_no_skip_coeff == 1 {
1274
285
            Some(self.b.read_literal(8).or_accumulate(&mut res))
1275
        } else {
1276
431
            None
1277
        };
1278
716
        self.b.check(res, ())?;
1279
1280
716
        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
716
        } else {
1289
716
            // Reset motion vectors
1290
716
        }
1291
1292
716
        Ok(())
1293
813
    }
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::read_frame_header
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_frame_header
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_frame_header
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_frame_header
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_frame_header
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_frame_header
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_frame_header
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_frame_header
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_frame_header
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_frame_header
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_frame_header
Line
Count
Source
1170
535
    fn read_frame_header(&mut self) -> Result<(), DecodingError> {
1171
535
        let tag = self.r.read_u24::<LittleEndian>()?;
1172
1173
534
        self.frame.keyframe = tag & 1 == 0;
1174
534
        self.frame.version = ((tag >> 1) & 7) as u8;
1175
534
        self.frame.for_display = (tag >> 4) & 1 != 0;
1176
1177
534
        let first_partition_size = tag >> 5;
1178
1179
534
        if self.frame.keyframe {
1180
515
            let mut tag = [0u8; 3];
1181
515
            self.r.read_exact(&mut tag)?;
1182
1183
515
            if tag != [0x9d, 0x01, 0x2a] {
1184
0
                return Err(DecodingError::Vp8MagicInvalid(tag));
1185
515
            }
1186
1187
515
            let w = self.r.read_u16::<LittleEndian>()?;
1188
515
            let h = self.r.read_u16::<LittleEndian>()?;
1189
1190
515
            self.frame.width = w & 0x3FFF;
1191
515
            self.frame.height = h & 0x3FFF;
1192
1193
515
            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
515
            self.left = self.top.first().copied().unwrap_or_default();
1196
1197
515
            self.mbwidth = self.frame.width.div_ceil(16);
1198
515
            self.mbheight = self.frame.height.div_ceil(16);
1199
1200
515
            self.frame.ybuf =
1201
515
                vec![0u8; usize::from(self.mbwidth) * 16 * usize::from(self.mbheight) * 16];
1202
515
            self.frame.ubuf =
1203
515
                vec![0u8; usize::from(self.mbwidth) * 8 * usize::from(self.mbheight) * 8];
1204
515
            self.frame.vbuf =
1205
515
                vec![0u8; usize::from(self.mbwidth) * 8 * usize::from(self.mbheight) * 8];
1206
1207
515
            self.top_border_y = vec![127u8; self.frame.width as usize + 4 + 16];
1208
515
            self.left_border_y = vec![129u8; 1 + 16];
1209
1210
            // 8 pixels per macroblock
1211
515
            self.top_border_u = vec![127u8; 8 * self.mbwidth as usize];
1212
515
            self.left_border_u = vec![129u8; 1 + 8];
1213
1214
515
            self.top_border_v = vec![127u8; 8 * self.mbwidth as usize];
1215
515
            self.left_border_v = vec![129u8; 1 + 8];
1216
19
        }
1217
1218
534
        let size = first_partition_size as usize;
1219
534
        let mut buf = vec![[0; 4]; size.div_ceil(4)];
1220
534
        let bytes: &mut [u8] = buf.as_mut_slice().as_flattened_mut();
1221
534
        self.r.read_exact(&mut bytes[..size])?;
1222
1223
        // initialise binary decoder
1224
534
        self.b.init(buf, size)?;
1225
1226
534
        let mut res = self.b.start_accumulated_result();
1227
534
        if self.frame.keyframe {
1228
515
            let color_space = self.b.read_literal(1).or_accumulate(&mut res);
1229
515
            self.frame.pixel_type = self.b.read_literal(1).or_accumulate(&mut res);
1230
1231
515
            if color_space != 0 {
1232
0
                return Err(DecodingError::ColorSpaceInvalid(color_space));
1233
515
            }
1234
19
        }
1235
1236
534
        self.segments_enabled = self.b.read_flag().or_accumulate(&mut res);
1237
534
        if self.segments_enabled {
1238
178
            self.read_segment_updates()?;
1239
356
        }
1240
1241
534
        self.frame.filter_type = self.b.read_flag().or_accumulate(&mut res);
1242
534
        self.frame.filter_level = self.b.read_literal(6).or_accumulate(&mut res);
1243
534
        self.frame.sharpness_level = self.b.read_literal(3).or_accumulate(&mut res);
1244
1245
534
        self.loop_filter_adjustments_enabled = self.b.read_flag().or_accumulate(&mut res);
1246
534
        if self.loop_filter_adjustments_enabled {
1247
107
            self.read_loop_filter_adjustments()?;
1248
427
        }
1249
1250
520
        let num_partitions = 1 << self.b.read_literal(2).or_accumulate(&mut res) as usize;
1251
520
        self.b.check(res, ())?;
1252
1253
518
        self.num_partitions = num_partitions as u8;
1254
518
        self.init_partitions(num_partitions)?;
1255
1256
512
        self.read_quantization_indices()?;
1257
1258
510
        if !self.frame.keyframe {
1259
            // 9.7 refresh golden frame and altref frame
1260
            // FIXME: support this?
1261
0
            return Err(DecodingError::UnsupportedFeature(
1262
0
                "Non-keyframe frames".to_owned(),
1263
0
            ));
1264
510
        }
1265
1266
        // Refresh entropy probs ?????
1267
510
        let _ = self.b.read_literal(1);
1268
1269
510
        self.update_token_probabilities()?;
1270
1271
504
        let mut res = self.b.start_accumulated_result();
1272
504
        let mb_no_skip_coeff = self.b.read_literal(1).or_accumulate(&mut res);
1273
504
        self.prob_skip_false = if mb_no_skip_coeff == 1 {
1274
172
            Some(self.b.read_literal(8).or_accumulate(&mut res))
1275
        } else {
1276
332
            None
1277
        };
1278
504
        self.b.check(res, ())?;
1279
1280
504
        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
504
        } else {
1289
504
            // Reset motion vectors
1290
504
        }
1291
1292
504
        Ok(())
1293
535
    }
1294
1295
2.15M
    fn read_macroblock_header(&mut self, mbx: usize) -> Result<MacroBlock, DecodingError> {
1296
2.15M
        let mut mb = MacroBlock::default();
1297
2.15M
        let mut res = self.b.start_accumulated_result();
1298
1299
2.15M
        if self.segments_enabled && self.segments_update_map {
1300
1.17M
            mb.segmentid =
1301
1.17M
                (self.b.read_with_tree(&self.segment_tree_nodes)).or_accumulate(&mut res) as u8;
1302
1.17M
        };
1303
1304
2.15M
        mb.coeffs_skipped = if let Some(prob) = self.prob_skip_false {
1305
1.90M
            self.b.read_bool(prob).or_accumulate(&mut res)
1306
        } else {
1307
253k
            false
1308
        };
1309
1310
2.15M
        let inter_predicted = if !self.frame.keyframe {
1311
0
            self.b.read_bool(self.prob_intra).or_accumulate(&mut res)
1312
        } else {
1313
2.15M
            false
1314
        };
1315
1316
2.15M
        if inter_predicted {
1317
0
            return Err(DecodingError::UnsupportedFeature(
1318
0
                "VP8 inter-prediction".to_owned(),
1319
0
            ));
1320
2.15M
        }
1321
1322
2.15M
        if self.frame.keyframe {
1323
            // intra prediction
1324
2.15M
            let luma = (self.b.read_with_tree(&KEYFRAME_YMODE_NODES)).or_accumulate(&mut res);
1325
            mb.luma_mode =
1326
2.15M
                LumaMode::from_i8(luma).ok_or(DecodingError::LumaPredictionModeInvalid(luma))?;
1327
1328
2.15M
            match mb.luma_mode.into_intra() {
1329
                // `LumaMode::B` - This is predicted individually
1330
                None => {
1331
5.01M
                    for y in 0usize..4 {
1332
20.0M
                        for x in 0usize..4 {
1333
16.0M
                            let top = self.top[mbx].bpred[12 + x];
1334
16.0M
                            let left = self.left.bpred[y];
1335
16.0M
                            let intra = self.b.read_with_tree(
1336
16.0M
                                &KEYFRAME_BPRED_MODE_NODES[top as usize][left as usize],
1337
                            );
1338
16.0M
                            let intra = intra.or_accumulate(&mut res);
1339
16.0M
                            let bmode = IntraMode::from_i8(intra)
1340
16.0M
                                .ok_or(DecodingError::IntraPredictionModeInvalid(intra))?;
1341
16.0M
                            mb.bpred[x + y * 4] = bmode;
1342
1343
16.0M
                            self.top[mbx].bpred[12 + x] = bmode;
1344
16.0M
                            self.left.bpred[y] = bmode;
1345
                        }
1346
                    }
1347
                }
1348
1.15M
                Some(mode) => {
1349
5.77M
                    for i in 0usize..4 {
1350
4.62M
                        mb.bpred[12 + i] = mode;
1351
4.62M
                        self.left.bpred[i] = mode;
1352
4.62M
                    }
1353
                }
1354
            }
1355
1356
2.15M
            let chroma = (self.b.read_with_tree(&KEYFRAME_UV_MODE_NODES)).or_accumulate(&mut res);
1357
2.15M
            mb.chroma_mode = ChromaMode::from_i8(chroma)
1358
2.15M
                .ok_or(DecodingError::ChromaPredictionModeInvalid(chroma))?;
1359
0
        }
1360
1361
2.15M
        self.top[mbx].chroma_mode = mb.chroma_mode;
1362
2.15M
        self.top[mbx].luma_mode = mb.luma_mode;
1363
2.15M
        self.top[mbx].bpred = mb.bpred;
1364
1365
2.15M
        self.b.check(res, mb)
1366
2.15M
    }
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_macroblock_header
Line
Count
Source
1295
2.00M
    fn read_macroblock_header(&mut self, mbx: usize) -> Result<MacroBlock, DecodingError> {
1296
2.00M
        let mut mb = MacroBlock::default();
1297
2.00M
        let mut res = self.b.start_accumulated_result();
1298
1299
2.00M
        if self.segments_enabled && self.segments_update_map {
1300
1.14M
            mb.segmentid =
1301
1.14M
                (self.b.read_with_tree(&self.segment_tree_nodes)).or_accumulate(&mut res) as u8;
1302
1.14M
        };
1303
1304
2.00M
        mb.coeffs_skipped = if let Some(prob) = self.prob_skip_false {
1305
1.80M
            self.b.read_bool(prob).or_accumulate(&mut res)
1306
        } else {
1307
194k
            false
1308
        };
1309
1310
2.00M
        let inter_predicted = if !self.frame.keyframe {
1311
0
            self.b.read_bool(self.prob_intra).or_accumulate(&mut res)
1312
        } else {
1313
2.00M
            false
1314
        };
1315
1316
2.00M
        if inter_predicted {
1317
0
            return Err(DecodingError::UnsupportedFeature(
1318
0
                "VP8 inter-prediction".to_owned(),
1319
0
            ));
1320
2.00M
        }
1321
1322
2.00M
        if self.frame.keyframe {
1323
            // intra prediction
1324
2.00M
            let luma = (self.b.read_with_tree(&KEYFRAME_YMODE_NODES)).or_accumulate(&mut res);
1325
            mb.luma_mode =
1326
2.00M
                LumaMode::from_i8(luma).ok_or(DecodingError::LumaPredictionModeInvalid(luma))?;
1327
1328
2.00M
            match mb.luma_mode.into_intra() {
1329
                // `LumaMode::B` - This is predicted individually
1330
                None => {
1331
4.59M
                    for y in 0usize..4 {
1332
18.3M
                        for x in 0usize..4 {
1333
14.6M
                            let top = self.top[mbx].bpred[12 + x];
1334
14.6M
                            let left = self.left.bpred[y];
1335
14.6M
                            let intra = self.b.read_with_tree(
1336
14.6M
                                &KEYFRAME_BPRED_MODE_NODES[top as usize][left as usize],
1337
                            );
1338
14.6M
                            let intra = intra.or_accumulate(&mut res);
1339
14.6M
                            let bmode = IntraMode::from_i8(intra)
1340
14.6M
                                .ok_or(DecodingError::IntraPredictionModeInvalid(intra))?;
1341
14.6M
                            mb.bpred[x + y * 4] = bmode;
1342
1343
14.6M
                            self.top[mbx].bpred[12 + x] = bmode;
1344
14.6M
                            self.left.bpred[y] = bmode;
1345
                        }
1346
                    }
1347
                }
1348
1.08M
                Some(mode) => {
1349
5.41M
                    for i in 0usize..4 {
1350
4.33M
                        mb.bpred[12 + i] = mode;
1351
4.33M
                        self.left.bpred[i] = mode;
1352
4.33M
                    }
1353
                }
1354
            }
1355
1356
2.00M
            let chroma = (self.b.read_with_tree(&KEYFRAME_UV_MODE_NODES)).or_accumulate(&mut res);
1357
2.00M
            mb.chroma_mode = ChromaMode::from_i8(chroma)
1358
2.00M
                .ok_or(DecodingError::ChromaPredictionModeInvalid(chroma))?;
1359
0
        }
1360
1361
2.00M
        self.top[mbx].chroma_mode = mb.chroma_mode;
1362
2.00M
        self.top[mbx].luma_mode = mb.luma_mode;
1363
2.00M
        self.top[mbx].bpred = mb.bpred;
1364
1365
2.00M
        self.b.check(res, mb)
1366
2.00M
    }
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::read_macroblock_header
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_macroblock_header
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_macroblock_header
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_macroblock_header
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_macroblock_header
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_macroblock_header
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_macroblock_header
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_macroblock_header
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_macroblock_header
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_macroblock_header
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_macroblock_header
Line
Count
Source
1295
157k
    fn read_macroblock_header(&mut self, mbx: usize) -> Result<MacroBlock, DecodingError> {
1296
157k
        let mut mb = MacroBlock::default();
1297
157k
        let mut res = self.b.start_accumulated_result();
1298
1299
157k
        if self.segments_enabled && self.segments_update_map {
1300
25.6k
            mb.segmentid =
1301
25.6k
                (self.b.read_with_tree(&self.segment_tree_nodes)).or_accumulate(&mut res) as u8;
1302
131k
        };
1303
1304
157k
        mb.coeffs_skipped = if let Some(prob) = self.prob_skip_false {
1305
98.1k
            self.b.read_bool(prob).or_accumulate(&mut res)
1306
        } else {
1307
59.1k
            false
1308
        };
1309
1310
157k
        let inter_predicted = if !self.frame.keyframe {
1311
0
            self.b.read_bool(self.prob_intra).or_accumulate(&mut res)
1312
        } else {
1313
157k
            false
1314
        };
1315
1316
157k
        if inter_predicted {
1317
0
            return Err(DecodingError::UnsupportedFeature(
1318
0
                "VP8 inter-prediction".to_owned(),
1319
0
            ));
1320
157k
        }
1321
1322
157k
        if self.frame.keyframe {
1323
            // intra prediction
1324
157k
            let luma = (self.b.read_with_tree(&KEYFRAME_YMODE_NODES)).or_accumulate(&mut res);
1325
            mb.luma_mode =
1326
157k
                LumaMode::from_i8(luma).ok_or(DecodingError::LumaPredictionModeInvalid(luma))?;
1327
1328
157k
            match mb.luma_mode.into_intra() {
1329
                // `LumaMode::B` - This is predicted individually
1330
                None => {
1331
422k
                    for y in 0usize..4 {
1332
1.68M
                        for x in 0usize..4 {
1333
1.35M
                            let top = self.top[mbx].bpred[12 + x];
1334
1.35M
                            let left = self.left.bpred[y];
1335
1.35M
                            let intra = self.b.read_with_tree(
1336
1.35M
                                &KEYFRAME_BPRED_MODE_NODES[top as usize][left as usize],
1337
                            );
1338
1.35M
                            let intra = intra.or_accumulate(&mut res);
1339
1.35M
                            let bmode = IntraMode::from_i8(intra)
1340
1.35M
                                .ok_or(DecodingError::IntraPredictionModeInvalid(intra))?;
1341
1.35M
                            mb.bpred[x + y * 4] = bmode;
1342
1343
1.35M
                            self.top[mbx].bpred[12 + x] = bmode;
1344
1.35M
                            self.left.bpred[y] = bmode;
1345
                        }
1346
                    }
1347
                }
1348
72.8k
                Some(mode) => {
1349
364k
                    for i in 0usize..4 {
1350
291k
                        mb.bpred[12 + i] = mode;
1351
291k
                        self.left.bpred[i] = mode;
1352
291k
                    }
1353
                }
1354
            }
1355
1356
157k
            let chroma = (self.b.read_with_tree(&KEYFRAME_UV_MODE_NODES)).or_accumulate(&mut res);
1357
157k
            mb.chroma_mode = ChromaMode::from_i8(chroma)
1358
157k
                .ok_or(DecodingError::ChromaPredictionModeInvalid(chroma))?;
1359
0
        }
1360
1361
157k
        self.top[mbx].chroma_mode = mb.chroma_mode;
1362
157k
        self.top[mbx].luma_mode = mb.luma_mode;
1363
157k
        self.top[mbx].bpred = mb.bpred;
1364
1365
157k
        self.b.check(res, mb)
1366
157k
    }
1367
1368
2.15M
    fn intra_predict_luma(&mut self, mbx: usize, mby: usize, mb: &MacroBlock, resdata: &[i32]) {
1369
2.15M
        let stride = 1usize + 16 + 4;
1370
2.15M
        let mw = self.mbwidth as usize;
1371
2.15M
        let mut ws = create_border_luma(mbx, mby, mw, &self.top_border_y, &self.left_border_y);
1372
1373
2.15M
        match mb.luma_mode {
1374
160k
            LumaMode::V => predict_vpred(&mut ws, 16, 1, 1, stride),
1375
263k
            LumaMode::H => predict_hpred(&mut ws, 16, 1, 1, stride),
1376
355k
            LumaMode::TM => predict_tmpred(&mut ws, 16, 1, 1, stride),
1377
376k
            LumaMode::DC => predict_dcpred(&mut ws, 16, stride, mby != 0, mbx != 0),
1378
1.00M
            LumaMode::B => predict_4x4(&mut ws, stride, &mb.bpred, resdata),
1379
        }
1380
1381
2.15M
        if mb.luma_mode != LumaMode::B {
1382
5.77M
            for y in 0usize..4 {
1383
23.1M
                for x in 0usize..4 {
1384
18.4M
                    let i = x + y * 4;
1385
18.4M
                    // Create a reference to a [i32; 16] array for add_residue (slices of size 16 do not work).
1386
18.4M
                    let rb: &[i32; 16] = resdata[i * 16..][..16].try_into().unwrap();
1387
18.4M
                    let y0 = 1 + y * 4;
1388
18.4M
                    let x0 = 1 + x * 4;
1389
18.4M
1390
18.4M
                    add_residue(&mut ws, rb, y0, x0, stride);
1391
18.4M
                }
1392
            }
1393
1.00M
        }
1394
1395
2.15M
        self.left_border_y[0] = ws[16];
1396
1397
34.5M
        for (i, left) in self.left_border_y[1..][..16].iter_mut().enumerate() {
1398
34.5M
            *left = ws[(i + 1) * stride + 16];
1399
34.5M
        }
1400
1401
34.5M
        for (top, &w) in self.top_border_y[mbx * 16..][..16]
1402
2.15M
            .iter_mut()
1403
2.15M
            .zip(&ws[16 * stride + 1..][..16])
1404
34.5M
        {
1405
34.5M
            *top = w;
1406
34.5M
        }
1407
1408
36.6M
        for y in 0usize..16 {
1409
552M
            for (ybuf, &ws) in self.frame.ybuf[(mby * 16 + y) * mw * 16 + mbx * 16..][..16]
1410
34.5M
                .iter_mut()
1411
34.5M
                .zip(ws[(1 + y) * stride + 1..][..16].iter())
1412
552M
            {
1413
552M
                *ybuf = ws;
1414
552M
            }
1415
        }
1416
2.15M
    }
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_luma
Line
Count
Source
1368
2.00M
    fn intra_predict_luma(&mut self, mbx: usize, mby: usize, mb: &MacroBlock, resdata: &[i32]) {
1369
2.00M
        let stride = 1usize + 16 + 4;
1370
2.00M
        let mw = self.mbwidth as usize;
1371
2.00M
        let mut ws = create_border_luma(mbx, mby, mw, &self.top_border_y, &self.left_border_y);
1372
1373
2.00M
        match mb.luma_mode {
1374
148k
            LumaMode::V => predict_vpred(&mut ws, 16, 1, 1, stride),
1375
252k
            LumaMode::H => predict_hpred(&mut ws, 16, 1, 1, stride),
1376
332k
            LumaMode::TM => predict_tmpred(&mut ws, 16, 1, 1, stride),
1377
348k
            LumaMode::DC => predict_dcpred(&mut ws, 16, stride, mby != 0, mbx != 0),
1378
918k
            LumaMode::B => predict_4x4(&mut ws, stride, &mb.bpred, resdata),
1379
        }
1380
1381
2.00M
        if mb.luma_mode != LumaMode::B {
1382
5.41M
            for y in 0usize..4 {
1383
21.6M
                for x in 0usize..4 {
1384
17.3M
                    let i = x + y * 4;
1385
17.3M
                    // Create a reference to a [i32; 16] array for add_residue (slices of size 16 do not work).
1386
17.3M
                    let rb: &[i32; 16] = resdata[i * 16..][..16].try_into().unwrap();
1387
17.3M
                    let y0 = 1 + y * 4;
1388
17.3M
                    let x0 = 1 + x * 4;
1389
17.3M
1390
17.3M
                    add_residue(&mut ws, rb, y0, x0, stride);
1391
17.3M
                }
1392
            }
1393
918k
        }
1394
1395
2.00M
        self.left_border_y[0] = ws[16];
1396
1397
32.0M
        for (i, left) in self.left_border_y[1..][..16].iter_mut().enumerate() {
1398
32.0M
            *left = ws[(i + 1) * stride + 16];
1399
32.0M
        }
1400
1401
32.0M
        for (top, &w) in self.top_border_y[mbx * 16..][..16]
1402
2.00M
            .iter_mut()
1403
2.00M
            .zip(&ws[16 * stride + 1..][..16])
1404
32.0M
        {
1405
32.0M
            *top = w;
1406
32.0M
        }
1407
1408
34.0M
        for y in 0usize..16 {
1409
512M
            for (ybuf, &ws) in self.frame.ybuf[(mby * 16 + y) * mw * 16 + mbx * 16..][..16]
1410
32.0M
                .iter_mut()
1411
32.0M
                .zip(ws[(1 + y) * stride + 1..][..16].iter())
1412
512M
            {
1413
512M
                *ybuf = ws;
1414
512M
            }
1415
        }
1416
2.00M
    }
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::intra_predict_luma
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_luma
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_luma
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_luma
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_luma
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_luma
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_luma
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_luma
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_luma
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_luma
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_luma
Line
Count
Source
1368
157k
    fn intra_predict_luma(&mut self, mbx: usize, mby: usize, mb: &MacroBlock, resdata: &[i32]) {
1369
157k
        let stride = 1usize + 16 + 4;
1370
157k
        let mw = self.mbwidth as usize;
1371
157k
        let mut ws = create_border_luma(mbx, mby, mw, &self.top_border_y, &self.left_border_y);
1372
1373
157k
        match mb.luma_mode {
1374
11.7k
            LumaMode::V => predict_vpred(&mut ws, 16, 1, 1, stride),
1375
10.4k
            LumaMode::H => predict_hpred(&mut ws, 16, 1, 1, stride),
1376
22.4k
            LumaMode::TM => predict_tmpred(&mut ws, 16, 1, 1, stride),
1377
28.1k
            LumaMode::DC => predict_dcpred(&mut ws, 16, stride, mby != 0, mbx != 0),
1378
84.3k
            LumaMode::B => predict_4x4(&mut ws, stride, &mb.bpred, resdata),
1379
        }
1380
1381
157k
        if mb.luma_mode != LumaMode::B {
1382
363k
            for y in 0usize..4 {
1383
1.45M
                for x in 0usize..4 {
1384
1.16M
                    let i = x + y * 4;
1385
1.16M
                    // Create a reference to a [i32; 16] array for add_residue (slices of size 16 do not work).
1386
1.16M
                    let rb: &[i32; 16] = resdata[i * 16..][..16].try_into().unwrap();
1387
1.16M
                    let y0 = 1 + y * 4;
1388
1.16M
                    let x0 = 1 + x * 4;
1389
1.16M
1390
1.16M
                    add_residue(&mut ws, rb, y0, x0, stride);
1391
1.16M
                }
1392
            }
1393
84.3k
        }
1394
1395
157k
        self.left_border_y[0] = ws[16];
1396
1397
2.51M
        for (i, left) in self.left_border_y[1..][..16].iter_mut().enumerate() {
1398
2.51M
            *left = ws[(i + 1) * stride + 16];
1399
2.51M
        }
1400
1401
2.51M
        for (top, &w) in self.top_border_y[mbx * 16..][..16]
1402
157k
            .iter_mut()
1403
157k
            .zip(&ws[16 * stride + 1..][..16])
1404
2.51M
        {
1405
2.51M
            *top = w;
1406
2.51M
        }
1407
1408
2.67M
        for y in 0usize..16 {
1409
40.2M
            for (ybuf, &ws) in self.frame.ybuf[(mby * 16 + y) * mw * 16 + mbx * 16..][..16]
1410
2.51M
                .iter_mut()
1411
2.51M
                .zip(ws[(1 + y) * stride + 1..][..16].iter())
1412
40.2M
            {
1413
40.2M
                *ybuf = ws;
1414
40.2M
            }
1415
        }
1416
157k
    }
1417
1418
2.15M
    fn intra_predict_chroma(&mut self, mbx: usize, mby: usize, mb: &MacroBlock, resdata: &[i32]) {
1419
2.15M
        let stride = 1usize + 8;
1420
1421
2.15M
        let mw = self.mbwidth as usize;
1422
1423
        //8x8 with left top border of 1
1424
2.15M
        let mut uws = create_border_chroma(mbx, mby, &self.top_border_u, &self.left_border_u);
1425
2.15M
        let mut vws = create_border_chroma(mbx, mby, &self.top_border_v, &self.left_border_v);
1426
1427
2.15M
        match mb.chroma_mode {
1428
1.09M
            ChromaMode::DC => {
1429
1.09M
                predict_dcpred(&mut uws, 8, stride, mby != 0, mbx != 0);
1430
1.09M
                predict_dcpred(&mut vws, 8, stride, mby != 0, mbx != 0);
1431
1.09M
            }
1432
365k
            ChromaMode::V => {
1433
365k
                predict_vpred(&mut uws, 8, 1, 1, stride);
1434
365k
                predict_vpred(&mut vws, 8, 1, 1, stride);
1435
365k
            }
1436
284k
            ChromaMode::H => {
1437
284k
                predict_hpred(&mut uws, 8, 1, 1, stride);
1438
284k
                predict_hpred(&mut vws, 8, 1, 1, stride);
1439
284k
            }
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.47M
        for y in 0usize..2 {
1447
12.9M
            for x in 0usize..2 {
1448
8.63M
                let i = x + y * 2;
1449
8.63M
                let urb: &[i32; 16] = resdata[16 * 16 + i * 16..][..16].try_into().unwrap();
1450
8.63M
1451
8.63M
                let y0 = 1 + y * 4;
1452
8.63M
                let x0 = 1 + x * 4;
1453
8.63M
                add_residue(&mut uws, urb, y0, x0, stride);
1454
8.63M
1455
8.63M
                let vrb: &[i32; 16] = resdata[20 * 16 + i * 16..][..16].try_into().unwrap();
1456
8.63M
1457
8.63M
                add_residue(&mut vws, vrb, y0, x0, stride);
1458
8.63M
            }
1459
        }
1460
1461
2.15M
        set_chroma_border(&mut self.left_border_u, &mut self.top_border_u, &uws, mbx);
1462
2.15M
        set_chroma_border(&mut self.left_border_v, &mut self.top_border_v, &vws, mbx);
1463
1464
19.4M
        for y in 0usize..8 {
1465
17.2M
            let uv_buf_index = (mby * 8 + y) * mw * 8 + mbx * 8;
1466
17.2M
            let ws_index = (1 + y) * stride + 1;
1467
1468
138M
            for (((ub, vb), &uw), &vw) in self.frame.ubuf[uv_buf_index..][..8]
1469
17.2M
                .iter_mut()
1470
17.2M
                .zip(self.frame.vbuf[uv_buf_index..][..8].iter_mut())
1471
17.2M
                .zip(uws[ws_index..][..8].iter())
1472
17.2M
                .zip(vws[ws_index..][..8].iter())
1473
138M
            {
1474
138M
                *ub = uw;
1475
138M
                *vb = vw;
1476
138M
            }
1477
        }
1478
2.15M
    }
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_chroma
Line
Count
Source
1418
2.00M
    fn intra_predict_chroma(&mut self, mbx: usize, mby: usize, mb: &MacroBlock, resdata: &[i32]) {
1419
2.00M
        let stride = 1usize + 8;
1420
1421
2.00M
        let mw = self.mbwidth as usize;
1422
1423
        //8x8 with left top border of 1
1424
2.00M
        let mut uws = create_border_chroma(mbx, mby, &self.top_border_u, &self.left_border_u);
1425
2.00M
        let mut vws = create_border_chroma(mbx, mby, &self.top_border_v, &self.left_border_v);
1426
1427
2.00M
        match mb.chroma_mode {
1428
1.00M
            ChromaMode::DC => {
1429
1.00M
                predict_dcpred(&mut uws, 8, stride, mby != 0, mbx != 0);
1430
1.00M
                predict_dcpred(&mut vws, 8, stride, mby != 0, mbx != 0);
1431
1.00M
            }
1432
341k
            ChromaMode::V => {
1433
341k
                predict_vpred(&mut uws, 8, 1, 1, stride);
1434
341k
                predict_vpred(&mut vws, 8, 1, 1, stride);
1435
341k
            }
1436
263k
            ChromaMode::H => {
1437
263k
                predict_hpred(&mut uws, 8, 1, 1, stride);
1438
263k
                predict_hpred(&mut vws, 8, 1, 1, stride);
1439
263k
            }
1440
392k
            ChromaMode::TM => {
1441
392k
                predict_tmpred(&mut uws, 8, 1, 1, stride);
1442
392k
                predict_tmpred(&mut vws, 8, 1, 1, stride);
1443
392k
            }
1444
        }
1445
1446
6.00M
        for y in 0usize..2 {
1447
12.0M
            for x in 0usize..2 {
1448
8.00M
                let i = x + y * 2;
1449
8.00M
                let urb: &[i32; 16] = resdata[16 * 16 + i * 16..][..16].try_into().unwrap();
1450
8.00M
1451
8.00M
                let y0 = 1 + y * 4;
1452
8.00M
                let x0 = 1 + x * 4;
1453
8.00M
                add_residue(&mut uws, urb, y0, x0, stride);
1454
8.00M
1455
8.00M
                let vrb: &[i32; 16] = resdata[20 * 16 + i * 16..][..16].try_into().unwrap();
1456
8.00M
1457
8.00M
                add_residue(&mut vws, vrb, y0, x0, stride);
1458
8.00M
            }
1459
        }
1460
1461
2.00M
        set_chroma_border(&mut self.left_border_u, &mut self.top_border_u, &uws, mbx);
1462
2.00M
        set_chroma_border(&mut self.left_border_v, &mut self.top_border_v, &vws, mbx);
1463
1464
18.0M
        for y in 0usize..8 {
1465
16.0M
            let uv_buf_index = (mby * 8 + y) * mw * 8 + mbx * 8;
1466
16.0M
            let ws_index = (1 + y) * stride + 1;
1467
1468
128M
            for (((ub, vb), &uw), &vw) in self.frame.ubuf[uv_buf_index..][..8]
1469
16.0M
                .iter_mut()
1470
16.0M
                .zip(self.frame.vbuf[uv_buf_index..][..8].iter_mut())
1471
16.0M
                .zip(uws[ws_index..][..8].iter())
1472
16.0M
                .zip(vws[ws_index..][..8].iter())
1473
128M
            {
1474
128M
                *ub = uw;
1475
128M
                *vb = vw;
1476
128M
            }
1477
        }
1478
2.00M
    }
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::intra_predict_chroma
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_chroma
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_chroma
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_chroma
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_chroma
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_chroma
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_chroma
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_chroma
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_chroma
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_chroma
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::intra_predict_chroma
Line
Count
Source
1418
157k
    fn intra_predict_chroma(&mut self, mbx: usize, mby: usize, mb: &MacroBlock, resdata: &[i32]) {
1419
157k
        let stride = 1usize + 8;
1420
1421
157k
        let mw = self.mbwidth as usize;
1422
1423
        //8x8 with left top border of 1
1424
157k
        let mut uws = create_border_chroma(mbx, mby, &self.top_border_u, &self.left_border_u);
1425
157k
        let mut vws = create_border_chroma(mbx, mby, &self.top_border_v, &self.left_border_v);
1426
1427
157k
        match mb.chroma_mode {
1428
91.6k
            ChromaMode::DC => {
1429
91.6k
                predict_dcpred(&mut uws, 8, stride, mby != 0, mbx != 0);
1430
91.6k
                predict_dcpred(&mut vws, 8, stride, mby != 0, mbx != 0);
1431
91.6k
            }
1432
24.2k
            ChromaMode::V => {
1433
24.2k
                predict_vpred(&mut uws, 8, 1, 1, stride);
1434
24.2k
                predict_vpred(&mut vws, 8, 1, 1, stride);
1435
24.2k
            }
1436
20.9k
            ChromaMode::H => {
1437
20.9k
                predict_hpred(&mut uws, 8, 1, 1, stride);
1438
20.9k
                predict_hpred(&mut vws, 8, 1, 1, stride);
1439
20.9k
            }
1440
20.2k
            ChromaMode::TM => {
1441
20.2k
                predict_tmpred(&mut uws, 8, 1, 1, stride);
1442
20.2k
                predict_tmpred(&mut vws, 8, 1, 1, stride);
1443
20.2k
            }
1444
        }
1445
1446
471k
        for y in 0usize..2 {
1447
942k
            for x in 0usize..2 {
1448
628k
                let i = x + y * 2;
1449
628k
                let urb: &[i32; 16] = resdata[16 * 16 + i * 16..][..16].try_into().unwrap();
1450
628k
1451
628k
                let y0 = 1 + y * 4;
1452
628k
                let x0 = 1 + x * 4;
1453
628k
                add_residue(&mut uws, urb, y0, x0, stride);
1454
628k
1455
628k
                let vrb: &[i32; 16] = resdata[20 * 16 + i * 16..][..16].try_into().unwrap();
1456
628k
1457
628k
                add_residue(&mut vws, vrb, y0, x0, stride);
1458
628k
            }
1459
        }
1460
1461
157k
        set_chroma_border(&mut self.left_border_u, &mut self.top_border_u, &uws, mbx);
1462
157k
        set_chroma_border(&mut self.left_border_v, &mut self.top_border_v, &vws, mbx);
1463
1464
1.41M
        for y in 0usize..8 {
1465
1.25M
            let uv_buf_index = (mby * 8 + y) * mw * 8 + mbx * 8;
1466
1.25M
            let ws_index = (1 + y) * stride + 1;
1467
1468
10.0M
            for (((ub, vb), &uw), &vw) in self.frame.ubuf[uv_buf_index..][..8]
1469
1.25M
                .iter_mut()
1470
1.25M
                .zip(self.frame.vbuf[uv_buf_index..][..8].iter_mut())
1471
1.25M
                .zip(uws[ws_index..][..8].iter())
1472
1.25M
                .zip(vws[ws_index..][..8].iter())
1473
10.0M
            {
1474
10.0M
                *ub = uw;
1475
10.0M
                *vb = vw;
1476
10.0M
            }
1477
        }
1478
157k
    }
1479
1480
10.9M
    fn read_coefficients(
1481
10.9M
        &mut self,
1482
10.9M
        block: &mut [i32; 16],
1483
10.9M
        p: usize,
1484
10.9M
        plane: usize,
1485
10.9M
        complexity: usize,
1486
10.9M
        dcq: i16,
1487
10.9M
        acq: i16,
1488
10.9M
    ) -> 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
10.9M
        assert!(complexity <= 2);
1492
1493
10.9M
        let first = if plane == 0 { 1usize } else { 0usize };
1494
10.9M
        let probs = &self.token_probs[plane];
1495
10.9M
        let decoder = &mut self.partitions[p];
1496
1497
10.9M
        let mut res = decoder.start_accumulated_result();
1498
1499
10.9M
        let mut complexity = complexity;
1500
10.9M
        let mut has_coefficients = false;
1501
10.9M
        let mut skip = false;
1502
1503
16.0M
        for i in first..16usize {
1504
16.0M
            let band = COEFF_BANDS[i] as usize;
1505
16.0M
            let tree = &probs[band][complexity];
1506
1507
16.0M
            let token = decoder
1508
16.0M
                .read_with_tree_with_first_node(tree, tree[skip as usize])
1509
16.0M
                .or_accumulate(&mut res);
1510
1511
16.0M
            let mut abs_value = i32::from(match token {
1512
10.8M
                DCT_EOB => break,
1513
1514
                DCT_0 => {
1515
1.73M
                    skip = true;
1516
1.73M
                    has_coefficients = true;
1517
1.73M
                    complexity = 0;
1518
1.73M
                    continue;
1519
                }
1520
1521
3.47M
                literal @ DCT_1..=DCT_4 => i16::from(literal),
1522
1523
111k
                category @ DCT_CAT1..=DCT_CAT6 => {
1524
111k
                    let probs = PROB_DCT_CAT[(category - DCT_CAT1) as usize];
1525
1526
111k
                    let mut extra = 0i16;
1527
1528
658k
                    for t in probs.iter().copied() {
1529
658k
                        if t == 0 {
1530
111k
                            break;
1531
547k
                        }
1532
547k
                        let b = decoder.read_bool(t).or_accumulate(&mut res);
1533
547k
                        extra = extra + extra + i16::from(b);
1534
                    }
1535
1536
111k
                    i16::from(DCT_CAT_BASE[(category - DCT_CAT1) as usize]) + extra
1537
                }
1538
1539
0
                c => panic!("unknown token: {c}"),
1540
            });
1541
1542
3.47M
            skip = false;
1543
1544
3.47M
            complexity = if abs_value == 0 {
1545
0
                0
1546
3.47M
            } else if abs_value == 1 {
1547
2.71M
                1
1548
            } else {
1549
750k
                2
1550
            };
1551
1552
3.47M
            if decoder.read_flag().or_accumulate(&mut res) {
1553
1.74M
                abs_value = -abs_value;
1554
1.74M
            }
1555
1556
3.47M
            let zigzag = ZIGZAG[i] as usize;
1557
3.47M
            block[zigzag] = abs_value * i32::from(if zigzag > 0 { acq } else { dcq });
1558
1559
3.47M
            has_coefficients = true;
1560
        }
1561
1562
10.9M
        decoder.check(res, has_coefficients)
1563
10.9M
    }
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_coefficients
Line
Count
Source
1480
8.99M
    fn read_coefficients(
1481
8.99M
        &mut self,
1482
8.99M
        block: &mut [i32; 16],
1483
8.99M
        p: usize,
1484
8.99M
        plane: usize,
1485
8.99M
        complexity: usize,
1486
8.99M
        dcq: i16,
1487
8.99M
        acq: i16,
1488
8.99M
    ) -> 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
8.99M
        assert!(complexity <= 2);
1492
1493
8.99M
        let first = if plane == 0 { 1usize } else { 0usize };
1494
8.99M
        let probs = &self.token_probs[plane];
1495
8.99M
        let decoder = &mut self.partitions[p];
1496
1497
8.99M
        let mut res = decoder.start_accumulated_result();
1498
1499
8.99M
        let mut complexity = complexity;
1500
8.99M
        let mut has_coefficients = false;
1501
8.99M
        let mut skip = false;
1502
1503
13.6M
        for i in first..16usize {
1504
13.6M
            let band = COEFF_BANDS[i] as usize;
1505
13.6M
            let tree = &probs[band][complexity];
1506
1507
13.6M
            let token = decoder
1508
13.6M
                .read_with_tree_with_first_node(tree, tree[skip as usize])
1509
13.6M
                .or_accumulate(&mut res);
1510
1511
13.6M
            let mut abs_value = i32::from(match token {
1512
8.98M
                DCT_EOB => break,
1513
1514
                DCT_0 => {
1515
1.51M
                    skip = true;
1516
1.51M
                    has_coefficients = true;
1517
1.51M
                    complexity = 0;
1518
1.51M
                    continue;
1519
                }
1520
1521
3.12M
                literal @ DCT_1..=DCT_4 => i16::from(literal),
1522
1523
99.9k
                category @ DCT_CAT1..=DCT_CAT6 => {
1524
99.9k
                    let probs = PROB_DCT_CAT[(category - DCT_CAT1) as usize];
1525
1526
99.9k
                    let mut extra = 0i16;
1527
1528
596k
                    for t in probs.iter().copied() {
1529
596k
                        if t == 0 {
1530
99.9k
                            break;
1531
496k
                        }
1532
496k
                        let b = decoder.read_bool(t).or_accumulate(&mut res);
1533
496k
                        extra = extra + extra + i16::from(b);
1534
                    }
1535
1536
99.9k
                    i16::from(DCT_CAT_BASE[(category - DCT_CAT1) as usize]) + extra
1537
                }
1538
1539
0
                c => panic!("unknown token: {c}"),
1540
            });
1541
1542
3.12M
            skip = false;
1543
1544
3.12M
            complexity = if abs_value == 0 {
1545
0
                0
1546
3.12M
            } else if abs_value == 1 {
1547
2.44M
                1
1548
            } else {
1549
686k
                2
1550
            };
1551
1552
3.12M
            if decoder.read_flag().or_accumulate(&mut res) {
1553
1.57M
                abs_value = -abs_value;
1554
1.57M
            }
1555
1556
3.12M
            let zigzag = ZIGZAG[i] as usize;
1557
3.12M
            block[zigzag] = abs_value * i32::from(if zigzag > 0 { acq } else { dcq });
1558
1559
3.12M
            has_coefficients = true;
1560
        }
1561
1562
8.99M
        decoder.check(res, has_coefficients)
1563
8.99M
    }
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::read_coefficients
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_coefficients
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_coefficients
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_coefficients
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_coefficients
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_coefficients
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_coefficients
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_coefficients
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_coefficients
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_coefficients
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_coefficients
Line
Count
Source
1480
1.91M
    fn read_coefficients(
1481
1.91M
        &mut self,
1482
1.91M
        block: &mut [i32; 16],
1483
1.91M
        p: usize,
1484
1.91M
        plane: usize,
1485
1.91M
        complexity: usize,
1486
1.91M
        dcq: i16,
1487
1.91M
        acq: i16,
1488
1.91M
    ) -> 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
1.91M
        assert!(complexity <= 2);
1492
1493
1.91M
        let first = if plane == 0 { 1usize } else { 0usize };
1494
1.91M
        let probs = &self.token_probs[plane];
1495
1.91M
        let decoder = &mut self.partitions[p];
1496
1497
1.91M
        let mut res = decoder.start_accumulated_result();
1498
1499
1.91M
        let mut complexity = complexity;
1500
1.91M
        let mut has_coefficients = false;
1501
1.91M
        let mut skip = false;
1502
1503
2.47M
        for i in first..16usize {
1504
2.47M
            let band = COEFF_BANDS[i] as usize;
1505
2.47M
            let tree = &probs[band][complexity];
1506
1507
2.47M
            let token = decoder
1508
2.47M
                .read_with_tree_with_first_node(tree, tree[skip as usize])
1509
2.47M
                .or_accumulate(&mut res);
1510
1511
2.47M
            let mut abs_value = i32::from(match token {
1512
1.90M
                DCT_EOB => break,
1513
1514
                DCT_0 => {
1515
220k
                    skip = true;
1516
220k
                    has_coefficients = true;
1517
220k
                    complexity = 0;
1518
220k
                    continue;
1519
                }
1520
1521
341k
                literal @ DCT_1..=DCT_4 => i16::from(literal),
1522
1523
11.5k
                category @ DCT_CAT1..=DCT_CAT6 => {
1524
11.5k
                    let probs = PROB_DCT_CAT[(category - DCT_CAT1) as usize];
1525
1526
11.5k
                    let mut extra = 0i16;
1527
1528
62.4k
                    for t in probs.iter().copied() {
1529
62.4k
                        if t == 0 {
1530
11.5k
                            break;
1531
50.9k
                        }
1532
50.9k
                        let b = decoder.read_bool(t).or_accumulate(&mut res);
1533
50.9k
                        extra = extra + extra + i16::from(b);
1534
                    }
1535
1536
11.5k
                    i16::from(DCT_CAT_BASE[(category - DCT_CAT1) as usize]) + extra
1537
                }
1538
1539
0
                c => panic!("unknown token: {c}"),
1540
            });
1541
1542
341k
            skip = false;
1543
1544
341k
            complexity = if abs_value == 0 {
1545
0
                0
1546
341k
            } else if abs_value == 1 {
1547
276k
                1
1548
            } else {
1549
64.7k
                2
1550
            };
1551
1552
341k
            if decoder.read_flag().or_accumulate(&mut res) {
1553
170k
                abs_value = -abs_value;
1554
170k
            }
1555
1556
341k
            let zigzag = ZIGZAG[i] as usize;
1557
341k
            block[zigzag] = abs_value * i32::from(if zigzag > 0 { acq } else { dcq });
1558
1559
341k
            has_coefficients = true;
1560
        }
1561
1562
1.91M
        decoder.check(res, has_coefficients)
1563
1.91M
    }
1564
1565
446k
    fn read_residual_data(
1566
446k
        &mut self,
1567
446k
        mb: &mut MacroBlock,
1568
446k
        mbx: usize,
1569
446k
        p: usize,
1570
446k
    ) -> Result<[i32; 384], DecodingError> {
1571
446k
        let sindex = mb.segmentid as usize;
1572
446k
        let mut blocks = [0i32; 384];
1573
446k
        let mut plane = if mb.luma_mode == LumaMode::B { 3 } else { 1 };
1574
1575
446k
        if plane == 1 {
1576
184k
            let complexity = self.top[mbx].complexity[0] + self.left.complexity[0];
1577
184k
            let mut block = [0i32; 16];
1578
184k
            let dcq = self.segment[sindex].y2dc;
1579
184k
            let acq = self.segment[sindex].y2ac;
1580
184k
            let n = self.read_coefficients(&mut block, p, plane, complexity as usize, dcq, acq)?;
1581
1582
184k
            self.left.complexity[0] = if n { 1 } else { 0 };
1583
184k
            self.top[mbx].complexity[0] = if n { 1 } else { 0 };
1584
1585
184k
            transform::iwht4x4(&mut block);
1586
1587
3.14M
            for k in 0usize..16 {
1588
2.95M
                blocks[16 * k] = block[k];
1589
2.95M
            }
1590
1591
184k
            plane = 0;
1592
261k
        }
1593
1594
2.23M
        for y in 0usize..4 {
1595
1.78M
            let mut left = self.left.complexity[y + 1];
1596
8.93M
            for x in 0usize..4 {
1597
7.14M
                let i = x + y * 4;
1598
7.14M
                let block = &mut blocks[i * 16..][..16];
1599
7.14M
                let block: &mut [i32; 16] = block.try_into().unwrap();
1600
1601
7.14M
                let complexity = self.top[mbx].complexity[x + 1] + left;
1602
7.14M
                let dcq = self.segment[sindex].ydc;
1603
7.14M
                let acq = self.segment[sindex].yac;
1604
1605
7.14M
                let n = self.read_coefficients(block, p, plane, complexity as usize, dcq, acq)?;
1606
1607
7.14M
                if block[0] != 0 || n {
1608
1.99M
                    mb.non_zero_dct = true;
1609
1.99M
                    transform::idct4x4(block);
1610
5.15M
                }
1611
1612
7.14M
                left = if n { 1 } else { 0 };
1613
7.14M
                self.top[mbx].complexity[x + 1] = if n { 1 } else { 0 };
1614
            }
1615
1616
1.78M
            self.left.complexity[y + 1] = left;
1617
        }
1618
1619
446k
        plane = 2;
1620
1621
1.33M
        for &j in &[5usize, 7usize] {
1622
2.67M
            for y in 0usize..2 {
1623
1.78M
                let mut left = self.left.complexity[y + j];
1624
1625
5.35M
                for x in 0usize..2 {
1626
3.57M
                    let i = x + y * 2 + if j == 5 { 16 } else { 20 };
1627
3.57M
                    let block = &mut blocks[i * 16..][..16];
1628
3.57M
                    let block: &mut [i32; 16] = block.try_into().unwrap();
1629
1630
3.57M
                    let complexity = self.top[mbx].complexity[x + j] + left;
1631
3.57M
                    let dcq = self.segment[sindex].uvdc;
1632
3.57M
                    let acq = self.segment[sindex].uvac;
1633
1634
3.57M
                    let n =
1635
3.57M
                        self.read_coefficients(block, p, plane, complexity as usize, dcq, acq)?;
1636
3.57M
                    if block[0] != 0 || n {
1637
463k
                        mb.non_zero_dct = true;
1638
463k
                        transform::idct4x4(block);
1639
3.10M
                    }
1640
1641
3.57M
                    left = if n { 1 } else { 0 };
1642
3.57M
                    self.top[mbx].complexity[x + j] = if n { 1 } else { 0 };
1643
                }
1644
1645
1.78M
                self.left.complexity[y + j] = left;
1646
            }
1647
        }
1648
1649
446k
        Ok(blocks)
1650
446k
    }
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_residual_data
Line
Count
Source
1565
368k
    fn read_residual_data(
1566
368k
        &mut self,
1567
368k
        mb: &mut MacroBlock,
1568
368k
        mbx: usize,
1569
368k
        p: usize,
1570
368k
    ) -> Result<[i32; 384], DecodingError> {
1571
368k
        let sindex = mb.segmentid as usize;
1572
368k
        let mut blocks = [0i32; 384];
1573
368k
        let mut plane = if mb.luma_mode == LumaMode::B { 3 } else { 1 };
1574
1575
368k
        if plane == 1 {
1576
151k
            let complexity = self.top[mbx].complexity[0] + self.left.complexity[0];
1577
151k
            let mut block = [0i32; 16];
1578
151k
            let dcq = self.segment[sindex].y2dc;
1579
151k
            let acq = self.segment[sindex].y2ac;
1580
151k
            let n = self.read_coefficients(&mut block, p, plane, complexity as usize, dcq, acq)?;
1581
1582
151k
            self.left.complexity[0] = if n { 1 } else { 0 };
1583
151k
            self.top[mbx].complexity[0] = if n { 1 } else { 0 };
1584
1585
151k
            transform::iwht4x4(&mut block);
1586
1587
2.58M
            for k in 0usize..16 {
1588
2.42M
                blocks[16 * k] = block[k];
1589
2.42M
            }
1590
1591
151k
            plane = 0;
1592
216k
        }
1593
1594
1.84M
        for y in 0usize..4 {
1595
1.47M
            let mut left = self.left.complexity[y + 1];
1596
7.36M
            for x in 0usize..4 {
1597
5.89M
                let i = x + y * 4;
1598
5.89M
                let block = &mut blocks[i * 16..][..16];
1599
5.89M
                let block: &mut [i32; 16] = block.try_into().unwrap();
1600
1601
5.89M
                let complexity = self.top[mbx].complexity[x + 1] + left;
1602
5.89M
                let dcq = self.segment[sindex].ydc;
1603
5.89M
                let acq = self.segment[sindex].yac;
1604
1605
5.89M
                let n = self.read_coefficients(block, p, plane, complexity as usize, dcq, acq)?;
1606
1607
5.89M
                if block[0] != 0 || n {
1608
1.78M
                    mb.non_zero_dct = true;
1609
1.78M
                    transform::idct4x4(block);
1610
4.10M
                }
1611
1612
5.89M
                left = if n { 1 } else { 0 };
1613
5.89M
                self.top[mbx].complexity[x + 1] = if n { 1 } else { 0 };
1614
            }
1615
1616
1.47M
            self.left.complexity[y + 1] = left;
1617
        }
1618
1619
368k
        plane = 2;
1620
1621
1.10M
        for &j in &[5usize, 7usize] {
1622
2.20M
            for y in 0usize..2 {
1623
1.47M
                let mut left = self.left.complexity[y + j];
1624
1625
4.41M
                for x in 0usize..2 {
1626
2.94M
                    let i = x + y * 2 + if j == 5 { 16 } else { 20 };
1627
2.94M
                    let block = &mut blocks[i * 16..][..16];
1628
2.94M
                    let block: &mut [i32; 16] = block.try_into().unwrap();
1629
1630
2.94M
                    let complexity = self.top[mbx].complexity[x + j] + left;
1631
2.94M
                    let dcq = self.segment[sindex].uvdc;
1632
2.94M
                    let acq = self.segment[sindex].uvac;
1633
1634
2.94M
                    let n =
1635
2.94M
                        self.read_coefficients(block, p, plane, complexity as usize, dcq, acq)?;
1636
2.94M
                    if block[0] != 0 || n {
1637
444k
                        mb.non_zero_dct = true;
1638
444k
                        transform::idct4x4(block);
1639
2.50M
                    }
1640
1641
2.94M
                    left = if n { 1 } else { 0 };
1642
2.94M
                    self.top[mbx].complexity[x + j] = if n { 1 } else { 0 };
1643
                }
1644
1645
1.47M
                self.left.complexity[y + j] = left;
1646
            }
1647
        }
1648
1649
368k
        Ok(blocks)
1650
368k
    }
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::read_residual_data
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_residual_data
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_residual_data
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_residual_data
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_residual_data
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_residual_data
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_residual_data
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_residual_data
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_residual_data
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_residual_data
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_residual_data
Line
Count
Source
1565
78.3k
    fn read_residual_data(
1566
78.3k
        &mut self,
1567
78.3k
        mb: &mut MacroBlock,
1568
78.3k
        mbx: usize,
1569
78.3k
        p: usize,
1570
78.3k
    ) -> Result<[i32; 384], DecodingError> {
1571
78.3k
        let sindex = mb.segmentid as usize;
1572
78.3k
        let mut blocks = [0i32; 384];
1573
78.3k
        let mut plane = if mb.luma_mode == LumaMode::B { 3 } else { 1 };
1574
1575
78.3k
        if plane == 1 {
1576
32.9k
            let complexity = self.top[mbx].complexity[0] + self.left.complexity[0];
1577
32.9k
            let mut block = [0i32; 16];
1578
32.9k
            let dcq = self.segment[sindex].y2dc;
1579
32.9k
            let acq = self.segment[sindex].y2ac;
1580
32.9k
            let n = self.read_coefficients(&mut block, p, plane, complexity as usize, dcq, acq)?;
1581
1582
32.9k
            self.left.complexity[0] = if n { 1 } else { 0 };
1583
32.9k
            self.top[mbx].complexity[0] = if n { 1 } else { 0 };
1584
1585
32.9k
            transform::iwht4x4(&mut block);
1586
1587
559k
            for k in 0usize..16 {
1588
526k
                blocks[16 * k] = block[k];
1589
526k
            }
1590
1591
32.9k
            plane = 0;
1592
45.3k
        }
1593
1594
391k
        for y in 0usize..4 {
1595
313k
            let mut left = self.left.complexity[y + 1];
1596
1.56M
            for x in 0usize..4 {
1597
1.25M
                let i = x + y * 4;
1598
1.25M
                let block = &mut blocks[i * 16..][..16];
1599
1.25M
                let block: &mut [i32; 16] = block.try_into().unwrap();
1600
1601
1.25M
                let complexity = self.top[mbx].complexity[x + 1] + left;
1602
1.25M
                let dcq = self.segment[sindex].ydc;
1603
1.25M
                let acq = self.segment[sindex].yac;
1604
1605
1.25M
                let n = self.read_coefficients(block, p, plane, complexity as usize, dcq, acq)?;
1606
1607
1.25M
                if block[0] != 0 || n {
1608
205k
                    mb.non_zero_dct = true;
1609
205k
                    transform::idct4x4(block);
1610
1.04M
                }
1611
1612
1.25M
                left = if n { 1 } else { 0 };
1613
1.25M
                self.top[mbx].complexity[x + 1] = if n { 1 } else { 0 };
1614
            }
1615
1616
312k
            self.left.complexity[y + 1] = left;
1617
        }
1618
1619
78.2k
        plane = 2;
1620
1621
234k
        for &j in &[5usize, 7usize] {
1622
469k
            for y in 0usize..2 {
1623
312k
                let mut left = self.left.complexity[y + j];
1624
1625
938k
                for x in 0usize..2 {
1626
625k
                    let i = x + y * 2 + if j == 5 { 16 } else { 20 };
1627
625k
                    let block = &mut blocks[i * 16..][..16];
1628
625k
                    let block: &mut [i32; 16] = block.try_into().unwrap();
1629
1630
625k
                    let complexity = self.top[mbx].complexity[x + j] + left;
1631
625k
                    let dcq = self.segment[sindex].uvdc;
1632
625k
                    let acq = self.segment[sindex].uvac;
1633
1634
625k
                    let n =
1635
625k
                        self.read_coefficients(block, p, plane, complexity as usize, dcq, acq)?;
1636
625k
                    if block[0] != 0 || n {
1637
18.8k
                        mb.non_zero_dct = true;
1638
18.8k
                        transform::idct4x4(block);
1639
606k
                    }
1640
1641
625k
                    left = if n { 1 } else { 0 };
1642
625k
                    self.top[mbx].complexity[x + j] = if n { 1 } else { 0 };
1643
                }
1644
1645
312k
                self.left.complexity[y + j] = left;
1646
            }
1647
        }
1648
1649
78.2k
        Ok(blocks)
1650
78.3k
    }
1651
1652
    /// Does loop filtering on the macroblock
1653
1.34M
    fn loop_filter(&mut self, mbx: usize, mby: usize, mb: &MacroBlock) {
1654
1.34M
        let luma_w = self.mbwidth as usize * 16;
1655
1.34M
        let chroma_w = self.mbwidth as usize * 8;
1656
1657
1.34M
        let (filter_level, interior_limit, hev_threshold) = self.calculate_filter_parameters(mb);
1658
1659
1.34M
        if filter_level > 0 {
1660
1.33M
            let mbedge_limit = (filter_level + 2) * 2 + interior_limit;
1661
1.33M
            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.33M
            let do_subblock_filtering =
1665
1.33M
                mb.luma_mode == LumaMode::B || (!mb.coeffs_skipped && mb.non_zero_dct);
1666
1667
            //filter across left of macroblock
1668
1.33M
            if mbx > 0 {
1669
                //simple loop filtering
1670
1.31M
                if self.frame.filter_type {
1671
1.66M
                    for y in 0usize..16 {
1672
1.56M
                        let y0 = mby * 16 + y;
1673
1.56M
                        let x0 = mbx * 16;
1674
1.56M
1675
1.56M
                        loop_filter::simple_segment_horizontal(
1676
1.56M
                            mbedge_limit,
1677
1.56M
                            &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8],
1678
1.56M
                        );
1679
1.56M
                    }
1680
                } else {
1681
20.6M
                    for y in 0usize..16 {
1682
19.4M
                        let y0 = mby * 16 + y;
1683
19.4M
                        let x0 = mbx * 16;
1684
19.4M
1685
19.4M
                        loop_filter::macroblock_filter_horizontal(
1686
19.4M
                            hev_threshold,
1687
19.4M
                            interior_limit,
1688
19.4M
                            mbedge_limit,
1689
19.4M
                            &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8],
1690
19.4M
                        );
1691
19.4M
                    }
1692
1693
10.9M
                    for y in 0usize..8 {
1694
9.72M
                        let y0 = mby * 8 + y;
1695
9.72M
                        let x0 = mbx * 8;
1696
9.72M
1697
9.72M
                        loop_filter::macroblock_filter_horizontal(
1698
9.72M
                            hev_threshold,
1699
9.72M
                            interior_limit,
1700
9.72M
                            mbedge_limit,
1701
9.72M
                            &mut self.frame.ubuf[y0 * chroma_w + x0 - 4..][..8],
1702
9.72M
                        );
1703
9.72M
                        loop_filter::macroblock_filter_horizontal(
1704
9.72M
                            hev_threshold,
1705
9.72M
                            interior_limit,
1706
9.72M
                            mbedge_limit,
1707
9.72M
                            &mut self.frame.vbuf[y0 * chroma_w + x0 - 4..][..8],
1708
9.72M
                        );
1709
9.72M
                    }
1710
                }
1711
19.6k
            }
1712
1713
            //filter across vertical subblocks in macroblock
1714
1.33M
            if do_subblock_filtering {
1715
587k
                if self.frame.filter_type {
1716
153k
                    for x in (4usize..16 - 1).step_by(4) {
1717
2.61M
                        for y in 0..16 {
1718
2.45M
                            let y0 = mby * 16 + y;
1719
2.45M
                            let x0 = mbx * 16 + x;
1720
2.45M
1721
2.45M
                            loop_filter::simple_segment_horizontal(
1722
2.45M
                                sub_bedge_limit,
1723
2.45M
                                &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8],
1724
2.45M
                            );
1725
2.45M
                        }
1726
                    }
1727
                } else {
1728
1.60M
                    for x in (4usize..16 - 3).step_by(4) {
1729
27.3M
                        for y in 0..16 {
1730
25.7M
                            let y0 = mby * 16 + y;
1731
25.7M
                            let x0 = mbx * 16 + x;
1732
25.7M
1733
25.7M
                            loop_filter::subblock_filter_horizontal(
1734
25.7M
                                hev_threshold,
1735
25.7M
                                interior_limit,
1736
25.7M
                                sub_bedge_limit,
1737
25.7M
                                &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8],
1738
25.7M
                            );
1739
25.7M
                        }
1740
                    }
1741
1742
4.82M
                    for y in 0usize..8 {
1743
4.28M
                        let y0 = mby * 8 + y;
1744
4.28M
                        let x0 = mbx * 8 + 4;
1745
4.28M
1746
4.28M
                        loop_filter::subblock_filter_horizontal(
1747
4.28M
                            hev_threshold,
1748
4.28M
                            interior_limit,
1749
4.28M
                            sub_bedge_limit,
1750
4.28M
                            &mut self.frame.ubuf[y0 * chroma_w + x0 - 4..][..8],
1751
4.28M
                        );
1752
4.28M
1753
4.28M
                        loop_filter::subblock_filter_horizontal(
1754
4.28M
                            hev_threshold,
1755
4.28M
                            interior_limit,
1756
4.28M
                            sub_bedge_limit,
1757
4.28M
                            &mut self.frame.vbuf[y0 * chroma_w + x0 - 4..][..8],
1758
4.28M
                        );
1759
4.28M
                    }
1760
                }
1761
745k
            }
1762
1763
            //filter across top of macroblock
1764
1.33M
            if mby > 0 {
1765
1.28M
                if self.frame.filter_type {
1766
1.46M
                    for x in 0usize..16 {
1767
1.38M
                        let y0 = mby * 16;
1768
1.38M
                        let x0 = mbx * 16 + x;
1769
1.38M
1770
1.38M
                        loop_filter::simple_segment_vertical(
1771
1.38M
                            mbedge_limit,
1772
1.38M
                            &mut self.frame.ybuf[..],
1773
1.38M
                            y0 * luma_w + x0,
1774
1.38M
                            luma_w,
1775
1.38M
                        );
1776
1.38M
                    }
1777
                } else {
1778
                    //if bottom macroblock, can only filter if there is 3 pixels below
1779
20.4M
                    for x in 0usize..16 {
1780
19.2M
                        let y0 = mby * 16;
1781
19.2M
                        let x0 = mbx * 16 + x;
1782
19.2M
1783
19.2M
                        loop_filter::macroblock_filter_vertical(
1784
19.2M
                            hev_threshold,
1785
19.2M
                            interior_limit,
1786
19.2M
                            mbedge_limit,
1787
19.2M
                            &mut self.frame.ybuf[..],
1788
19.2M
                            y0 * luma_w + x0,
1789
19.2M
                            luma_w,
1790
19.2M
                        );
1791
19.2M
                    }
1792
1793
10.8M
                    for x in 0usize..8 {
1794
9.61M
                        let y0 = mby * 8;
1795
9.61M
                        let x0 = mbx * 8 + x;
1796
9.61M
1797
9.61M
                        loop_filter::macroblock_filter_vertical(
1798
9.61M
                            hev_threshold,
1799
9.61M
                            interior_limit,
1800
9.61M
                            mbedge_limit,
1801
9.61M
                            &mut self.frame.ubuf[..],
1802
9.61M
                            y0 * chroma_w + x0,
1803
9.61M
                            chroma_w,
1804
9.61M
                        );
1805
9.61M
                        loop_filter::macroblock_filter_vertical(
1806
9.61M
                            hev_threshold,
1807
9.61M
                            interior_limit,
1808
9.61M
                            mbedge_limit,
1809
9.61M
                            &mut self.frame.vbuf[..],
1810
9.61M
                            y0 * chroma_w + x0,
1811
9.61M
                            chroma_w,
1812
9.61M
                        );
1813
9.61M
                    }
1814
                }
1815
44.3k
            }
1816
1817
            //filter across horizontal subblock edges within the macroblock
1818
1.33M
            if do_subblock_filtering {
1819
587k
                if self.frame.filter_type {
1820
153k
                    for y in (4usize..16 - 1).step_by(4) {
1821
2.61M
                        for x in 0..16 {
1822
2.45M
                            let y0 = mby * 16 + y;
1823
2.45M
                            let x0 = mbx * 16 + x;
1824
2.45M
1825
2.45M
                            loop_filter::simple_segment_vertical(
1826
2.45M
                                sub_bedge_limit,
1827
2.45M
                                &mut self.frame.ybuf[..],
1828
2.45M
                                y0 * luma_w + x0,
1829
2.45M
                                luma_w,
1830
2.45M
                            );
1831
2.45M
                        }
1832
                    }
1833
                } else {
1834
1.60M
                    for y in (4usize..16 - 3).step_by(4) {
1835
27.3M
                        for x in 0..16 {
1836
25.7M
                            let y0 = mby * 16 + y;
1837
25.7M
                            let x0 = mbx * 16 + x;
1838
25.7M
1839
25.7M
                            loop_filter::subblock_filter_vertical(
1840
25.7M
                                hev_threshold,
1841
25.7M
                                interior_limit,
1842
25.7M
                                sub_bedge_limit,
1843
25.7M
                                &mut self.frame.ybuf[..],
1844
25.7M
                                y0 * luma_w + x0,
1845
25.7M
                                luma_w,
1846
25.7M
                            );
1847
25.7M
                        }
1848
                    }
1849
1850
4.82M
                    for x in 0..8 {
1851
4.28M
                        let y0 = mby * 8 + 4;
1852
4.28M
                        let x0 = mbx * 8 + x;
1853
4.28M
1854
4.28M
                        loop_filter::subblock_filter_vertical(
1855
4.28M
                            hev_threshold,
1856
4.28M
                            interior_limit,
1857
4.28M
                            sub_bedge_limit,
1858
4.28M
                            &mut self.frame.ubuf[..],
1859
4.28M
                            y0 * chroma_w + x0,
1860
4.28M
                            chroma_w,
1861
4.28M
                        );
1862
4.28M
1863
4.28M
                        loop_filter::subblock_filter_vertical(
1864
4.28M
                            hev_threshold,
1865
4.28M
                            interior_limit,
1866
4.28M
                            sub_bedge_limit,
1867
4.28M
                            &mut self.frame.vbuf[..],
1868
4.28M
                            y0 * chroma_w + x0,
1869
4.28M
                            chroma_w,
1870
4.28M
                        );
1871
4.28M
                    }
1872
                }
1873
745k
            }
1874
16.6k
        }
1875
1.34M
    }
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::loop_filter
Line
Count
Source
1653
1.27M
    fn loop_filter(&mut self, mbx: usize, mby: usize, mb: &MacroBlock) {
1654
1.27M
        let luma_w = self.mbwidth as usize * 16;
1655
1.27M
        let chroma_w = self.mbwidth as usize * 8;
1656
1657
1.27M
        let (filter_level, interior_limit, hev_threshold) = self.calculate_filter_parameters(mb);
1658
1659
1.27M
        if filter_level > 0 {
1660
1.26M
            let mbedge_limit = (filter_level + 2) * 2 + interior_limit;
1661
1.26M
            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.26M
            let do_subblock_filtering =
1665
1.26M
                mb.luma_mode == LumaMode::B || (!mb.coeffs_skipped && mb.non_zero_dct);
1666
1667
            //filter across left of macroblock
1668
1.26M
            if mbx > 0 {
1669
                //simple loop filtering
1670
1.25M
                if self.frame.filter_type {
1671
1.22M
                    for y in 0usize..16 {
1672
1.15M
                        let y0 = mby * 16 + y;
1673
1.15M
                        let x0 = mbx * 16;
1674
1.15M
1675
1.15M
                        loop_filter::simple_segment_horizontal(
1676
1.15M
                            mbedge_limit,
1677
1.15M
                            &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8],
1678
1.15M
                        );
1679
1.15M
                    }
1680
                } else {
1681
20.0M
                    for y in 0usize..16 {
1682
18.8M
                        let y0 = mby * 16 + y;
1683
18.8M
                        let x0 = mbx * 16;
1684
18.8M
1685
18.8M
                        loop_filter::macroblock_filter_horizontal(
1686
18.8M
                            hev_threshold,
1687
18.8M
                            interior_limit,
1688
18.8M
                            mbedge_limit,
1689
18.8M
                            &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8],
1690
18.8M
                        );
1691
18.8M
                    }
1692
1693
10.6M
                    for y in 0usize..8 {
1694
9.44M
                        let y0 = mby * 8 + y;
1695
9.44M
                        let x0 = mbx * 8;
1696
9.44M
1697
9.44M
                        loop_filter::macroblock_filter_horizontal(
1698
9.44M
                            hev_threshold,
1699
9.44M
                            interior_limit,
1700
9.44M
                            mbedge_limit,
1701
9.44M
                            &mut self.frame.ubuf[y0 * chroma_w + x0 - 4..][..8],
1702
9.44M
                        );
1703
9.44M
                        loop_filter::macroblock_filter_horizontal(
1704
9.44M
                            hev_threshold,
1705
9.44M
                            interior_limit,
1706
9.44M
                            mbedge_limit,
1707
9.44M
                            &mut self.frame.vbuf[y0 * chroma_w + x0 - 4..][..8],
1708
9.44M
                        );
1709
9.44M
                    }
1710
                }
1711
13.4k
            }
1712
1713
            //filter across vertical subblocks in macroblock
1714
1.26M
            if do_subblock_filtering {
1715
550k
                if self.frame.filter_type {
1716
101k
                    for x in (4usize..16 - 1).step_by(4) {
1717
1.72M
                        for y in 0..16 {
1718
1.62M
                            let y0 = mby * 16 + y;
1719
1.62M
                            let x0 = mbx * 16 + x;
1720
1.62M
1721
1.62M
                            loop_filter::simple_segment_horizontal(
1722
1.62M
                                sub_bedge_limit,
1723
1.62M
                                &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8],
1724
1.62M
                            );
1725
1.62M
                        }
1726
                    }
1727
                } else {
1728
1.55M
                    for x in (4usize..16 - 3).step_by(4) {
1729
26.3M
                        for y in 0..16 {
1730
24.8M
                            let y0 = mby * 16 + y;
1731
24.8M
                            let x0 = mbx * 16 + x;
1732
24.8M
1733
24.8M
                            loop_filter::subblock_filter_horizontal(
1734
24.8M
                                hev_threshold,
1735
24.8M
                                interior_limit,
1736
24.8M
                                sub_bedge_limit,
1737
24.8M
                                &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8],
1738
24.8M
                            );
1739
24.8M
                        }
1740
                    }
1741
1742
4.65M
                    for y in 0usize..8 {
1743
4.13M
                        let y0 = mby * 8 + y;
1744
4.13M
                        let x0 = mbx * 8 + 4;
1745
4.13M
1746
4.13M
                        loop_filter::subblock_filter_horizontal(
1747
4.13M
                            hev_threshold,
1748
4.13M
                            interior_limit,
1749
4.13M
                            sub_bedge_limit,
1750
4.13M
                            &mut self.frame.ubuf[y0 * chroma_w + x0 - 4..][..8],
1751
4.13M
                        );
1752
4.13M
1753
4.13M
                        loop_filter::subblock_filter_horizontal(
1754
4.13M
                            hev_threshold,
1755
4.13M
                            interior_limit,
1756
4.13M
                            sub_bedge_limit,
1757
4.13M
                            &mut self.frame.vbuf[y0 * chroma_w + x0 - 4..][..8],
1758
4.13M
                        );
1759
4.13M
                    }
1760
                }
1761
716k
            }
1762
1763
            //filter across top of macroblock
1764
1.26M
            if mby > 0 {
1765
1.22M
                if self.frame.filter_type {
1766
1.01M
                    for x in 0usize..16 {
1767
956k
                        let y0 = mby * 16;
1768
956k
                        let x0 = mbx * 16 + x;
1769
956k
1770
956k
                        loop_filter::simple_segment_vertical(
1771
956k
                            mbedge_limit,
1772
956k
                            &mut self.frame.ybuf[..],
1773
956k
                            y0 * luma_w + x0,
1774
956k
                            luma_w,
1775
956k
                        );
1776
956k
                    }
1777
                } else {
1778
                    //if bottom macroblock, can only filter if there is 3 pixels below
1779
19.8M
                    for x in 0usize..16 {
1780
18.6M
                        let y0 = mby * 16;
1781
18.6M
                        let x0 = mbx * 16 + x;
1782
18.6M
1783
18.6M
                        loop_filter::macroblock_filter_vertical(
1784
18.6M
                            hev_threshold,
1785
18.6M
                            interior_limit,
1786
18.6M
                            mbedge_limit,
1787
18.6M
                            &mut self.frame.ybuf[..],
1788
18.6M
                            y0 * luma_w + x0,
1789
18.6M
                            luma_w,
1790
18.6M
                        );
1791
18.6M
                    }
1792
1793
10.4M
                    for x in 0usize..8 {
1794
9.33M
                        let y0 = mby * 8;
1795
9.33M
                        let x0 = mbx * 8 + x;
1796
9.33M
1797
9.33M
                        loop_filter::macroblock_filter_vertical(
1798
9.33M
                            hev_threshold,
1799
9.33M
                            interior_limit,
1800
9.33M
                            mbedge_limit,
1801
9.33M
                            &mut self.frame.ubuf[..],
1802
9.33M
                            y0 * chroma_w + x0,
1803
9.33M
                            chroma_w,
1804
9.33M
                        );
1805
9.33M
                        loop_filter::macroblock_filter_vertical(
1806
9.33M
                            hev_threshold,
1807
9.33M
                            interior_limit,
1808
9.33M
                            mbedge_limit,
1809
9.33M
                            &mut self.frame.vbuf[..],
1810
9.33M
                            y0 * chroma_w + x0,
1811
9.33M
                            chroma_w,
1812
9.33M
                        );
1813
9.33M
                    }
1814
                }
1815
40.4k
            }
1816
1817
            //filter across horizontal subblock edges within the macroblock
1818
1.26M
            if do_subblock_filtering {
1819
550k
                if self.frame.filter_type {
1820
101k
                    for y in (4usize..16 - 1).step_by(4) {
1821
1.72M
                        for x in 0..16 {
1822
1.62M
                            let y0 = mby * 16 + y;
1823
1.62M
                            let x0 = mbx * 16 + x;
1824
1.62M
1825
1.62M
                            loop_filter::simple_segment_vertical(
1826
1.62M
                                sub_bedge_limit,
1827
1.62M
                                &mut self.frame.ybuf[..],
1828
1.62M
                                y0 * luma_w + x0,
1829
1.62M
                                luma_w,
1830
1.62M
                            );
1831
1.62M
                        }
1832
                    }
1833
                } else {
1834
1.55M
                    for y in (4usize..16 - 3).step_by(4) {
1835
26.3M
                        for x in 0..16 {
1836
24.8M
                            let y0 = mby * 16 + y;
1837
24.8M
                            let x0 = mbx * 16 + x;
1838
24.8M
1839
24.8M
                            loop_filter::subblock_filter_vertical(
1840
24.8M
                                hev_threshold,
1841
24.8M
                                interior_limit,
1842
24.8M
                                sub_bedge_limit,
1843
24.8M
                                &mut self.frame.ybuf[..],
1844
24.8M
                                y0 * luma_w + x0,
1845
24.8M
                                luma_w,
1846
24.8M
                            );
1847
24.8M
                        }
1848
                    }
1849
1850
4.65M
                    for x in 0..8 {
1851
4.13M
                        let y0 = mby * 8 + 4;
1852
4.13M
                        let x0 = mbx * 8 + x;
1853
4.13M
1854
4.13M
                        loop_filter::subblock_filter_vertical(
1855
4.13M
                            hev_threshold,
1856
4.13M
                            interior_limit,
1857
4.13M
                            sub_bedge_limit,
1858
4.13M
                            &mut self.frame.ubuf[..],
1859
4.13M
                            y0 * chroma_w + x0,
1860
4.13M
                            chroma_w,
1861
4.13M
                        );
1862
4.13M
1863
4.13M
                        loop_filter::subblock_filter_vertical(
1864
4.13M
                            hev_threshold,
1865
4.13M
                            interior_limit,
1866
4.13M
                            sub_bedge_limit,
1867
4.13M
                            &mut self.frame.vbuf[..],
1868
4.13M
                            y0 * chroma_w + x0,
1869
4.13M
                            chroma_w,
1870
4.13M
                        );
1871
4.13M
                    }
1872
                }
1873
716k
            }
1874
12.2k
        }
1875
1.27M
    }
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::loop_filter
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::loop_filter
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::loop_filter
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::loop_filter
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::loop_filter
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::loop_filter
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::loop_filter
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::loop_filter
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::loop_filter
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::loop_filter
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::loop_filter
Line
Count
Source
1653
70.6k
    fn loop_filter(&mut self, mbx: usize, mby: usize, mb: &MacroBlock) {
1654
70.6k
        let luma_w = self.mbwidth as usize * 16;
1655
70.6k
        let chroma_w = self.mbwidth as usize * 8;
1656
1657
70.6k
        let (filter_level, interior_limit, hev_threshold) = self.calculate_filter_parameters(mb);
1658
1659
70.6k
        if filter_level > 0 {
1660
66.2k
            let mbedge_limit = (filter_level + 2) * 2 + interior_limit;
1661
66.2k
            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
66.2k
            let do_subblock_filtering =
1665
66.2k
                mb.luma_mode == LumaMode::B || (!mb.coeffs_skipped && mb.non_zero_dct);
1666
1667
            //filter across left of macroblock
1668
66.2k
            if mbx > 0 {
1669
                //simple loop filtering
1670
60.0k
                if self.frame.filter_type {
1671
432k
                    for y in 0usize..16 {
1672
406k
                        let y0 = mby * 16 + y;
1673
406k
                        let x0 = mbx * 16;
1674
406k
1675
406k
                        loop_filter::simple_segment_horizontal(
1676
406k
                            mbedge_limit,
1677
406k
                            &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8],
1678
406k
                        );
1679
406k
                    }
1680
                } else {
1681
588k
                    for y in 0usize..16 {
1682
554k
                        let y0 = mby * 16 + y;
1683
554k
                        let x0 = mbx * 16;
1684
554k
1685
554k
                        loop_filter::macroblock_filter_horizontal(
1686
554k
                            hev_threshold,
1687
554k
                            interior_limit,
1688
554k
                            mbedge_limit,
1689
554k
                            &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8],
1690
554k
                        );
1691
554k
                    }
1692
1693
311k
                    for y in 0usize..8 {
1694
277k
                        let y0 = mby * 8 + y;
1695
277k
                        let x0 = mbx * 8;
1696
277k
1697
277k
                        loop_filter::macroblock_filter_horizontal(
1698
277k
                            hev_threshold,
1699
277k
                            interior_limit,
1700
277k
                            mbedge_limit,
1701
277k
                            &mut self.frame.ubuf[y0 * chroma_w + x0 - 4..][..8],
1702
277k
                        );
1703
277k
                        loop_filter::macroblock_filter_horizontal(
1704
277k
                            hev_threshold,
1705
277k
                            interior_limit,
1706
277k
                            mbedge_limit,
1707
277k
                            &mut self.frame.vbuf[y0 * chroma_w + x0 - 4..][..8],
1708
277k
                        );
1709
277k
                    }
1710
                }
1711
6.16k
            }
1712
1713
            //filter across vertical subblocks in macroblock
1714
66.2k
            if do_subblock_filtering {
1715
36.5k
                if self.frame.filter_type {
1716
52.3k
                    for x in (4usize..16 - 1).step_by(4) {
1717
890k
                        for y in 0..16 {
1718
837k
                            let y0 = mby * 16 + y;
1719
837k
                            let x0 = mbx * 16 + x;
1720
837k
1721
837k
                            loop_filter::simple_segment_horizontal(
1722
837k
                                sub_bedge_limit,
1723
837k
                                &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8],
1724
837k
                            );
1725
837k
                        }
1726
                    }
1727
                } else {
1728
57.1k
                    for x in (4usize..16 - 3).step_by(4) {
1729
971k
                        for y in 0..16 {
1730
914k
                            let y0 = mby * 16 + y;
1731
914k
                            let x0 = mbx * 16 + x;
1732
914k
1733
914k
                            loop_filter::subblock_filter_horizontal(
1734
914k
                                hev_threshold,
1735
914k
                                interior_limit,
1736
914k
                                sub_bedge_limit,
1737
914k
                                &mut self.frame.ybuf[y0 * luma_w + x0 - 4..][..8],
1738
914k
                            );
1739
914k
                        }
1740
                    }
1741
1742
171k
                    for y in 0usize..8 {
1743
152k
                        let y0 = mby * 8 + y;
1744
152k
                        let x0 = mbx * 8 + 4;
1745
152k
1746
152k
                        loop_filter::subblock_filter_horizontal(
1747
152k
                            hev_threshold,
1748
152k
                            interior_limit,
1749
152k
                            sub_bedge_limit,
1750
152k
                            &mut self.frame.ubuf[y0 * chroma_w + x0 - 4..][..8],
1751
152k
                        );
1752
152k
1753
152k
                        loop_filter::subblock_filter_horizontal(
1754
152k
                            hev_threshold,
1755
152k
                            interior_limit,
1756
152k
                            sub_bedge_limit,
1757
152k
                            &mut self.frame.vbuf[y0 * chroma_w + x0 - 4..][..8],
1758
152k
                        );
1759
152k
                    }
1760
                }
1761
29.7k
            }
1762
1763
            //filter across top of macroblock
1764
66.2k
            if mby > 0 {
1765
62.3k
                if self.frame.filter_type {
1766
451k
                    for x in 0usize..16 {
1767
424k
                        let y0 = mby * 16;
1768
424k
                        let x0 = mbx * 16 + x;
1769
424k
1770
424k
                        loop_filter::simple_segment_vertical(
1771
424k
                            mbedge_limit,
1772
424k
                            &mut self.frame.ybuf[..],
1773
424k
                            y0 * luma_w + x0,
1774
424k
                            luma_w,
1775
424k
                        );
1776
424k
                    }
1777
                } else {
1778
                    //if bottom macroblock, can only filter if there is 3 pixels below
1779
607k
                    for x in 0usize..16 {
1780
572k
                        let y0 = mby * 16;
1781
572k
                        let x0 = mbx * 16 + x;
1782
572k
1783
572k
                        loop_filter::macroblock_filter_vertical(
1784
572k
                            hev_threshold,
1785
572k
                            interior_limit,
1786
572k
                            mbedge_limit,
1787
572k
                            &mut self.frame.ybuf[..],
1788
572k
                            y0 * luma_w + x0,
1789
572k
                            luma_w,
1790
572k
                        );
1791
572k
                    }
1792
1793
321k
                    for x in 0usize..8 {
1794
286k
                        let y0 = mby * 8;
1795
286k
                        let x0 = mbx * 8 + x;
1796
286k
1797
286k
                        loop_filter::macroblock_filter_vertical(
1798
286k
                            hev_threshold,
1799
286k
                            interior_limit,
1800
286k
                            mbedge_limit,
1801
286k
                            &mut self.frame.ubuf[..],
1802
286k
                            y0 * chroma_w + x0,
1803
286k
                            chroma_w,
1804
286k
                        );
1805
286k
                        loop_filter::macroblock_filter_vertical(
1806
286k
                            hev_threshold,
1807
286k
                            interior_limit,
1808
286k
                            mbedge_limit,
1809
286k
                            &mut self.frame.vbuf[..],
1810
286k
                            y0 * chroma_w + x0,
1811
286k
                            chroma_w,
1812
286k
                        );
1813
286k
                    }
1814
                }
1815
3.92k
            }
1816
1817
            //filter across horizontal subblock edges within the macroblock
1818
66.2k
            if do_subblock_filtering {
1819
36.5k
                if self.frame.filter_type {
1820
52.3k
                    for y in (4usize..16 - 1).step_by(4) {
1821
890k
                        for x in 0..16 {
1822
837k
                            let y0 = mby * 16 + y;
1823
837k
                            let x0 = mbx * 16 + x;
1824
837k
1825
837k
                            loop_filter::simple_segment_vertical(
1826
837k
                                sub_bedge_limit,
1827
837k
                                &mut self.frame.ybuf[..],
1828
837k
                                y0 * luma_w + x0,
1829
837k
                                luma_w,
1830
837k
                            );
1831
837k
                        }
1832
                    }
1833
                } else {
1834
57.1k
                    for y in (4usize..16 - 3).step_by(4) {
1835
971k
                        for x in 0..16 {
1836
914k
                            let y0 = mby * 16 + y;
1837
914k
                            let x0 = mbx * 16 + x;
1838
914k
1839
914k
                            loop_filter::subblock_filter_vertical(
1840
914k
                                hev_threshold,
1841
914k
                                interior_limit,
1842
914k
                                sub_bedge_limit,
1843
914k
                                &mut self.frame.ybuf[..],
1844
914k
                                y0 * luma_w + x0,
1845
914k
                                luma_w,
1846
914k
                            );
1847
914k
                        }
1848
                    }
1849
1850
171k
                    for x in 0..8 {
1851
152k
                        let y0 = mby * 8 + 4;
1852
152k
                        let x0 = mbx * 8 + x;
1853
152k
1854
152k
                        loop_filter::subblock_filter_vertical(
1855
152k
                            hev_threshold,
1856
152k
                            interior_limit,
1857
152k
                            sub_bedge_limit,
1858
152k
                            &mut self.frame.ubuf[..],
1859
152k
                            y0 * chroma_w + x0,
1860
152k
                            chroma_w,
1861
152k
                        );
1862
152k
1863
152k
                        loop_filter::subblock_filter_vertical(
1864
152k
                            hev_threshold,
1865
152k
                            interior_limit,
1866
152k
                            sub_bedge_limit,
1867
152k
                            &mut self.frame.vbuf[..],
1868
152k
                            y0 * chroma_w + x0,
1869
152k
                            chroma_w,
1870
152k
                        );
1871
152k
                    }
1872
                }
1873
29.7k
            }
1874
4.41k
        }
1875
70.6k
    }
1876
1877
    //return values are the filter level, interior limit and hev threshold
1878
1.34M
    fn calculate_filter_parameters(&self, macroblock: &MacroBlock) -> (u8, u8, u8) {
1879
1.34M
        let segment = self.segment[macroblock.segmentid as usize];
1880
1.34M
        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.34M
        if filter_level == 0 {
1884
3.75k
            return (0, 0, 0);
1885
1.34M
        }
1886
1887
1.34M
        if self.segments_enabled {
1888
990k
            if segment.delta_values {
1889
765k
                filter_level += i32::from(segment.loopfilter_level);
1890
765k
            } else {
1891
224k
                filter_level = i32::from(segment.loopfilter_level);
1892
224k
            }
1893
355k
        }
1894
1895
1.34M
        filter_level = filter_level.clamp(0, 63);
1896
1897
1.34M
        if self.loop_filter_adjustments_enabled {
1898
899k
            filter_level += self.ref_delta[0];
1899
899k
            if macroblock.luma_mode == LumaMode::B {
1900
388k
                filter_level += self.mode_delta[0];
1901
510k
            }
1902
446k
        }
1903
1904
1.34M
        let filter_level = filter_level.clamp(0, 63) as u8;
1905
1906
        //interior limit
1907
1.34M
        let mut interior_limit = filter_level;
1908
1909
1.34M
        if self.frame.sharpness_level > 0 {
1910
911k
            interior_limit >>= if self.frame.sharpness_level > 4 { 2 } else { 1 };
1911
1912
911k
            if interior_limit > 9 - self.frame.sharpness_level {
1913
773k
                interior_limit = 9 - self.frame.sharpness_level;
1914
773k
            }
1915
434k
        }
1916
1917
1.34M
        if interior_limit == 0 {
1918
115k
            interior_limit = 1;
1919
1.22M
        }
1920
1921
        //high edge variance threshold
1922
1.34M
        let mut hev_threshold = 0;
1923
1924
        #[allow(clippy::collapsible_else_if)]
1925
1.34M
        if self.frame.keyframe {
1926
1.34M
            if filter_level >= 40 {
1927
798k
                hev_threshold = 2;
1928
798k
            } else if filter_level >= 15 {
1929
220k
                hev_threshold = 1;
1930
326k
            }
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.34M
        (filter_level, interior_limit, hev_threshold)
1942
1.34M
    }
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::calculate_filter_parameters
Line
Count
Source
1878
1.27M
    fn calculate_filter_parameters(&self, macroblock: &MacroBlock) -> (u8, u8, u8) {
1879
1.27M
        let segment = self.segment[macroblock.segmentid as usize];
1880
1.27M
        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.27M
        if filter_level == 0 {
1884
504
            return (0, 0, 0);
1885
1.27M
        }
1886
1887
1.27M
        if self.segments_enabled {
1888
944k
            if segment.delta_values {
1889
741k
                filter_level += i32::from(segment.loopfilter_level);
1890
741k
            } else {
1891
203k
                filter_level = i32::from(segment.loopfilter_level);
1892
203k
            }
1893
333k
        }
1894
1895
1.27M
        filter_level = filter_level.clamp(0, 63);
1896
1897
1.27M
        if self.loop_filter_adjustments_enabled {
1898
860k
            filter_level += self.ref_delta[0];
1899
860k
            if macroblock.luma_mode == LumaMode::B {
1900
365k
                filter_level += self.mode_delta[0];
1901
495k
            }
1902
418k
        }
1903
1904
1.27M
        let filter_level = filter_level.clamp(0, 63) as u8;
1905
1906
        //interior limit
1907
1.27M
        let mut interior_limit = filter_level;
1908
1909
1.27M
        if self.frame.sharpness_level > 0 {
1910
869k
            interior_limit >>= if self.frame.sharpness_level > 4 { 2 } else { 1 };
1911
1912
869k
            if interior_limit > 9 - self.frame.sharpness_level {
1913
747k
                interior_limit = 9 - self.frame.sharpness_level;
1914
747k
            }
1915
408k
        }
1916
1917
1.27M
        if interior_limit == 0 {
1918
114k
            interior_limit = 1;
1919
1.16M
        }
1920
1921
        //high edge variance threshold
1922
1.27M
        let mut hev_threshold = 0;
1923
1924
        #[allow(clippy::collapsible_else_if)]
1925
1.27M
        if self.frame.keyframe {
1926
1.27M
            if filter_level >= 40 {
1927
793k
                hev_threshold = 2;
1928
793k
            } else if filter_level >= 15 {
1929
193k
                hev_threshold = 1;
1930
291k
            }
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.27M
        (filter_level, interior_limit, hev_threshold)
1942
1.27M
    }
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::calculate_filter_parameters
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::calculate_filter_parameters
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::calculate_filter_parameters
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::calculate_filter_parameters
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::calculate_filter_parameters
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::calculate_filter_parameters
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::calculate_filter_parameters
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::calculate_filter_parameters
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::calculate_filter_parameters
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::calculate_filter_parameters
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::calculate_filter_parameters
Line
Count
Source
1878
70.6k
    fn calculate_filter_parameters(&self, macroblock: &MacroBlock) -> (u8, u8, u8) {
1879
70.6k
        let segment = self.segment[macroblock.segmentid as usize];
1880
70.6k
        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
70.6k
        if filter_level == 0 {
1884
3.24k
            return (0, 0, 0);
1885
67.3k
        }
1886
1887
67.3k
        if self.segments_enabled {
1888
46.0k
            if segment.delta_values {
1889
24.8k
                filter_level += i32::from(segment.loopfilter_level);
1890
24.8k
            } else {
1891
21.2k
                filter_level = i32::from(segment.loopfilter_level);
1892
21.2k
            }
1893
21.3k
        }
1894
1895
67.3k
        filter_level = filter_level.clamp(0, 63);
1896
1897
67.3k
        if self.loop_filter_adjustments_enabled {
1898
38.9k
            filter_level += self.ref_delta[0];
1899
38.9k
            if macroblock.luma_mode == LumaMode::B {
1900
23.1k
                filter_level += self.mode_delta[0];
1901
23.1k
            }
1902
28.4k
        }
1903
1904
67.3k
        let filter_level = filter_level.clamp(0, 63) as u8;
1905
1906
        //interior limit
1907
67.3k
        let mut interior_limit = filter_level;
1908
1909
67.3k
        if self.frame.sharpness_level > 0 {
1910
41.4k
            interior_limit >>= if self.frame.sharpness_level > 4 { 2 } else { 1 };
1911
1912
41.4k
            if interior_limit > 9 - self.frame.sharpness_level {
1913
26.7k
                interior_limit = 9 - self.frame.sharpness_level;
1914
26.7k
            }
1915
25.9k
        }
1916
1917
67.3k
        if interior_limit == 0 {
1918
1.22k
            interior_limit = 1;
1919
66.1k
        }
1920
1921
        //high edge variance threshold
1922
67.3k
        let mut hev_threshold = 0;
1923
1924
        #[allow(clippy::collapsible_else_if)]
1925
67.3k
        if self.frame.keyframe {
1926
67.3k
            if filter_level >= 40 {
1927
5.67k
                hev_threshold = 2;
1928
61.7k
            } else if filter_level >= 15 {
1929
27.1k
                hev_threshold = 1;
1930
34.5k
            }
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
67.3k
        (filter_level, interior_limit, hev_threshold)
1942
70.6k
    }
1943
1944
    /// Decodes the current frame
1945
1.34k
    pub fn decode_frame(r: R) -> Result<Frame, DecodingError> {
1946
1.34k
        let decoder = Self::new(r);
1947
1.34k
        decoder.decode_frame_()
1948
1.34k
    }
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame
Line
Count
Source
1945
813
    pub fn decode_frame(r: R) -> Result<Frame, DecodingError> {
1946
813
        let decoder = Self::new(r);
1947
813
        decoder.decode_frame_()
1948
813
    }
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::decode_frame
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame
Line
Count
Source
1945
535
    pub fn decode_frame(r: R) -> Result<Frame, DecodingError> {
1946
535
        let decoder = Self::new(r);
1947
535
        decoder.decode_frame_()
1948
535
    }
1949
1950
1.34k
    fn decode_frame_(mut self) -> Result<Frame, DecodingError> {
1951
1.34k
        self.read_frame_header()?;
1952
1953
33.9k
        for mby in 0..self.mbheight as usize {
1954
33.9k
            let p = mby % self.num_partitions as usize;
1955
33.9k
            self.left = MacroBlock::default();
1956
1957
2.15M
            for mbx in 0..self.mbwidth as usize {
1958
2.15M
                let mut mb = self.read_macroblock_header(mbx)?;
1959
2.15M
                let blocks = if !mb.coeffs_skipped {
1960
446k
                    self.read_residual_data(&mut mb, mbx, p)?
1961
                } else {
1962
1.71M
                    if mb.luma_mode != LumaMode::B {
1963
970k
                        self.left.complexity[0] = 0;
1964
970k
                        self.top[mbx].complexity[0] = 0;
1965
970k
                    }
1966
1967
15.4M
                    for i in 1usize..9 {
1968
13.6M
                        self.left.complexity[i] = 0;
1969
13.6M
                        self.top[mbx].complexity[i] = 0;
1970
13.6M
                    }
1971
1972
1.71M
                    [0i32; 384]
1973
                };
1974
1975
2.15M
                self.intra_predict_luma(mbx, mby, &mb, &blocks);
1976
2.15M
                self.intra_predict_chroma(mbx, mby, &mb, &blocks);
1977
1978
2.15M
                self.macroblocks.push(mb);
1979
            }
1980
1981
33.5k
            self.left_border_y = vec![129u8; 1 + 16];
1982
33.5k
            self.left_border_u = vec![129u8; 1 + 8];
1983
33.5k
            self.left_border_v = vec![129u8; 1 + 8];
1984
        }
1985
1986
        //do loop filtering
1987
22.1k
        for mby in 0..self.mbheight as usize {
1988
1.34M
            for mbx in 0..self.mbwidth as usize {
1989
1.34M
                let mb = self.macroblocks[mby * self.mbwidth as usize + mbx];
1990
1.34M
                self.loop_filter(mbx, mby, &mb);
1991
1.34M
            }
1992
        }
1993
1994
756
        Ok(self.frame)
1995
1.34k
    }
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame_
Line
Count
Source
1950
813
    fn decode_frame_(mut self) -> Result<Frame, DecodingError> {
1951
813
        self.read_frame_header()?;
1952
1953
22.2k
        for mby in 0..self.mbheight as usize {
1954
22.2k
            let p = mby % self.num_partitions as usize;
1955
22.2k
            self.left = MacroBlock::default();
1956
1957
2.00M
            for mbx in 0..self.mbwidth as usize {
1958
2.00M
                let mut mb = self.read_macroblock_header(mbx)?;
1959
2.00M
                let blocks = if !mb.coeffs_skipped {
1960
368k
                    self.read_residual_data(&mut mb, mbx, p)?
1961
                } else {
1962
1.63M
                    if mb.luma_mode != LumaMode::B {
1963
930k
                        self.left.complexity[0] = 0;
1964
930k
                        self.top[mbx].complexity[0] = 0;
1965
930k
                    }
1966
1967
14.6M
                    for i in 1usize..9 {
1968
13.0M
                        self.left.complexity[i] = 0;
1969
13.0M
                        self.top[mbx].complexity[i] = 0;
1970
13.0M
                    }
1971
1972
1.63M
                    [0i32; 384]
1973
                };
1974
1975
2.00M
                self.intra_predict_luma(mbx, mby, &mb, &blocks);
1976
2.00M
                self.intra_predict_chroma(mbx, mby, &mb, &blocks);
1977
1978
2.00M
                self.macroblocks.push(mb);
1979
            }
1980
1981
22.0k
            self.left_border_y = vec![129u8; 1 + 16];
1982
22.0k
            self.left_border_u = vec![129u8; 1 + 8];
1983
22.0k
            self.left_border_v = vec![129u8; 1 + 8];
1984
        }
1985
1986
        //do loop filtering
1987
15.0k
        for mby in 0..self.mbheight as usize {
1988
1.27M
            for mbx in 0..self.mbwidth as usize {
1989
1.27M
                let mb = self.macroblocks[mby * self.mbwidth as usize + mbx];
1990
1.27M
                self.loop_filter(mbx, mby, &mb);
1991
1.27M
            }
1992
        }
1993
1994
454
        Ok(self.frame)
1995
813
    }
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<_>>::decode_frame_
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame_
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame_
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame_
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame_
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame_
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame_
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame_
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame_
Unexecuted instantiation: <image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame_
<image_webp::vp8::Vp8Decoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame_
Line
Count
Source
1950
535
    fn decode_frame_(mut self) -> Result<Frame, DecodingError> {
1951
535
        self.read_frame_header()?;
1952
1953
11.6k
        for mby in 0..self.mbheight as usize {
1954
11.6k
            let p = mby % self.num_partitions as usize;
1955
11.6k
            self.left = MacroBlock::default();
1956
1957
157k
            for mbx in 0..self.mbwidth as usize {
1958
157k
                let mut mb = self.read_macroblock_header(mbx)?;
1959
157k
                let blocks = if !mb.coeffs_skipped {
1960
78.3k
                    self.read_residual_data(&mut mb, mbx, p)?
1961
                } else {
1962
78.9k
                    if mb.luma_mode != LumaMode::B {
1963
39.9k
                        self.left.complexity[0] = 0;
1964
39.9k
                        self.top[mbx].complexity[0] = 0;
1965
39.9k
                    }
1966
1967
710k
                    for i in 1usize..9 {
1968
631k
                        self.left.complexity[i] = 0;
1969
631k
                        self.top[mbx].complexity[i] = 0;
1970
631k
                    }
1971
1972
78.9k
                    [0i32; 384]
1973
                };
1974
1975
157k
                self.intra_predict_luma(mbx, mby, &mb, &blocks);
1976
157k
                self.intra_predict_chroma(mbx, mby, &mb, &blocks);
1977
1978
157k
                self.macroblocks.push(mb);
1979
            }
1980
1981
11.4k
            self.left_border_y = vec![129u8; 1 + 16];
1982
11.4k
            self.left_border_u = vec![129u8; 1 + 8];
1983
11.4k
            self.left_border_v = vec![129u8; 1 + 8];
1984
        }
1985
1986
        //do loop filtering
1987
7.15k
        for mby in 0..self.mbheight as usize {
1988
70.6k
            for mbx in 0..self.mbwidth as usize {
1989
70.6k
                let mb = self.macroblocks[mby * self.mbwidth as usize + mbx];
1990
70.6k
                self.loop_filter(mbx, mby, &mb);
1991
70.6k
            }
1992
        }
1993
1994
302
        Ok(self.frame)
1995
535
    }
1996
}
1997
1998
impl LumaMode {
1999
2.15M
    const fn from_i8(val: i8) -> Option<Self> {
2000
2.15M
        Some(match val {
2001
376k
            DC_PRED => Self::DC,
2002
160k
            V_PRED => Self::V,
2003
263k
            H_PRED => Self::H,
2004
355k
            TM_PRED => Self::TM,
2005
1.00M
            B_PRED => Self::B,
2006
0
            _ => return None,
2007
        })
2008
2.15M
    }
2009
2010
2.15M
    const fn into_intra(self) -> Option<IntraMode> {
2011
2.15M
        Some(match self {
2012
376k
            Self::DC => IntraMode::DC,
2013
160k
            Self::V => IntraMode::VE,
2014
263k
            Self::H => IntraMode::HE,
2015
355k
            Self::TM => IntraMode::TM,
2016
1.00M
            Self::B => return None,
2017
        })
2018
2.15M
    }
2019
}
2020
2021
impl ChromaMode {
2022
2.15M
    const fn from_i8(val: i8) -> Option<Self> {
2023
2.15M
        Some(match val {
2024
1.09M
            DC_PRED => Self::DC,
2025
365k
            V_PRED => Self::V,
2026
284k
            H_PRED => Self::H,
2027
412k
            TM_PRED => Self::TM,
2028
0
            _ => return None,
2029
        })
2030
2.15M
    }
2031
}
2032
2033
impl IntraMode {
2034
16.0M
    const fn from_i8(val: i8) -> Option<Self> {
2035
16.0M
        Some(match val {
2036
10.2M
            B_DC_PRED => Self::DC,
2037
2.20M
            B_TM_PRED => Self::TM,
2038
957k
            B_VE_PRED => Self::VE,
2039
697k
            B_HE_PRED => Self::HE,
2040
286k
            B_LD_PRED => Self::LD,
2041
245k
            B_RD_PRED => Self::RD,
2042
334k
            B_VR_PRED => Self::VR,
2043
386k
            B_VL_PRED => Self::VL,
2044
309k
            B_HD_PRED => Self::HD,
2045
393k
            B_HU_PRED => Self::HU,
2046
0
            _ => return None,
2047
        })
2048
16.0M
    }
2049
}
2050
2051
1.32k
fn init_top_macroblocks(width: usize) -> Vec<MacroBlock> {
2052
1.32k
    let mb_width = width.div_ceil(16);
2053
2054
1.32k
    let mb = MacroBlock {
2055
1.32k
        // Section 11.3 #3
2056
1.32k
        bpred: [IntraMode::DC; 16],
2057
1.32k
        luma_mode: LumaMode::DC,
2058
1.32k
        ..MacroBlock::default()
2059
1.32k
    };
2060
2061
1.32k
    vec![mb; mb_width]
2062
1.32k
}
2063
2064
2.15M
fn create_border_luma(mbx: usize, mby: usize, mbw: usize, top: &[u8], left: &[u8]) -> [u8; 357] {
2065
2.15M
    let stride = 1usize + 16 + 4;
2066
2.15M
    let mut ws = [0u8; (1 + 16) * (1 + 16 + 4)];
2067
2068
    // A
2069
    {
2070
2.15M
        let above = &mut ws[1..stride];
2071
2.15M
        if mby == 0 {
2072
1.76M
            for above in above.iter_mut() {
2073
1.76M
                *above = 127;
2074
1.76M
            }
2075
        } else {
2076
33.1M
            for (above, &top) in above[..16].iter_mut().zip(&top[mbx * 16..]) {
2077
33.1M
                *above = top;
2078
33.1M
            }
2079
2080
2.07M
            if mbx == mbw - 1 {
2081
128k
                for above in &mut above[16..] {
2082
128k
                    *above = top[mbx * 16 + 15];
2083
128k
                }
2084
            } else {
2085
8.15M
                for (above, &top) in above[16..].iter_mut().zip(&top[mbx * 16 + 16..]) {
2086
8.15M
                    *above = top;
2087
8.15M
                }
2088
            }
2089
        }
2090
    }
2091
2092
8.63M
    for i in 17usize..stride {
2093
8.63M
        ws[4 * stride + i] = ws[i];
2094
8.63M
        ws[8 * stride + i] = ws[i];
2095
8.63M
        ws[12 * stride + i] = ws[i];
2096
8.63M
    }
2097
2098
    // L
2099
2.15M
    if mbx == 0 {
2100
570k
        for i in 0usize..16 {
2101
536k
            ws[(i + 1) * stride] = 129;
2102
536k
        }
2103
    } else {
2104
33.9M
        for (i, &left) in (0usize..16).zip(&left[1..]) {
2105
33.9M
            ws[(i + 1) * stride] = left;
2106
33.9M
        }
2107
    }
2108
2109
    // P
2110
2.15M
    ws[0] = if mby == 0 {
2111
88.2k
        127
2112
2.07M
    } else if mbx == 0 {
2113
32.3k
        129
2114
    } else {
2115
2.03M
        left[0]
2116
    };
2117
2118
2.15M
    ws
2119
2.15M
}
2120
2121
const CHROMA_BLOCK_SIZE: usize = (8 + 1) * (8 + 1);
2122
// creates the left and top border for chroma prediction
2123
4.31M
fn create_border_chroma(
2124
4.31M
    mbx: usize,
2125
4.31M
    mby: usize,
2126
4.31M
    top: &[u8],
2127
4.31M
    left: &[u8],
2128
4.31M
) -> [u8; CHROMA_BLOCK_SIZE] {
2129
4.31M
    let stride: usize = 1usize + 8;
2130
4.31M
    let mut chroma_block = [0u8; CHROMA_BLOCK_SIZE];
2131
2132
    // above
2133
    {
2134
4.31M
        let above = &mut chroma_block[1..stride];
2135
4.31M
        if mby == 0 {
2136
1.41M
            for above in above.iter_mut() {
2137
1.41M
                *above = 127;
2138
1.41M
            }
2139
        } else {
2140
33.1M
            for (above, &top) in above.iter_mut().zip(&top[mbx * 8..]) {
2141
33.1M
                *above = top;
2142
33.1M
            }
2143
        }
2144
    }
2145
2146
    // left
2147
4.31M
    if mbx == 0 {
2148
603k
        for y in 0usize..8 {
2149
536k
            chroma_block[(y + 1) * stride] = 129;
2150
536k
        }
2151
    } else {
2152
33.9M
        for (y, &left) in (0usize..8).zip(&left[1..]) {
2153
33.9M
            chroma_block[(y + 1) * stride] = left;
2154
33.9M
        }
2155
    }
2156
2157
4.31M
    chroma_block[0] = if mby == 0 {
2158
176k
        127
2159
4.14M
    } else if mbx == 0 {
2160
64.7k
        129
2161
    } else {
2162
4.07M
        left[0]
2163
    };
2164
2165
4.31M
    chroma_block
2166
4.31M
}
2167
2168
// set border
2169
4.31M
fn set_chroma_border(
2170
4.31M
    left_border: &mut [u8],
2171
4.31M
    top_border: &mut [u8],
2172
4.31M
    chroma_block: &[u8],
2173
4.31M
    mbx: usize,
2174
4.31M
) {
2175
4.31M
    let stride = 1usize + 8;
2176
    // top left is top right of previous chroma block
2177
4.31M
    left_border[0] = chroma_block[8];
2178
2179
    // left border
2180
34.5M
    for (i, left) in left_border[1..][..8].iter_mut().enumerate() {
2181
34.5M
        *left = chroma_block[(i + 1) * stride + 8];
2182
34.5M
    }
2183
2184
34.5M
    for (top, &w) in top_border[mbx * 8..][..8]
2185
4.31M
        .iter_mut()
2186
4.31M
        .zip(&chroma_block[8 * stride + 1..][..8])
2187
34.5M
    {
2188
34.5M
        *top = w;
2189
34.5M
    }
2190
4.31M
}
2191
2192
21.5M
fn avg3(left: u8, this: u8, right: u8) -> u8 {
2193
21.5M
    let avg = (u16::from(left) + 2 * u16::from(this) + u16::from(right) + 2) >> 2;
2194
21.5M
    avg as u8
2195
21.5M
}
2196
2197
9.17M
fn avg2(this: u8, right: u8) -> u8 {
2198
9.17M
    let avg = (u16::from(this) + u16::from(right) + 1) >> 1;
2199
9.17M
    avg as u8
2200
9.17M
}
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
51.8M
fn add_residue(pblock: &mut [u8], rblock: &[i32; 16], y0: usize, x0: usize, stride: usize) {
2208
51.8M
    let mut pos = y0 * stride + x0;
2209
207M
    for row in rblock.chunks(4) {
2210
828M
        for (p, &a) in pblock[pos..][..4].iter_mut().zip(row.iter()) {
2211
828M
            *p = (a + i32::from(*p)).max(0).min(255) as u8;
2212
828M
        }
2213
207M
        pos += stride;
2214
    }
2215
51.8M
}
2216
2217
1.00M
fn predict_4x4(ws: &mut [u8], stride: usize, modes: &[IntraMode], resdata: &[i32]) {
2218
5.01M
    for sby in 0usize..4 {
2219
20.0M
        for sbx in 0usize..4 {
2220
16.0M
            let i = sbx + sby * 4;
2221
16.0M
            let y0 = sby * 4 + 1;
2222
16.0M
            let x0 = sbx * 4 + 1;
2223
2224
16.0M
            match modes[i] {
2225
2.20M
                IntraMode::TM => predict_tmpred(ws, 4, x0, y0, stride),
2226
957k
                IntraMode::VE => predict_bvepred(ws, x0, y0, stride),
2227
697k
                IntraMode::HE => predict_bhepred(ws, x0, y0, stride),
2228
10.2M
                IntraMode::DC => predict_bdcpred(ws, x0, y0, stride),
2229
286k
                IntraMode::LD => predict_bldpred(ws, x0, y0, stride),
2230
245k
                IntraMode::RD => predict_brdpred(ws, x0, y0, stride),
2231
334k
                IntraMode::VR => predict_bvrpred(ws, x0, y0, stride),
2232
386k
                IntraMode::VL => predict_bvlpred(ws, x0, y0, stride),
2233
309k
                IntraMode::HD => predict_bhdpred(ws, x0, y0, stride),
2234
392k
                IntraMode::HU => predict_bhupred(ws, x0, y0, stride),
2235
            }
2236
2237
16.0M
            let rb: &[i32; 16] = resdata[i * 16..][..16].try_into().unwrap();
2238
16.0M
            add_residue(ws, rb, y0, x0, stride);
2239
        }
2240
    }
2241
1.00M
}
2242
2243
891k
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
891k
    let (above, curr) = a.split_at_mut(stride * y0);
2246
891k
    let above_slice = &above[x0..];
2247
2248
8.41M
    for curr_chunk in curr.chunks_exact_mut(stride).take(size) {
2249
98.1M
        for (curr, &above) in curr_chunk[1..].iter_mut().zip(above_slice) {
2250
98.1M
            *curr = above;
2251
98.1M
        }
2252
    }
2253
891k
}
2254
2255
831k
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
8.75M
    for chunk in a.chunks_exact_mut(stride).skip(y0).take(size) {
2258
8.75M
        let left = chunk[x0 - 1];
2259
120M
        chunk[x0..].iter_mut().for_each(|a| *a = left);
2260
    }
2261
831k
}
2262
2263
2.56M
fn predict_dcpred(a: &mut [u8], size: usize, stride: usize, above: bool, left: bool) {
2264
2.56M
    let mut sum = 0;
2265
2.56M
    let mut shf = if size == 8 { 2 } else { 3 };
2266
2267
2.56M
    if left {
2268
23.2M
        for y in 0usize..size {
2269
23.2M
            sum += u32::from(a[(y + 1) * stride]);
2270
23.2M
        }
2271
2272
2.53M
        shf += 1;
2273
37.9k
    }
2274
2275
2.56M
    if above {
2276
22.6M
        sum += a[1..=size].iter().fold(0, |acc, &x| acc + u32::from(x));
2277
2278
2.46M
        shf += 1;
2279
98.9k
    }
2280
2281
2.56M
    let dcval = if !left && !above {
2282
1.91k
        128
2283
    } else {
2284
2.56M
        (sum + (1 << (shf - 1))) >> shf
2285
    };
2286
2287
23.5M
    for y in 0usize..size {
2288
23.5M
        a[1 + stride * (y + 1)..][..size]
2289
23.5M
            .iter_mut()
2290
236M
            .for_each(|a| *a = dcval as u8);
2291
    }
2292
2.56M
}
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.38M
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.38M
    let (above, x_block) = a.split_at_mut(y0 * stride + (x0 - 1));
2315
3.38M
    let p = i32::from(above[(y0 - 1) * stride + x0 - 1]);
2316
3.38M
    let above_slice = &above[(y0 - 1) * stride + x0..];
2317
2318
21.1M
    for y in 0usize..size {
2319
21.1M
        let left_minus_p = i32::from(x_block[y * stride]) - p;
2320
2321
        // Add 1 to skip over L0 byte
2322
21.1M
        x_block[y * stride + 1..][..size]
2323
21.1M
            .iter_mut()
2324
21.1M
            .zip(above_slice)
2325
179M
            .for_each(|(cur, &abv)| *cur = (left_minus_p + i32::from(abv)).max(0).min(255) as u8);
2326
    }
2327
3.38M
}
2328
2329
10.2M
fn predict_bdcpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2330
10.2M
    let mut v = 4;
2331
2332
10.2M
    a[(y0 - 1) * stride + x0..][..4]
2333
10.2M
        .iter()
2334
40.9M
        .for_each(|&a| v += u32::from(a));
2335
2336
51.1M
    for i in 0usize..4 {
2337
40.9M
        v += u32::from(a[(y0 + i) * stride + x0 - 1]);
2338
40.9M
    }
2339
2340
10.2M
    v >>= 3;
2341
40.9M
    for chunk in a.chunks_exact_mut(stride).skip(y0).take(4) {
2342
163M
        for ch in &mut chunk[x0..][..4] {
2343
163M
            *ch = v as u8;
2344
163M
        }
2345
    }
2346
10.2M
}
2347
2348
1.65M
fn topleft_pixel(a: &[u8], x0: usize, y0: usize, stride: usize) -> u8 {
2349
1.65M
    a[(y0 - 1) * stride + x0 - 1]
2350
1.65M
}
2351
2352
1.62M
fn top_pixels(a: &[u8], x0: usize, y0: usize, stride: usize) -> (u8, u8, u8, u8, u8, u8, u8, u8) {
2353
1.62M
    let pos = (y0 - 1) * stride + x0;
2354
1.62M
    let a_slice = &a[pos..pos + 8];
2355
1.62M
    let a0 = a_slice[0];
2356
1.62M
    let a1 = a_slice[1];
2357
1.62M
    let a2 = a_slice[2];
2358
1.62M
    let a3 = a_slice[3];
2359
1.62M
    let a4 = a_slice[4];
2360
1.62M
    let a5 = a_slice[5];
2361
1.62M
    let a6 = a_slice[6];
2362
1.62M
    let a7 = a_slice[7];
2363
2364
1.62M
    (a0, a1, a2, a3, a4, a5, a6, a7)
2365
1.62M
}
2366
2367
1.09M
fn left_pixels(a: &[u8], x0: usize, y0: usize, stride: usize) -> (u8, u8, u8, u8) {
2368
1.09M
    let l0 = a[y0 * stride + x0 - 1];
2369
1.09M
    let l1 = a[(y0 + 1) * stride + x0 - 1];
2370
1.09M
    let l2 = a[(y0 + 2) * stride + x0 - 1];
2371
1.09M
    let l3 = a[(y0 + 3) * stride + x0 - 1];
2372
2373
1.09M
    (l0, l1, l2, l3)
2374
1.09M
}
2375
2376
889k
fn edge_pixels(
2377
889k
    a: &[u8],
2378
889k
    x0: usize,
2379
889k
    y0: usize,
2380
889k
    stride: usize,
2381
889k
) -> (u8, u8, u8, u8, u8, u8, u8, u8, u8) {
2382
889k
    let pos = (y0 - 1) * stride + x0 - 1;
2383
889k
    let a_slice = &a[pos..=pos + 4];
2384
889k
    let e0 = a[pos + 4 * stride];
2385
889k
    let e1 = a[pos + 3 * stride];
2386
889k
    let e2 = a[pos + 2 * stride];
2387
889k
    let e3 = a[pos + stride];
2388
889k
    let e4 = a_slice[0];
2389
889k
    let e5 = a_slice[1];
2390
889k
    let e6 = a_slice[2];
2391
889k
    let e7 = a_slice[3];
2392
889k
    let e8 = a_slice[4];
2393
2394
889k
    (e0, e1, e2, e3, e4, e5, e6, e7, e8)
2395
889k
}
2396
2397
957k
fn predict_bvepred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2398
957k
    let p = topleft_pixel(a, x0, y0, stride);
2399
957k
    let (a0, a1, a2, a3, a4, ..) = top_pixels(a, x0, y0, stride);
2400
957k
    let avg_1 = avg3(p, a0, a1);
2401
957k
    let avg_2 = avg3(a0, a1, a2);
2402
957k
    let avg_3 = avg3(a1, a2, a3);
2403
957k
    let avg_4 = avg3(a2, a3, a4);
2404
2405
957k
    let avg = [avg_1, avg_2, avg_3, avg_4];
2406
2407
957k
    let mut pos = y0 * stride + x0;
2408
4.78M
    for _ in 0..4 {
2409
3.82M
        a[pos..=pos + 3].copy_from_slice(&avg);
2410
3.82M
        pos += stride;
2411
3.82M
    }
2412
957k
}
2413
2414
697k
fn predict_bhepred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2415
697k
    let p = topleft_pixel(a, x0, y0, stride);
2416
697k
    let (l0, l1, l2, l3) = left_pixels(a, x0, y0, stride);
2417
2418
697k
    let avgs = [
2419
697k
        avg3(p, l0, l1),
2420
697k
        avg3(l0, l1, l2),
2421
697k
        avg3(l1, l2, l3),
2422
697k
        avg3(l2, l3, l3),
2423
697k
    ];
2424
2425
697k
    let mut pos = y0 * stride + x0;
2426
3.48M
    for avg in avgs {
2427
11.1M
        for a_p in &mut a[pos..=pos + 3] {
2428
11.1M
            *a_p = avg;
2429
11.1M
        }
2430
2.78M
        pos += stride;
2431
    }
2432
697k
}
2433
2434
286k
fn predict_bldpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2435
286k
    let (a0, a1, a2, a3, a4, a5, a6, a7) = top_pixels(a, x0, y0, stride);
2436
2437
286k
    let avgs = [
2438
286k
        avg3(a0, a1, a2),
2439
286k
        avg3(a1, a2, a3),
2440
286k
        avg3(a2, a3, a4),
2441
286k
        avg3(a3, a4, a5),
2442
286k
        avg3(a4, a5, a6),
2443
286k
        avg3(a5, a6, a7),
2444
286k
        avg3(a6, a7, a7),
2445
286k
    ];
2446
2447
286k
    let mut pos = y0 * stride + x0;
2448
2449
1.43M
    for i in 0..4 {
2450
1.14M
        a[pos..=pos + 3].copy_from_slice(&avgs[i..=i + 3]);
2451
1.14M
        pos += stride;
2452
1.14M
    }
2453
286k
}
2454
2455
245k
fn predict_brdpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2456
245k
    let (e0, e1, e2, e3, e4, e5, e6, e7, e8) = edge_pixels(a, x0, y0, stride);
2457
2458
245k
    let avgs = [
2459
245k
        avg3(e0, e1, e2),
2460
245k
        avg3(e1, e2, e3),
2461
245k
        avg3(e2, e3, e4),
2462
245k
        avg3(e3, e4, e5),
2463
245k
        avg3(e4, e5, e6),
2464
245k
        avg3(e5, e6, e7),
2465
245k
        avg3(e6, e7, e8),
2466
245k
    ];
2467
245k
    let mut pos = y0 * stride + x0;
2468
2469
1.22M
    for i in 0..4 {
2470
981k
        a[pos..=pos + 3].copy_from_slice(&avgs[3 - i..7 - i]);
2471
981k
        pos += stride;
2472
981k
    }
2473
245k
}
2474
2475
334k
fn predict_bvrpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2476
334k
    let (_, e1, e2, e3, e4, e5, e6, e7, e8) = edge_pixels(a, x0, y0, stride);
2477
2478
334k
    a[(y0 + 3) * stride + x0] = avg3(e1, e2, e3);
2479
334k
    a[(y0 + 2) * stride + x0] = avg3(e2, e3, e4);
2480
334k
    a[(y0 + 3) * stride + x0 + 1] = avg3(e3, e4, e5);
2481
334k
    a[(y0 + 1) * stride + x0] = avg3(e3, e4, e5);
2482
334k
    a[(y0 + 2) * stride + x0 + 1] = avg2(e4, e5);
2483
334k
    a[y0 * stride + x0] = avg2(e4, e5);
2484
334k
    a[(y0 + 3) * stride + x0 + 2] = avg3(e4, e5, e6);
2485
334k
    a[(y0 + 1) * stride + x0 + 1] = avg3(e4, e5, e6);
2486
334k
    a[(y0 + 2) * stride + x0 + 2] = avg2(e5, e6);
2487
334k
    a[y0 * stride + x0 + 1] = avg2(e5, e6);
2488
334k
    a[(y0 + 3) * stride + x0 + 3] = avg3(e5, e6, e7);
2489
334k
    a[(y0 + 1) * stride + x0 + 2] = avg3(e5, e6, e7);
2490
334k
    a[(y0 + 2) * stride + x0 + 3] = avg2(e6, e7);
2491
334k
    a[y0 * stride + x0 + 2] = avg2(e6, e7);
2492
334k
    a[(y0 + 1) * stride + x0 + 3] = avg3(e6, e7, e8);
2493
334k
    a[y0 * stride + x0 + 3] = avg2(e7, e8);
2494
334k
}
2495
2496
386k
fn predict_bvlpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2497
386k
    let (a0, a1, a2, a3, a4, a5, a6, a7) = top_pixels(a, x0, y0, stride);
2498
2499
386k
    a[y0 * stride + x0] = avg2(a0, a1);
2500
386k
    a[(y0 + 1) * stride + x0] = avg3(a0, a1, a2);
2501
386k
    a[(y0 + 2) * stride + x0] = avg2(a1, a2);
2502
386k
    a[y0 * stride + x0 + 1] = avg2(a1, a2);
2503
386k
    a[(y0 + 1) * stride + x0 + 1] = avg3(a1, a2, a3);
2504
386k
    a[(y0 + 3) * stride + x0] = avg3(a1, a2, a3);
2505
386k
    a[(y0 + 2) * stride + x0 + 1] = avg2(a2, a3);
2506
386k
    a[y0 * stride + x0 + 2] = avg2(a2, a3);
2507
386k
    a[(y0 + 3) * stride + x0 + 1] = avg3(a2, a3, a4);
2508
386k
    a[(y0 + 1) * stride + x0 + 2] = avg3(a2, a3, a4);
2509
386k
    a[(y0 + 2) * stride + x0 + 2] = avg2(a3, a4);
2510
386k
    a[y0 * stride + x0 + 3] = avg2(a3, a4);
2511
386k
    a[(y0 + 3) * stride + x0 + 2] = avg3(a3, a4, a5);
2512
386k
    a[(y0 + 1) * stride + x0 + 3] = avg3(a3, a4, a5);
2513
386k
    a[(y0 + 2) * stride + x0 + 3] = avg3(a4, a5, a6);
2514
386k
    a[(y0 + 3) * stride + x0 + 3] = avg3(a5, a6, a7);
2515
386k
}
2516
2517
309k
fn predict_bhdpred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2518
309k
    let (e0, e1, e2, e3, e4, e5, e6, e7, _) = edge_pixels(a, x0, y0, stride);
2519
2520
309k
    a[(y0 + 3) * stride + x0] = avg2(e0, e1);
2521
309k
    a[(y0 + 3) * stride + x0 + 1] = avg3(e0, e1, e2);
2522
309k
    a[(y0 + 2) * stride + x0] = avg2(e1, e2);
2523
309k
    a[(y0 + 3) * stride + x0 + 2] = avg2(e1, e2);
2524
309k
    a[(y0 + 2) * stride + x0 + 1] = avg3(e1, e2, e3);
2525
309k
    a[(y0 + 3) * stride + x0 + 3] = avg3(e1, e2, e3);
2526
309k
    a[(y0 + 2) * stride + x0 + 2] = avg2(e2, e3);
2527
309k
    a[(y0 + 1) * stride + x0] = avg2(e2, e3);
2528
309k
    a[(y0 + 2) * stride + x0 + 3] = avg3(e2, e3, e4);
2529
309k
    a[(y0 + 1) * stride + x0 + 1] = avg3(e2, e3, e4);
2530
309k
    a[(y0 + 1) * stride + x0 + 2] = avg2(e3, e4);
2531
309k
    a[y0 * stride + x0] = avg2(e3, e4);
2532
309k
    a[(y0 + 1) * stride + x0 + 3] = avg3(e3, e4, e5);
2533
309k
    a[y0 * stride + x0 + 1] = avg3(e3, e4, e5);
2534
309k
    a[y0 * stride + x0 + 2] = avg3(e4, e5, e6);
2535
309k
    a[y0 * stride + x0 + 3] = avg3(e5, e6, e7);
2536
309k
}
2537
2538
392k
fn predict_bhupred(a: &mut [u8], x0: usize, y0: usize, stride: usize) {
2539
392k
    let (l0, l1, l2, l3) = left_pixels(a, x0, y0, stride);
2540
2541
392k
    a[y0 * stride + x0] = avg2(l0, l1);
2542
392k
    a[y0 * stride + x0 + 1] = avg3(l0, l1, l2);
2543
392k
    a[y0 * stride + x0 + 2] = avg2(l1, l2);
2544
392k
    a[(y0 + 1) * stride + x0] = avg2(l1, l2);
2545
392k
    a[y0 * stride + x0 + 3] = avg3(l1, l2, l3);
2546
392k
    a[(y0 + 1) * stride + x0 + 1] = avg3(l1, l2, l3);
2547
392k
    a[(y0 + 1) * stride + x0 + 2] = avg2(l2, l3);
2548
392k
    a[(y0 + 2) * stride + x0] = avg2(l2, l3);
2549
392k
    a[(y0 + 1) * stride + x0 + 3] = avg3(l2, l3, l3);
2550
392k
    a[(y0 + 2) * stride + x0 + 1] = avg3(l2, l3, l3);
2551
392k
    a[(y0 + 2) * stride + x0 + 2] = l3;
2552
392k
    a[(y0 + 2) * stride + x0 + 3] = l3;
2553
392k
    a[(y0 + 3) * stride + x0] = l3;
2554
392k
    a[(y0 + 3) * stride + x0 + 1] = l3;
2555
392k
    a[(y0 + 3) * stride + x0 + 2] = l3;
2556
392k
    a[(y0 + 3) * stride + x0 + 3] = l3;
2557
392k
}
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
}