Coverage Report

Created: 2026-10-28 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibGfx/ImageFormats/WebPLoaderLossy.cpp
Line
Count
Source
1
/*
2
 * Copyright (c) 2023, Nico Weber <thakis@chromium.org>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#include <AK/Debug.h>
8
#include <AK/Endian.h>
9
#include <AK/Format.h>
10
#include <AK/MemoryStream.h>
11
#include <AK/Vector.h>
12
#include <LibGfx/ImageFormats/BooleanDecoder.h>
13
#include <LibGfx/ImageFormats/WebPLoaderLossy.h>
14
#include <LibGfx/ImageFormats/WebPLoaderLossyTables.h>
15
16
// Lossy format: https://datatracker.ietf.org/doc/html/rfc6386
17
18
// Summary:
19
// A lossy webp image is a VP8 keyframe.
20
// A VP8 keyframe consists of 16x16 pixel tiles called macroblocks. Each macroblock is subdivided into 4x4 pixel tiles called subblocks.
21
// Pixel values are stored as YUV 4:2:0. That is, each 4x4 luma pixels are covered by 1 pixel U chroma and 1 pixel V chroma.
22
// This means one macroblock is covered by 4x4 Y subblocks and 2x2 U and V subblocks each.
23
// VP8 data consists of:
24
// * A tiny bit of uncompressed data, storing image dimensions and the size of the first compressed chunk of data, called the first partition
25
// * The first partition, which is a entropy-coded bitstream storing:
26
//   1. A fixed-size header.
27
//      The main piece of data this stores is a probability distribution for how pixel values of each macroblock are predicted from previously decoded data.
28
//      It also stores how may independent entropy-coded bitstreams are used to store the actual pixel data (for all images I've seen so far, just one).
29
//   2. For each macroblock, it stores how that macroblock's pixel values are predicted from previously decoded data (and some more per-macroblock metadata).
30
//      There are independent prediction modes for Y, U, V.
31
//      U and V store a single prediction mode per macroblock.
32
//      Y can store a single prediction mode per macroblock, or it can store one subblock prediction mode for each of the 4x4 luma subblocks.
33
// * One or more additional entropy-coded bitstreams ("partitions") that store the discrete cosine transform ("DCT") coefficients for the actual pixel data for each macroblock.
34
//   Each macroblock is subdivided into 4x4 tiles called "subblocks". A 16x16 pixel macroblock consists of:
35
//   0. If the macroblock stores 4x4 luma subblock prediction modes, the 4x4 DC coefficients of each subblock's DCT are stored at the start of the macroblock's data,
36
//      as coefficients of an inverse Walsh-Hadamard Transform (WHT).
37
//   1. 4x4 luma subblocks
38
//   2. 2x2 U chrome subblocks
39
//   3. 2x2 U chrome subblocks
40
//   That is, each macroblock stores 24 or 25 sets of coefficients.
41
//   Each set of coefficients stores 16 numbers, using a combination of a custom prefix tree and dequantization.
42
//   The inverse DCT output is added to the output of the prediction.
43
44
namespace Gfx {
45
46
// https://developers.google.com/speed/webp/docs/riff_container#simple_file_format_lossy
47
// https://datatracker.ietf.org/doc/html/rfc6386#section-19 "Annex A: Bitstream Syntax"
48
ErrorOr<VP8Header> decode_webp_chunk_VP8_header(ReadonlyBytes vp8_data)
49
1.93k
{
50
1.93k
    if (vp8_data.size() < 3)
51
6
        return Error::from_string_literal("WebPImageDecoderPlugin: 'VP8 ' chunk too small");
52
1.93k
    unsigned frame_tag_size = 3;
53
54
    // FIXME: Eventually, this should probably call into LibVideo/VP8,
55
    // and image decoders should move into LibImageDecoders which depends on both LibGfx and LibVideo.
56
    // (LibVideo depends on LibGfx, so LibGfx can't depend on LibVideo itself.)
57
58
    // https://datatracker.ietf.org/doc/html/rfc6386#section-4 "Overview of Compressed Data Format"
59
    // "The decoder is simply presented with a sequence of compressed frames [...]
60
    //  The first frame presented to the decompressor is [...] a key frame.  [...]
61
    //  [E]very compressed frame has three or more pieces. It begins with an uncompressed data chunk comprising 10 bytes in the case of key frames"
62
63
1.93k
    u8 const* data = vp8_data.data();
64
65
    // https://datatracker.ietf.org/doc/html/rfc6386#section-9.1 "Uncompressed Data Chunk"
66
1.93k
    u32 frame_tag = data[0] | (data[1] << 8) | (data[2] << 16);
67
1.93k
    bool is_key_frame = (frame_tag & 1) == 0; // https://www.rfc-editor.org/errata/eid5534
68
1.93k
    u8 version = (frame_tag & 0xe) >> 1;
69
1.93k
    bool show_frame = (frame_tag & 0x10) != 0;
70
1.93k
    u32 size_of_first_partition = frame_tag >> 5;
71
72
1.93k
    if (version > 3)
73
3
        return Error::from_string_literal("WebPImageDecoderPlugin: unknown version number in 'VP8 ' chunk");
74
75
1.92k
    Optional<VP8Header::KeyframeData> keyframe_data;
76
1.92k
    if (is_key_frame) {
77
1.91k
        if (vp8_data.size() < 10)
78
2
            return Error::from_string_literal("WebPImageDecoderPlugin: 'VP8 ' keyframe chunk too small");
79
1.91k
        frame_tag_size = 10;
80
81
1.91k
        u32 start_code = data[3] | (data[4] << 8) | (data[5] << 16);
82
1.91k
        if (start_code != 0x2a019d) // https://www.rfc-editor.org/errata/eid7370
83
41
            return Error::from_string_literal("WebPImageDecoderPlugin: 'VP8 ' chunk invalid start_code");
84
85
        // "The scaling specifications for each dimension are encoded as follows.
86
        //   0     | No upscaling (the most common case).
87
        //   1     | Upscale by 5/4.
88
        //   2     | Upscale by 5/3.
89
        //   3     | Upscale by 2."
90
        // This is a display-time operation and doesn't affect decoding."
91
1.87k
        u16 width_and_horizontal_scale = data[6] | (data[7] << 8);
92
1.87k
        u16 width = width_and_horizontal_scale & 0x3fff;
93
1.87k
        u8 horizontal_scale = width_and_horizontal_scale >> 14;
94
95
1.87k
        u16 height_and_vertical_scale = data[8] | (data[9] << 8);
96
1.87k
        u16 height = height_and_vertical_scale & 0x3fff;
97
1.87k
        u8 vertical_scale = height_and_vertical_scale >> 14;
98
99
1.87k
        dbgln_if(WEBP_DEBUG, "version {}, show_frame {}, size_of_first_partition {}, width {}, horizontal_scale {}, height {}, vertical_scale {}",
100
1.87k
            version, show_frame, size_of_first_partition, width, horizontal_scale, height, vertical_scale);
101
102
1.87k
        keyframe_data = VP8Header::KeyframeData { width, horizontal_scale, height, vertical_scale };
103
1.87k
    } else {
104
9
        dbgln_if(WEBP_DEBUG, "version {}, show_frame {}, size_of_first_partition {}",
105
9
            version, show_frame, size_of_first_partition);
106
9
    }
107
108
1.88k
    if (vp8_data.size() < frame_tag_size + size_of_first_partition)
109
16
        return Error::from_string_literal("WebPImageDecoderPlugin: 'VP8 ' chunk too small for full first partition");
110
111
1.86k
    return VP8Header { version, show_frame, keyframe_data, vp8_data.slice(frame_tag_size), vp8_data.slice(frame_tag_size + size_of_first_partition) };
112
1.88k
}
113
114
namespace {
115
116
// Reads n bits followed by a sign bit (0: positive, 1: negative).
117
i8 read_signed_literal(BooleanDecoder& decoder, u8 n)
118
2.09k
{
119
2.09k
    VERIFY(n <= 7);
120
2.09k
    i8 i = decoder.read_literal(n);
121
2.09k
    if (decoder.read_literal(1))
122
855
        i = -i;
123
2.09k
    return i;
124
2.09k
}
125
126
// https://datatracker.ietf.org/doc/html/rfc6386#section-19 "Annex A: Bitstream Syntax"
127
37.5k
#define L(n) decoder.read_literal(n)
128
422M
#define B(prob) decoder.read_bool(prob)
129
2.09k
#define L_signed(n) read_signed_literal(decoder, n)
130
131
// https://datatracker.ietf.org/doc/html/rfc6386#section-9.3 Segment-Based Adjustments"
132
// https://datatracker.ietf.org/doc/html/rfc6386#section-19.2 "Frame Header"
133
enum class SegmentFeatureMode {
134
    // Spec 19.2 says 0 is delta, 1 absolute; spec 9.3 has it the other way round. 19.2 is correct.
135
    // https://www.rfc-editor.org/errata/eid7519
136
    DeltaValueMode = 0,
137
    AbsoluteValueMode = 1,
138
139
};
140
struct Segmentation {
141
    bool update_macroblock_segmentation_map { false };
142
    SegmentFeatureMode segment_feature_mode { SegmentFeatureMode::DeltaValueMode };
143
144
    i8 quantizer_update_value[4] {};
145
    i8 loop_filter_update_value[4] {};
146
147
    u8 macroblock_segment_tree_probabilities[3] = { 255, 255, 255 };
148
};
149
Segmentation decode_VP8_frame_header_segmentation(BooleanDecoder&);
150
151
// Also https://datatracker.ietf.org/doc/html/rfc6386#section-9.6 "Dequantization Indices"
152
struct QuantizationIndices {
153
    u8 y_ac { 0 };
154
    i8 y_dc_delta { 0 };
155
156
    i8 y2_dc_delta { 0 };
157
    i8 y2_ac_delta { 0 };
158
159
    i8 uv_dc_delta { 0 };
160
    i8 uv_ac_delta { 0 };
161
};
162
QuantizationIndices decode_VP8_frame_header_quantization_indices(BooleanDecoder&);
163
164
struct LoopFilterAdjustment {
165
    bool enable_loop_filter_adjustment { false };
166
    i8 ref_frame_delta[4] {};
167
    i8 mb_mode_delta[4] {};
168
};
169
LoopFilterAdjustment decode_VP8_frame_header_loop_filter_adjustment(BooleanDecoder&);
170
171
using CoefficientProbabilities = Prob[4][8][3][num_dct_tokens - 1];
172
ErrorOr<void> decode_VP8_frame_header_coefficient_probabilities(BooleanDecoder&, CoefficientProbabilities);
173
174
// https://datatracker.ietf.org/doc/html/rfc6386#section-15 "Loop Filter"
175
// "The first is a flag (filter_type) selecting the type of filter (normal or simple)"
176
enum class FilterType {
177
    Normal = 0,
178
    Simple = 1,
179
};
180
181
// https://datatracker.ietf.org/doc/html/rfc6386#section-9.2 "Color Space and Pixel Type (Key Frames Only)"
182
enum class ColorSpaceAndPixelType {
183
    YUV = 0,
184
    ReservedForFutureUse = 1,
185
};
186
enum class ClampingSpecification {
187
    DecoderMustClampTo0To255 = 0,
188
    NoClampingNecessary = 1,
189
};
190
191
// https://datatracker.ietf.org/doc/html/rfc6386#section-19.2 "Frame Header"
192
struct FrameHeader {
193
    ColorSpaceAndPixelType color_space {};
194
    ClampingSpecification clamping_type {};
195
196
    bool is_segmentation_enabled {};
197
    Segmentation segmentation {};
198
199
    FilterType filter_type {};
200
    u8 loop_filter_level {};
201
    u8 sharpness_level {};
202
    LoopFilterAdjustment loop_filter_adjustment {};
203
204
    u8 number_of_dct_partitions {};
205
206
    QuantizationIndices quantization_indices {};
207
208
    CoefficientProbabilities coefficient_probabilities;
209
210
    bool enable_skipping_of_macroblocks_containing_only_zero_coefficients {};
211
    u8 probability_skip_false;
212
};
213
214
ErrorOr<FrameHeader> decode_VP8_frame_header(BooleanDecoder& decoder)
215
1.03k
{
216
    // https://datatracker.ietf.org/doc/html/rfc6386#section-19.2 "Frame Header"
217
1.03k
    FrameHeader header;
218
219
    // In the VP8 spec, this is in an `if (key_frames)`, but webp files only have key frames.
220
1.03k
    header.color_space = ColorSpaceAndPixelType { L(1) };
221
1.03k
    header.clamping_type = ClampingSpecification { L(1) };
222
1.03k
    dbgln_if(WEBP_DEBUG, "color_space {} clamping_type {}", (int)header.color_space, (int)header.clamping_type);
223
224
    // https://datatracker.ietf.org/doc/html/rfc6386#section-9.3 "Segment-Based Adjustments"
225
1.03k
    header.is_segmentation_enabled = L(1);
226
1.03k
    dbgln_if(WEBP_DEBUG, "segmentation_enabled {}", header.is_segmentation_enabled);
227
228
1.03k
    if (header.is_segmentation_enabled)
229
202
        header.segmentation = decode_VP8_frame_header_segmentation(decoder);
230
231
1.03k
    header.filter_type = FilterType { L(1) };
232
1.03k
    header.loop_filter_level = L(6);
233
1.03k
    header.sharpness_level = L(3);
234
1.03k
    dbgln_if(WEBP_DEBUG, "filter_type {} loop_filter_level {} sharpness_level {}", (int)header.filter_type, header.loop_filter_level, header.sharpness_level);
235
236
1.03k
    header.loop_filter_adjustment = decode_VP8_frame_header_loop_filter_adjustment(decoder);
237
238
1.03k
    u8 log2_nbr_of_dct_partitions = L(2);
239
1.03k
    dbgln_if(WEBP_DEBUG, "log2_nbr_of_dct_partitions {}", log2_nbr_of_dct_partitions);
240
1.03k
    header.number_of_dct_partitions = 1 << log2_nbr_of_dct_partitions;
241
242
1.03k
    header.quantization_indices = decode_VP8_frame_header_quantization_indices(decoder);
243
244
    // In the VP8 spec, this is in an `if (key_frames)` followed by a lengthy `else`, but webp files only have key frames.
245
1.03k
    u8 refresh_entropy_probs = L(1); // Has no effect in webp files.
246
1.03k
    dbgln_if(WEBP_DEBUG, "refresh_entropy_probs {}", refresh_entropy_probs);
247
248
1.03k
    memcpy(header.coefficient_probabilities, DEFAULT_COEFFICIENT_PROBABILITIES, sizeof(header.coefficient_probabilities));
249
1.03k
    TRY(decode_VP8_frame_header_coefficient_probabilities(decoder, header.coefficient_probabilities));
250
251
    // https://datatracker.ietf.org/doc/html/rfc6386#section-9.11 "Remaining Frame Header Data (Key Frame)"
252
1.03k
    header.enable_skipping_of_macroblocks_containing_only_zero_coefficients = L(1);
253
1.03k
    dbgln_if(WEBP_DEBUG, "mb_no_skip_coeff {}", header.enable_skipping_of_macroblocks_containing_only_zero_coefficients);
254
1.03k
    if (header.enable_skipping_of_macroblocks_containing_only_zero_coefficients) {
255
207
        header.probability_skip_false = L(8);
256
207
        dbgln_if(WEBP_DEBUG, "prob_skip_false {}", header.probability_skip_false);
257
207
    }
258
259
    // In the VP8 spec, there is a length `if (!key_frames)` here, but webp files only have key frames.
260
261
1.03k
    return header;
262
1.03k
}
263
264
Segmentation decode_VP8_frame_header_segmentation(BooleanDecoder& decoder)
265
202
{
266
    // Corresponds to "update_segmentation()" in section 19.2 of the spec.
267
202
    Segmentation segmentation;
268
269
202
    segmentation.update_macroblock_segmentation_map = L(1);
270
202
    u8 update_segment_feature_data = L(1);
271
272
202
    dbgln_if(WEBP_DEBUG, "update_mb_segmentation_map {} update_segment_feature_data {}",
273
202
        segmentation.update_macroblock_segmentation_map, update_segment_feature_data);
274
275
202
    if (update_segment_feature_data) {
276
111
        segmentation.segment_feature_mode = static_cast<SegmentFeatureMode>(L(1));
277
111
        dbgln_if(WEBP_DEBUG, "segment_feature_mode {}", (int)segmentation.segment_feature_mode);
278
279
555
        for (int i = 0; i < 4; ++i) {
280
444
            u8 quantizer_update = L(1);
281
444
            dbgln_if(WEBP_DEBUG, "quantizer_update {}", quantizer_update);
282
444
            if (quantizer_update) {
283
248
                i8 quantizer_update_value = L_signed(7);
284
248
                dbgln_if(WEBP_DEBUG, "quantizer_update_value {}", quantizer_update_value);
285
248
                segmentation.quantizer_update_value[i] = quantizer_update_value;
286
248
            }
287
444
        }
288
555
        for (int i = 0; i < 4; ++i) {
289
444
            u8 loop_filter_update = L(1);
290
444
            dbgln_if(WEBP_DEBUG, "loop_filter_update {}", loop_filter_update);
291
444
            if (loop_filter_update) {
292
155
                i8 loop_filter_update_value = L_signed(6);
293
155
                dbgln_if(WEBP_DEBUG, "loop_filter_update_value {}", loop_filter_update_value);
294
155
                segmentation.loop_filter_update_value[i] = loop_filter_update_value;
295
155
            }
296
444
        }
297
111
    }
298
299
202
    if (segmentation.update_macroblock_segmentation_map) {
300
        // This reads mb_segment_tree_probs for https://datatracker.ietf.org/doc/html/rfc6386#section-10.
301
596
        for (int i = 0; i < 3; ++i) {
302
447
            u8 segment_prob_update = L(1);
303
447
            dbgln_if(WEBP_DEBUG, "segment_prob_update {}", segment_prob_update);
304
447
            if (segment_prob_update) {
305
150
                u8 segment_prob = L(8);
306
150
                dbgln_if(WEBP_DEBUG, "segment_prob {}", segment_prob);
307
150
                segmentation.macroblock_segment_tree_probabilities[i] = segment_prob;
308
150
            }
309
447
        }
310
149
    }
311
312
202
    return segmentation;
313
202
}
314
315
QuantizationIndices decode_VP8_frame_header_quantization_indices(BooleanDecoder& decoder)
316
1.03k
{
317
    // Corresponds to "quant_indices()" in section 19.2 of the spec.
318
1.03k
    QuantizationIndices quantization_indices;
319
320
    // "The first 7-bit index gives the dequantization table index for
321
    //  Y-plane AC coefficients, called yac_qi.  It is always coded and acts
322
    //  as a baseline for the other 5 quantization indices, each of which is
323
    //  represented by a delta from this baseline index."
324
1.03k
    quantization_indices.y_ac = L(7);
325
1.03k
    dbgln_if(WEBP_DEBUG, "y_ac_qi {}", quantization_indices.y_ac);
326
327
5.18k
    auto read_delta = [&decoder](StringView name, i8* destination) -> void {
328
5.18k
        u8 is_present = L(1);
329
5.18k
        dbgln_if(WEBP_DEBUG, "{}_present {}", name, is_present);
330
5.18k
        if (is_present) {
331
1.38k
            i8 delta = L_signed(4);
332
1.38k
            dbgln_if(WEBP_DEBUG, "{} {}", name, delta);
333
1.38k
            *destination = delta;
334
1.38k
        }
335
5.18k
    };
336
1.03k
    read_delta("y_dc_delta"sv, &quantization_indices.y_dc_delta);
337
1.03k
    read_delta("y2_dc_delta"sv, &quantization_indices.y2_dc_delta);
338
1.03k
    read_delta("y2_ac_delta"sv, &quantization_indices.y2_ac_delta);
339
1.03k
    read_delta("uv_dc_delta"sv, &quantization_indices.uv_dc_delta);
340
1.03k
    read_delta("uv_ac_delta"sv, &quantization_indices.uv_ac_delta);
341
342
1.03k
    return quantization_indices;
343
1.03k
}
344
345
LoopFilterAdjustment decode_VP8_frame_header_loop_filter_adjustment(BooleanDecoder& decoder)
346
1.03k
{
347
    // Corresponds to "mb_lf_adjustments()" in section 19.2 of the spec.
348
1.03k
    LoopFilterAdjustment adjustment;
349
350
1.03k
    adjustment.enable_loop_filter_adjustment = L(1);
351
1.03k
    if (adjustment.enable_loop_filter_adjustment) {
352
186
        u8 mode_ref_lf_delta_update = L(1);
353
186
        dbgln_if(WEBP_DEBUG, "mode_ref_lf_delta_update {}", mode_ref_lf_delta_update);
354
186
        if (mode_ref_lf_delta_update) {
355
555
            for (int i = 0; i < 4; ++i) {
356
444
                u8 ref_frame_delta_update_flag = L(1);
357
444
                dbgln_if(WEBP_DEBUG, "ref_frame_delta_update_flag {}", ref_frame_delta_update_flag);
358
444
                if (ref_frame_delta_update_flag) {
359
178
                    i8 delta = L_signed(6);
360
178
                    dbgln_if(WEBP_DEBUG, "delta {}", delta);
361
178
                    adjustment.ref_frame_delta[i] = delta;
362
178
                }
363
444
            }
364
555
            for (int i = 0; i < 4; ++i) {
365
444
                u8 mb_mode_delta_update_flag = L(1);
366
444
                dbgln_if(WEBP_DEBUG, "mb_mode_delta_update_flag {}", mb_mode_delta_update_flag);
367
444
                if (mb_mode_delta_update_flag) {
368
130
                    i8 delta = L_signed(6);
369
130
                    dbgln_if(WEBP_DEBUG, "delta {}", delta);
370
130
                    adjustment.mb_mode_delta[i] = delta;
371
130
                }
372
444
            }
373
111
        }
374
186
    }
375
376
1.03k
    return adjustment;
377
1.03k
}
378
379
ErrorOr<void> decode_VP8_frame_header_coefficient_probabilities(BooleanDecoder& decoder, CoefficientProbabilities coefficient_probabilities)
380
1.03k
{
381
    // Corresponds to "token_prob_update()" in section 19.2 of the spec.
382
5.18k
    for (int i = 0; i < 4; i++) {
383
37.2k
        for (int j = 0; j < 8; j++) {
384
132k
            for (int k = 0; k < 3; k++) {
385
1.19M
                for (int l = 0; l < 11; l++) {
386
                    // token_prob_update() says L(1) and L(8), but it's actually B(p) and L(8).
387
                    // https://datatracker.ietf.org/doc/html/rfc6386#section-13.4 "Token Probability Updates" describes it correctly.
388
1.09M
                    if (B(COEFFICIENT_UPDATE_PROBABILITIES[i][j][k][l]))
389
17.6k
                        coefficient_probabilities[i][j][k][l] = L(8);
390
1.09M
                }
391
99.4k
            }
392
33.1k
        }
393
4.14k
    }
394
395
1.03k
    return {};
396
1.03k
}
397
398
// https://datatracker.ietf.org/doc/html/rfc6386#section-8.1 "Tree Coding Implementation"
399
u8 tree_decode(BooleanDecoder& decoder, ReadonlySpan<TreeIndex> tree, ReadonlyBytes probabilities, TreeIndex initial_i = 0)
400
382M
{
401
382M
    TreeIndex i = initial_i;
402
419M
    while (true) {
403
419M
        u8 b = B(probabilities[i >> 1]);
404
419M
        i = tree[i + b];
405
419M
        if (i <= 0)
406
382M
            return -i;
407
419M
    }
408
382M
}
409
410
// Similar to BlockContext in LibVideo/VP9/Context.h
411
struct MacroblockMetadata {
412
    // https://datatracker.ietf.org/doc/html/rfc6386#section-10 "Segment-Based Feature Adjustments"
413
    // Read only if `update_mb_segmentation_map` is set.
414
    u8 segment_id { 0 }; // 0, 1, 2, or 3. Fits in two bits.
415
416
    // https://datatracker.ietf.org/doc/html/rfc6386#section-11.1 "mb_skip_coeff"
417
    bool skip_coefficients { false };
418
419
    IntraMacroblockMode intra_y_mode;
420
    IntraMacroblockMode uv_mode;
421
422
    IntraBlockMode intra_b_modes[16];
423
};
424
425
ErrorOr<Vector<MacroblockMetadata>> decode_VP8_macroblock_metadata(BooleanDecoder& decoder, FrameHeader const& header, int macroblock_width, int macroblock_height)
426
1.03k
{
427
    // https://datatracker.ietf.org/doc/html/rfc6386#section-19.3
428
429
    // Corresponds to "macroblock_header()" in section 19.3 of the spec.
430
431
1.03k
    Vector<MacroblockMetadata> macroblock_metadata;
432
433
    // Key frames must use intra prediction, that is new macroblocks are predicted from old macroblocks in the same frame.
434
    // (Inter prediction on the other hand predicts new macroblocks from the corresponding macroblock in the previous frame.)
435
436
    // https://datatracker.ietf.org/doc/html/rfc6386#section-11.3 "Subblock Mode Contexts"
437
    // "For macroblocks on the top row or left edge of the image, some of
438
    //  the predictors will be non-existent.  Such predictors are taken
439
    //  to have had the value B_DC_PRED, which, perhaps conveniently,
440
    //  takes the value 0 in the enumeration above.
441
    //  A simple management scheme for these contexts might maintain a row
442
    //  of above predictors and four left predictors.  Before decoding the
443
    //  frame, the entire row is initialized to B_DC_PRED; before decoding
444
    //  each row of macroblocks, the four left predictors are also set to
445
    //  B_DC_PRED.  After decoding a macroblock, the bottom four subblock
446
    //  modes are copied into the row predictor (at the current position,
447
    //  which then advances to be above the next macroblock), and the
448
    //  right four subblock modes are copied into the left predictor."
449
1.03k
    Vector<IntraBlockMode> above;
450
1.03k
    TRY(above.try_resize(macroblock_width * 4)); // One per 4x4 subblock.
451
452
    // It's possible to not decode all macroblock metadata at once. Instead, this could for example decode one row of metadata,
453
    // then decode the coefficients for one row of macroblocks, convert that row to pixels, and then go on to the next row of macroblocks.
454
    // That'd require slightly less memory. But MacroblockMetadata is fairly small, and this way we can keep the context
455
    // (`above`, `left`) in stack variables instead of having to have a class for that. So keep it simple for now.
456
75.8k
    for (int mb_y = 0; mb_y < macroblock_height; ++mb_y) {
457
74.7k
        IntraBlockMode left[4] {};
458
459
20.6M
        for (int mb_x = 0; mb_x < macroblock_width; ++mb_x) {
460
20.5M
            MacroblockMetadata metadata;
461
462
20.5M
            if (header.segmentation.update_macroblock_segmentation_map)
463
6.08M
                metadata.segment_id = tree_decode(decoder, MACROBLOCK_SEGMENT_TREE, header.segmentation.macroblock_segment_tree_probabilities);
464
465
20.5M
            if (header.enable_skipping_of_macroblocks_containing_only_zero_coefficients)
466
1.72M
                metadata.skip_coefficients = B(header.probability_skip_false);
467
468
20.5M
            int intra_y_mode = tree_decode(decoder, KEYFRAME_YMODE_TREE, KEYFRAME_YMODE_PROBABILITIES);
469
20.5M
            metadata.intra_y_mode = (IntraMacroblockMode)intra_y_mode;
470
471
            // "If the Ymode is B_PRED, it is followed by a (tree-coded) mode for each of the 16 Y subblocks."
472
20.5M
            if (intra_y_mode == B_PRED) {
473
102M
                for (int y = 0; y < 4; ++y) {
474
409M
                    for (int x = 0; x < 4; ++x) {
475
                        // "The outer two dimensions of this array are indexed by the already-
476
                        //  coded subblock modes above and to the left of the current block,
477
                        //  respectively."
478
327M
                        int A = above[mb_x * 4 + x];
479
327M
                        int L = left[y];
480
481
327M
                        auto intra_b_mode = static_cast<IntraBlockMode>(tree_decode(decoder, BLOCK_MODE_TREE, KEYFRAME_BLOCK_MODE_PROBABILITIES[A][L]));
482
327M
                        metadata.intra_b_modes[y * 4 + x] = intra_b_mode;
483
484
327M
                        above[mb_x * 4 + x] = intra_b_mode;
485
327M
                        left[y] = intra_b_mode;
486
327M
                    }
487
81.9M
                }
488
20.4M
            } else {
489
64.9k
                VERIFY(intra_y_mode < B_PRED);
490
64.9k
                constexpr IntraBlockMode b_mode_from_y_mode[] = { B_DC_PRED, B_VE_PRED, B_HE_PRED, B_TM_PRED };
491
64.9k
                IntraBlockMode intra_b_mode = b_mode_from_y_mode[intra_y_mode];
492
324k
                for (int i = 0; i < 4; ++i) {
493
259k
                    above[mb_x * 4 + i] = intra_b_mode;
494
259k
                    left[i] = intra_b_mode;
495
259k
                }
496
64.9k
            }
497
498
20.5M
            metadata.uv_mode = (IntraMacroblockMode)tree_decode(decoder, UV_MODE_TREE, KEYFRAME_UV_MODE_PROBABILITIES);
499
500
20.5M
            TRY(macroblock_metadata.try_append(metadata));
501
20.5M
        }
502
74.7k
    }
503
504
1.03k
    return macroblock_metadata;
505
1.03k
}
506
507
// Every macroblock stores:
508
// - One optional set of coefficients for Y2
509
// - 16 sets of Y coefficients for the 4x4 Y subblocks of the macroblock
510
// - 4 sets of U coefficients for the 2x2 U subblocks of the macroblock
511
// - 4 sets of V coefficients for the 2x2 V subblocks of the macroblock
512
// That's 24 or 25 sets of coefficients total. This struct identifies one of these sets by index.
513
// If a macroblock does not have Y2, then i goes from [1..25], else it goes [0..25].
514
struct CoefficientBlockIndex {
515
    int i;
516
517
    CoefficientBlockIndex(int i)
518
3.40M
        : i(i)
519
3.40M
    {
520
3.40M
        VERIFY(i >= 0);
521
3.40M
        VERIFY(i <= 25);
522
3.40M
    }
523
524
32.9M
    bool is_y2() const { return i == 0; }
525
1.04M
    bool is_y() const { return i >= 1 && i <= 16; }
526
32.4M
    bool is_u() const { return i >= 17 && i <= 20; }
527
27.1M
    bool is_v() const { return i >= 21; }
528
529
    u8 sub_x() const
530
5.97M
    {
531
5.97M
        VERIFY(i > 0);
532
5.97M
        if (i <= 16)
533
3.98M
            return (i - 1) % 4;
534
1.99M
        if (i <= 20)
535
995k
            return (i - 17) % 2;
536
995k
        return (i - 21) % 2;
537
1.99M
    }
538
539
    u8 sub_y() const
540
5.97M
    {
541
5.97M
        VERIFY(i > 0);
542
5.97M
        if (i <= 16)
543
3.98M
            return (i - 1) / 4;
544
1.99M
        if (i <= 20)
545
995k
            return (i - 17) / 2;
546
995k
        return (i - 21) / 2;
547
1.99M
    }
548
};
549
550
int plane_index(CoefficientBlockIndex index, bool have_y2)
551
7.60M
{
552
    // https://datatracker.ietf.org/doc/html/rfc6386#section-13.3 "Token Probabilities"
553
    // "o  0 - Y beginning at coefficient 1 (i.e., Y after Y2)
554
    //  o  1 - Y2
555
    //  o  2 - U or V
556
    //  o  3 - Y beginning at coefficient 0 (i.e., Y in the absence of Y2)."
557
7.60M
    if (index.is_y2())
558
120k
        return 1;
559
7.48M
    if (index.is_u() || index.is_v())
560
2.46M
        return 2;
561
5.02M
    if (have_y2)
562
1.75M
        return 0;
563
3.26M
    return 3;
564
5.02M
}
565
566
i16 coefficient_value_for_token(BooleanDecoder& decoder, u8 token)
567
5.24M
{
568
    // Implements the second half of https://datatracker.ietf.org/doc/html/rfc6386#section-13.2 "Coding of Individual Coefficient Values"
569
5.24M
    i16 v = static_cast<i16>(token); // For DCT_0 to DCT4
570
571
5.24M
    if (token >= dct_cat1 && token <= dct_cat6) {
572
4.89M
        static int constexpr starts[] = { 5, 7, 11, 19, 35, 67 };
573
4.89M
        static int constexpr bits[] = { 1, 2, 3, 4, 5, 11 };
574
575
4.89M
        static Prob constexpr Pcat1[] = { 159 };
576
4.89M
        static Prob constexpr Pcat2[] = { 165, 145 };
577
4.89M
        static Prob constexpr Pcat3[] = { 173, 148, 140 };
578
4.89M
        static Prob constexpr Pcat4[] = { 176, 155, 140, 135 };
579
4.89M
        static Prob constexpr Pcat5[] = { 180, 157, 141, 134, 130 };
580
4.89M
        static Prob constexpr Pcat6[] = { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129 };
581
4.89M
        static Prob const* const Pcats[] = { Pcat1, Pcat2, Pcat3, Pcat4, Pcat5, Pcat6 };
582
583
4.89M
        v = 0;
584
585
        // This loop corresponds to `DCTextra` in the spec in section 13.2.
586
58.7M
        for (int i = 0; i < bits[token - dct_cat1]; ++i)
587
53.8M
            v = (v << 1) | decoder.read_bool(Pcats[token - dct_cat1][i]);
588
589
4.89M
        v += starts[token - dct_cat1];
590
4.89M
    }
591
592
5.24M
    if (v) {
593
5.11M
        if (decoder.read_bool(128))
594
5.00M
            v = -v;
595
5.11M
    }
596
597
5.24M
    return v;
598
5.24M
}
599
600
i16 dequantize_value(i16 value, bool is_dc, QuantizationIndices const& quantization_indices, Segmentation const& segmentation, int segment_id, CoefficientBlockIndex index)
601
5.24M
{
602
    // https://datatracker.ietf.org/doc/html/rfc6386#section-9.6 "Dequantization Indices"
603
    // "before inverting the transform, each decoded coefficient
604
    //  is multiplied by one of six dequantization factors, the choice of
605
    //  which depends on the plane (Y, chroma = U or V, Y2) and coefficient
606
    //  position (DC = coefficient 0, AC = coefficients 1-15).  The six
607
    //  values are specified using 7-bit indices into six corresponding fixed
608
    //  tables (the tables are given in Section 14)."
609
    // Section 14 then lists two (!) fixed tables (which are in WebPLoaderLossyTables.h)
610
611
    // "Lookup values from the above two tables are directly used in the DC
612
    //  and AC coefficients in Y1, respectively.  For Y2 and chroma, values
613
    //  from the above tables undergo either scaling or clamping before the
614
    //  multiplies.  Details regarding these scaling and clamping processes
615
    //  can be found in related lookup functions in dixie.c (Section 20.4)."
616
    // Apparently spec writing became too much work at this point. In section 20.4, in dequant_init():
617
    // * For y2, the output (!) of dc_qlookup is multiplied by 2, the output of ac_qlookup is multiplied by 155 / 100
618
    // * Also for y2, ac_qlookup is at least 8 for lower table entries
619
    // * For uv, the dc_qlookup index is clamped to 117 (instead of 127 for everything else)
620
    //   (or, alternatively, the value is clamped to 132 at most)
621
622
5.24M
    int y_ac_base = quantization_indices.y_ac;
623
5.24M
    if (segmentation.update_macroblock_segmentation_map) {
624
139k
        if (segmentation.segment_feature_mode == SegmentFeatureMode::DeltaValueMode)
625
38.8k
            y_ac_base += segmentation.quantizer_update_value[segment_id];
626
100k
        else
627
100k
            y_ac_base = segmentation.quantizer_update_value[segment_id];
628
139k
    }
629
630
5.24M
    int dequantization_index;
631
5.24M
    if (index.is_y2())
632
83.1k
        dequantization_index = y_ac_base + (is_dc ? quantization_indices.y2_dc_delta : quantization_indices.y2_ac_delta);
633
5.16M
    else if (index.is_u() || index.is_v())
634
1.68M
        dequantization_index = y_ac_base + (is_dc ? quantization_indices.uv_dc_delta : quantization_indices.uv_ac_delta);
635
3.47M
    else
636
3.47M
        dequantization_index = is_dc ? (y_ac_base + quantization_indices.y_dc_delta) : y_ac_base;
637
638
    // clamp index
639
5.24M
    if ((index.is_u() || index.is_v()) && is_dc)
640
129k
        dequantization_index = clamp(dequantization_index, 0, 117);
641
5.11M
    else
642
5.11M
        dequantization_index = clamp(dequantization_index, 0, 127);
643
644
    // "the multiplies are computed and stored using 16-bit signed integers."
645
5.24M
    i16 dequantization_factor;
646
5.24M
    if (is_dc)
647
336k
        dequantization_factor = (i16)dc_qlookup[dequantization_index];
648
4.90M
    else
649
4.90M
        dequantization_factor = (i16)ac_qlookup[dequantization_index];
650
651
5.24M
    if (index.is_y2()) {
652
83.1k
        if (is_dc)
653
7.18k
            dequantization_factor *= 2;
654
75.9k
        else
655
75.9k
            dequantization_factor = max((dequantization_factor * 155) / 100, 8);
656
83.1k
    }
657
658
5.24M
    return dequantization_factor * value;
659
5.24M
}
660
661
// Reading macroblock coefficients requires needing to know if the block to the left and above the current macroblock
662
// has non-zero coefficients. This stores that state.
663
struct CoefficientReadingContext {
664
    // Store if each plane has nonzero coefficients in the block above and to the left of the current block.
665
    Vector<bool> y2_above;
666
    Vector<bool> y_above;
667
    Vector<bool> u_above;
668
    Vector<bool> v_above;
669
670
    bool y2_left {};
671
    bool y_left[4] {};
672
    bool u_left[2] {};
673
    bool v_left[2] {};
674
675
    ErrorOr<void> initialize(int macroblock_width)
676
844
    {
677
844
        TRY(y2_above.try_resize(macroblock_width));
678
844
        TRY(y_above.try_resize(macroblock_width * 4));
679
844
        TRY(u_above.try_resize(macroblock_width * 2));
680
844
        TRY(v_above.try_resize(macroblock_width * 2));
681
844
        return {};
682
844
    }
683
684
    void start_new_row()
685
25.4k
    {
686
25.4k
        y2_left = false;
687
25.4k
        for (bool& b : y_left)
688
101k
            b = false;
689
25.4k
        for (bool& b : u_left)
690
50.9k
            b = false;
691
25.4k
        for (bool& b : v_left)
692
50.9k
            b = false;
693
25.4k
    }
694
695
    bool& was_above_nonzero(CoefficientBlockIndex index, int mb_x)
696
6.07M
    {
697
6.07M
        if (index.is_y2())
698
105k
            return y2_above[mb_x];
699
5.97M
        if (index.is_u())
700
995k
            return u_above[mb_x * 2 + index.sub_x()];
701
4.97M
        if (index.is_v())
702
995k
            return v_above[mb_x * 2 + index.sub_x()];
703
3.98M
        return y_above[mb_x * 4 + index.sub_x()];
704
4.97M
    }
705
0
    bool was_above_nonzero(CoefficientBlockIndex index, int mb_x) const { return const_cast<CoefficientReadingContext&>(*this).was_above_nonzero(index, mb_x); }
706
707
    bool& was_left_nonzero(CoefficientBlockIndex index)
708
6.07M
    {
709
6.07M
        if (index.is_y2())
710
105k
            return y2_left;
711
5.97M
        if (index.is_u())
712
995k
            return u_left[index.sub_y()];
713
4.97M
        if (index.is_v())
714
995k
            return v_left[index.sub_y()];
715
3.98M
        return y_left[index.sub_y()];
716
4.97M
    }
717
0
    bool was_left_nonzero(CoefficientBlockIndex index) const { return const_cast<CoefficientReadingContext&>(*this).was_left_nonzero(index); }
718
719
    void update(CoefficientBlockIndex index, int mb_x, bool subblock_has_nonzero_coefficients)
720
3.40M
    {
721
3.40M
        was_above_nonzero(index, mb_x) = subblock_has_nonzero_coefficients;
722
3.40M
        was_left_nonzero(index) = subblock_has_nonzero_coefficients;
723
3.40M
    }
724
};
725
726
using Coefficients = i16[16];
727
728
// Returns if any non-zero coefficients were read.
729
bool read_coefficent_block(BooleanDecoder& decoder, Coefficients out_coefficients, CoefficientBlockIndex block_index, CoefficientReadingContext& coefficient_reading_context, int mb_x, bool have_y2, int segment_id, FrameHeader const& header)
730
2.67M
{
731
    // Corresponds to `residual_block()` in https://datatracker.ietf.org/doc/html/rfc6386#section-19.3,
732
    // but also does dequantization of the stored values.
733
    // "firstCoeff is 1 for luma blocks of macroblocks containing Y2 subblock; otherwise 0"
734
2.67M
    int firstCoeff = have_y2 && block_index.is_y() ? 1 : 0;
735
2.67M
    i16 last_decoded_value = num_dct_tokens; // Start with an invalid value
736
737
2.67M
    bool subblock_has_nonzero_coefficients = false;
738
739
7.91M
    for (int j = firstCoeff; j < 16; ++j) {
740
        // https://datatracker.ietf.org/doc/html/rfc6386#section-13.2 "Coding of Individual Coefficient Values"
741
        // https://datatracker.ietf.org/doc/html/rfc6386#section-13.3 "Token Probabilities"
742
743
        // "Working from the outside in, the outermost dimension is indexed by
744
        //  the type of plane being decoded"
745
7.60M
        int plane = plane_index(block_index, have_y2);
746
747
        // "The next dimension is selected by the position of the coefficient
748
        //  being decoded.  That position, c, steps by ones up to 15, starting
749
        //  from zero for block types 1, 2, or 3 and starting from one for block
750
        //  type 0.  The second array index is then"
751
        // "block type" here seems to refer to the "type of plane" in the previous paragraph.
752
7.60M
        static int constexpr coeff_bands[16] = { 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7 };
753
7.60M
        int band = coeff_bands[j];
754
755
        // "The third dimension is the trickiest."
756
7.60M
        int tricky = 0;
757
758
        // "For the first coefficient (DC, unless the block type is 0), we
759
        //  consider the (already encoded) blocks within the same plane (Y2, Y,
760
        //  U, or V) above and to the left of the current block.  The context
761
        //  index is then the number (0, 1, or 2) of these blocks that had at
762
        //  least one non-zero coefficient in their residue record.  Specifically
763
        //  for Y2, because macroblocks above and to the left may or may not have
764
        //  a Y2 block, the block above is determined by the most recent
765
        //  macroblock in the same column that has a Y2 block, and the block to
766
        //  the left is determined by the most recent macroblock in the same row
767
        //  that has a Y2 block.
768
        //  [...]
769
        //  As with other contexts used by VP8, the "neighboring block" context
770
        //  described here needs a special definition for subblocks lying along
771
        //  the top row or left edge of the frame.  These "non-existent"
772
        //  predictors above and to the left of the image are simply taken to be
773
        //  empty -- that is, taken to contain no non-zero coefficients."
774
7.60M
        if (j == firstCoeff) {
775
2.67M
            bool was_left_nonzero = coefficient_reading_context.was_left_nonzero(block_index);
776
2.67M
            bool was_above_nonzero = coefficient_reading_context.was_above_nonzero(block_index, mb_x);
777
2.67M
            tricky = static_cast<int>(was_left_nonzero) + static_cast<int>(was_above_nonzero);
778
2.67M
        }
779
        // "Beyond the first coefficient, the context index is determined by the
780
        //  absolute value of the most recently decoded coefficient (necessarily
781
        //  within the current block) and is 0 if the last coefficient was a
782
        //  zero, 1 if it was plus or minus one, and 2 if its absolute value
783
        //  exceeded one."
784
4.93M
        else {
785
4.93M
            if (last_decoded_value == 0)
786
129k
                tricky = 0;
787
4.80M
            else if (last_decoded_value == 1 || last_decoded_value == -1)
788
174k
                tricky = 1;
789
4.62M
            else
790
4.62M
                tricky = 2;
791
4.93M
        }
792
793
        // "In general, all DCT coefficients are decoded using the same tree.
794
        //  However, if the preceding coefficient is a DCT_0, decoding will skip
795
        //  the first branch, since it is not possible for dct_eob to follow a
796
        //  DCT_0."
797
7.60M
        u8 token = tree_decode(decoder, COEFFICIENT_TREE, header.coefficient_probabilities[plane][band][tricky], last_decoded_value == DCT_0 ? 2 : 0);
798
7.60M
        if (token == dct_eob)
799
2.36M
            break;
800
801
5.24M
        i16 v = coefficient_value_for_token(decoder, token);
802
803
5.24M
        if (v) {
804
            // Subblock has non-0 coefficients. Store that, so that `tricky` on the next subblock is initialized correctly.
805
5.11M
            subblock_has_nonzero_coefficients = true;
806
5.11M
        }
807
808
        // last_decoded_value is used for setting `tricky`. It needs to be set to the last decoded token, not to the last dequantized value.
809
5.24M
        last_decoded_value = v;
810
811
5.24M
        i16 dequantized_value = dequantize_value(v, j == 0, header.quantization_indices, header.segmentation, segment_id, block_index);
812
813
5.24M
        static int constexpr Zigzag[] = { 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 };
814
5.24M
        out_coefficients[Zigzag[j]] = dequantized_value;
815
5.24M
    }
816
817
2.67M
    return subblock_has_nonzero_coefficients;
818
2.67M
}
819
820
struct MacroblockCoefficients {
821
    Coefficients y_coeffs[16] {};
822
    Coefficients u_coeffs[4] {};
823
    Coefficients v_coeffs[4] {};
824
};
825
826
MacroblockCoefficients read_macroblock_coefficients(BooleanDecoder& decoder, FrameHeader const& header, CoefficientReadingContext& coefficient_reading_context, MacroblockMetadata const& metadata, int mb_x)
827
139k
{
828
    // Corresponds to `residual_data()` in https://datatracker.ietf.org/doc/html/rfc6386#section-19.3,
829
    // but also does the inverse walsh-hadamard transform if a Y2 block is present.
830
831
139k
    MacroblockCoefficients coefficients;
832
139k
    Coefficients y2_coeffs {};
833
834
    // "firstCoeff is 1 for luma blocks of macroblocks containing Y2 subblock; otherwise 0"
835
836
    // https://datatracker.ietf.org/doc/html/rfc6386#section-13
837
838
    // "For all intra- and inter-prediction modes apart from B_PRED (intra:
839
    //  whose Y subblocks are independently predicted) and SPLITMV (inter),
840
    //  each macroblock's residue record begins with the Y2 component of the
841
    //  residue, coded using a WHT.  B_PRED and SPLITMV coded macroblocks
842
    //  omit this WHT and specify the 0th DCT coefficient in each of the 16 Y
843
    //  subblocks."
844
139k
    bool have_y2 = metadata.intra_y_mode != B_PRED;
845
846
    // "for Y2, because macroblocks above and to the left may or may not have
847
    //  a Y2 block, the block above is determined by the most recent
848
    //  macroblock in the same column that has a Y2 block, and the block to
849
    //  the left is determined by the most recent macroblock in the same row
850
    //  that has a Y2 block."
851
    // We only write to y2_above / y2_left when it's present, so we don't need to do any explicit work to get the right behavior.
852
853
    // "After the optional Y2 block, the residue record continues with 16
854
    //  DCTs for the Y subblocks, followed by 4 DCTs for the U subblocks,
855
    //  ending with 4 DCTs for the V subblocks.  The subblocks occur in the
856
    //  usual order."
857
858
    /* (1 Y2)?, 16 Y, 4 U, 4 V */
859
3.54M
    for (int i = have_y2 ? 0 : 1; i < 25; ++i) {
860
3.40M
        CoefficientBlockIndex block_index { i };
861
862
3.40M
        bool subblock_has_nonzero_coefficients = false;
863
864
3.40M
        if (!metadata.skip_coefficients) {
865
2.67M
            i16* to_read;
866
2.67M
            if (block_index.is_y2())
867
41.8k
                to_read = y2_coeffs;
868
2.63M
            else if (block_index.is_u())
869
438k
                to_read = coefficients.u_coeffs[i - 17];
870
2.19M
            else if (block_index.is_v())
871
438k
                to_read = coefficients.v_coeffs[i - 21];
872
1.75M
            else // Y
873
1.75M
                to_read = coefficients.y_coeffs[i - 1];
874
2.67M
            subblock_has_nonzero_coefficients = read_coefficent_block(decoder, to_read, block_index, coefficient_reading_context, mb_x, have_y2, metadata.segment_id, header);
875
2.67M
        }
876
877
3.40M
        coefficient_reading_context.update(block_index, mb_x, subblock_has_nonzero_coefficients);
878
3.40M
    }
879
880
    // https://datatracker.ietf.org/doc/html/rfc6386#section-14.2 "Inverse Transforms"
881
    // "If the Y2 residue block exists (i.e., the macroblock luma mode is not
882
    //  SPLITMV or B_PRED), it is inverted first (using the inverse WHT) and
883
    //  the element of the result at row i, column j is used as the 0th
884
    //  coefficient of the Y subblock at position (i, j), that is, the Y
885
    //  subblock whose index is (i * 4) + j."
886
139k
    if (have_y2) {
887
63.2k
        Coefficients wht_output;
888
63.2k
        vp8_short_inv_walsh4x4_c(y2_coeffs, wht_output);
889
1.07M
        for (size_t i = 0; i < 16; ++i)
890
1.01M
            coefficients.y_coeffs[i][0] = wht_output[i];
891
63.2k
    }
892
893
139k
    return coefficients;
894
139k
}
895
896
template<int N>
897
void predict_macroblock(Bytes prediction, IntraMacroblockMode mode, int mb_x, int mb_y, ReadonlyBytes left, ReadonlyBytes above, u8 truemotion_corner)
898
341k
{
899
    // https://datatracker.ietf.org/doc/html/rfc6386#section-12.2 "Chroma Prediction"
900
    // (Also used for the DC_PRED, H_PRED, V_PRED, TM_PRED for luma prediction.)
901
341k
    if (mode == DC_PRED) {
902
170k
        if (mb_x == 0 && mb_y == 0) {
903
103k
            for (size_t i = 0; i < N * N; ++i)
904
102k
                prediction[i] = 128;
905
169k
        } else {
906
169k
            int sum = 0, n = 0;
907
169k
            if (mb_x > 0) {
908
1.38M
                for (int i = 0; i < N; ++i)
909
1.24M
                    sum += left[i];
910
143k
                n += N;
911
143k
            }
912
169k
            if (mb_y > 0) {
913
1.25M
                for (int i = 0; i < N; ++i)
914
1.12M
                    sum += above[mb_x * N + i];
915
130k
                n += N;
916
130k
            }
917
169k
            u8 average = (sum + n / 2) / n;
918
13.7M
            for (size_t i = 0; i < N * N; ++i)
919
13.6M
                prediction[i] = average;
920
169k
        }
921
170k
    } else if (mode == H_PRED) {
922
363k
        for (int y = 0; y < N; ++y)
923
3.83M
            for (int x = 0; x < N; ++x)
924
3.50M
                prediction[y * N + x] = left[y];
925
136k
    } else if (mode == V_PRED) {
926
402k
        for (int y = 0; y < N; ++y)
927
4.32M
            for (int x = 0; x < N; ++x)
928
3.96M
                prediction[y * N + x] = above[mb_x * N + x];
929
98.6k
    } else {
930
98.6k
        VERIFY(mode == TM_PRED);
931
1.15M
        for (int y = 0; y < N; ++y)
932
13.8M
            for (int x = 0; x < N; ++x)
933
12.8M
                prediction[y * N + x] = clamp(left[y] + above[mb_x * N + x] - truemotion_corner, 0, 255);
934
98.6k
    }
935
341k
}
WebPLoaderLossy.cpp:void Gfx::(anonymous namespace)::predict_macroblock<16>(AK::Span<unsigned char>, Gfx::IntraMacroblockMode, int, int, AK::Span<unsigned char const>, AK::Span<unsigned char const>, unsigned char)
Line
Count
Source
898
63.2k
{
899
    // https://datatracker.ietf.org/doc/html/rfc6386#section-12.2 "Chroma Prediction"
900
    // (Also used for the DC_PRED, H_PRED, V_PRED, TM_PRED for luma prediction.)
901
63.2k
    if (mode == DC_PRED) {
902
14.3k
        if (mb_x == 0 && mb_y == 0) {
903
17.4k
            for (size_t i = 0; i < N * N; ++i)
904
17.4k
                prediction[i] = 128;
905
14.3k
        } else {
906
14.3k
            int sum = 0, n = 0;
907
14.3k
            if (mb_x > 0) {
908
199k
                for (int i = 0; i < N; ++i)
909
187k
                    sum += left[i];
910
11.7k
                n += N;
911
11.7k
            }
912
14.3k
            if (mb_y > 0) {
913
177k
                for (int i = 0; i < N; ++i)
914
167k
                    sum += above[mb_x * N + i];
915
10.4k
                n += N;
916
10.4k
            }
917
14.3k
            u8 average = (sum + n / 2) / n;
918
3.67M
            for (size_t i = 0; i < N * N; ++i)
919
3.66M
                prediction[i] = average;
920
14.3k
        }
921
48.8k
    } else if (mode == H_PRED) {
922
115k
        for (int y = 0; y < N; ++y)
923
1.84M
            for (int x = 0; x < N; ++x)
924
1.73M
                prediction[y * N + x] = left[y];
925
42.0k
    } else if (mode == V_PRED) {
926
138k
        for (int y = 0; y < N; ++y)
927
2.22M
            for (int x = 0; x < N; ++x)
928
2.08M
                prediction[y * N + x] = above[mb_x * N + x];
929
33.9k
    } else {
930
33.9k
        VERIFY(mode == TM_PRED);
931
576k
        for (int y = 0; y < N; ++y)
932
9.22M
            for (int x = 0; x < N; ++x)
933
8.68M
                prediction[y * N + x] = clamp(left[y] + above[mb_x * N + x] - truemotion_corner, 0, 255);
934
33.9k
    }
935
63.2k
}
WebPLoaderLossy.cpp:void Gfx::(anonymous namespace)::predict_macroblock<8>(AK::Span<unsigned char>, Gfx::IntraMacroblockMode, int, int, AK::Span<unsigned char const>, AK::Span<unsigned char const>, unsigned char)
Line
Count
Source
898
278k
{
899
    // https://datatracker.ietf.org/doc/html/rfc6386#section-12.2 "Chroma Prediction"
900
    // (Also used for the DC_PRED, H_PRED, V_PRED, TM_PRED for luma prediction.)
901
278k
    if (mode == DC_PRED) {
902
156k
        if (mb_x == 0 && mb_y == 0) {
903
86.0k
            for (size_t i = 0; i < N * N; ++i)
904
84.7k
                prediction[i] = 128;
905
155k
        } else {
906
155k
            int sum = 0, n = 0;
907
155k
            if (mb_x > 0) {
908
1.18M
                for (int i = 0; i < N; ++i)
909
1.05M
                    sum += left[i];
910
132k
                n += N;
911
132k
            }
912
155k
            if (mb_y > 0) {
913
1.07M
                for (int i = 0; i < N; ++i)
914
958k
                    sum += above[mb_x * N + i];
915
119k
                n += N;
916
119k
            }
917
155k
            u8 average = (sum + n / 2) / n;
918
10.0M
            for (size_t i = 0; i < N * N; ++i)
919
9.93M
                prediction[i] = average;
920
155k
        }
921
156k
    } else if (mode == H_PRED) {
922
248k
        for (int y = 0; y < N; ++y)
923
1.98M
            for (int x = 0; x < N; ++x)
924
1.76M
                prediction[y * N + x] = left[y];
925
94.0k
    } else if (mode == V_PRED) {
926
263k
        for (int y = 0; y < N; ++y)
927
2.10M
            for (int x = 0; x < N; ++x)
928
1.87M
                prediction[y * N + x] = above[mb_x * N + x];
929
64.7k
    } else {
930
64.7k
        VERIFY(mode == TM_PRED);
931
583k
        for (int y = 0; y < N; ++y)
932
4.66M
            for (int x = 0; x < N; ++x)
933
4.14M
                prediction[y * N + x] = clamp(left[y] + above[mb_x * N + x] - truemotion_corner, 0, 255);
934
64.7k
    }
935
278k
}
936
937
void predict_y_subblock(Bytes y_prediction, IntraBlockMode mode, int x, int y, ReadonlyBytes left, ReadonlyBytes above, u8 corner)
938
1.21M
{
939
    // https://datatracker.ietf.org/doc/html/rfc6386#section-12.3 "Luma Prediction"
940
    // Roughly corresponds to "subblock_intra_predict()" in the spec.
941
1.37M
    auto weighted_average = [](u8 x, u8 y, u8 z) { return (x + 2 * y + z + 2) / 4; };
942
1.21M
    auto average = [](u8 x, u8 y) { return (x + y + 1) / 2; };
943
944
1.21M
    auto at = [&y_prediction, y, x](int px, int py) -> u8& { return y_prediction[(4 * y + py) * 16 + 4 * x + px]; };
945
946
1.21M
    if (mode == B_DC_PRED) {
947
        // The spec text says this is like DC_PRED, but predict_dc_nxn() in the sample implementation doesn't do the "oob isn't read" part.
948
991k
        int sum = 0, n = 8;
949
4.95M
        for (int i = 0; i < 4; ++i)
950
3.96M
            sum += left[i] + above[i];
951
991k
        u8 average = (sum + n / 2) / n;
952
4.95M
        for (int py = 0; py < 4; ++py)
953
19.8M
            for (int px = 0; px < 4; ++px)
954
15.8M
                y_prediction[(4 * y + py) * 16 + 4 * x + px] = average;
955
991k
    } else if (mode == B_TM_PRED) {
956
437k
        for (int py = 0; py < 4; ++py)
957
1.75M
            for (int px = 0; px < 4; ++px)
958
1.40M
                y_prediction[(4 * y + py) * 16 + 4 * x + px] = clamp(left[py] + above[px] - corner, 0, 255);
959
135k
    } else if (mode == B_VE_PRED) {
960
        // The spec text says this is like V_PRED, but the sample implementation shows it does weighted averages (unlike V_PRED).
961
165k
        for (int py = 0; py < 4; ++py)
962
662k
            for (int px = 0; px < 4; ++px) {
963
530k
                auto top_left = (px > 0 ? above[px - 1] : corner);
964
530k
                y_prediction[(4 * y + py) * 16 + 4 * x + px] = weighted_average(top_left, above[px], above[px + 1]);
965
530k
            }
966
102k
    } else if (mode == B_HE_PRED) {
967
        // The spec text says this is like H_PRED, but the sample implementation shows it does weighted averages (unlike H_PRED).
968
129k
        for (int py = 0; py < 4; ++py)
969
519k
            for (int px = 0; px < 4; ++px) {
970
415k
                if (py == 0) {
971
103k
                    y_prediction[(4 * y + py) * 16 + 4 * x + px] = weighted_average(corner, left[py], left[py + 1]);
972
311k
                } else if (py == 3) {
973
                    /* Bottom row is exceptional because L[4] does not exist */
974
103k
                    y_prediction[(4 * y + py) * 16 + 4 * x + px] = weighted_average(left[2], left[3], left[3]);
975
207k
                } else {
976
207k
                    y_prediction[(4 * y + py) * 16 + 4 * x + px] = weighted_average(left[py - 1], left[py], left[py + 1]);
977
207k
                }
978
415k
            }
979
76.1k
    } else if (mode == B_LD_PRED) {
980
        // this is 45-deg prediction from above, going left-down (i.e. isochromes on -1/+1 diags)
981
11.9k
        at(0, 0) = weighted_average(above[0], above[1], above[2]);
982
11.9k
        at(0, 1) = at(1, 0) = weighted_average(above[1], above[2], above[3]);
983
11.9k
        at(0, 2) = at(1, 1) = at(2, 0) = weighted_average(above[2], above[3], above[4]);
984
11.9k
        at(0, 3) = at(1, 2) = at(2, 1) = at(3, 0) = weighted_average(above[3], above[4], above[5]);
985
11.9k
        at(1, 3) = at(2, 2) = at(3, 1) = weighted_average(above[4], above[5], above[6]);
986
11.9k
        at(2, 3) = at(3, 2) = weighted_average(above[5], above[6], above[7]);
987
11.9k
        at(3, 3) = weighted_average(above[6], above[7], above[7]); // intentionally 6, 7, 7
988
64.2k
    } else if (mode == B_RD_PRED) {
989
        // this is 45-deg prediction from above / left, going right-down (i.e. isochromes on +1/+1 diags)
990
9.17k
        at(0, 3) = weighted_average(left[3], left[2], left[1]);
991
9.17k
        at(0, 2) = at(1, 3) = weighted_average(left[2], left[1], left[0]);
992
9.17k
        at(0, 1) = at(1, 2) = at(2, 3) = weighted_average(left[1], left[0], corner);
993
9.17k
        at(0, 0) = at(1, 1) = at(2, 2) = at(3, 3) = weighted_average(left[0], corner, above[0]);
994
9.17k
        at(1, 0) = at(2, 1) = at(3, 2) = weighted_average(corner, above[0], above[1]);
995
9.17k
        at(2, 0) = at(3, 1) = weighted_average(above[0], above[1], above[2]);
996
9.17k
        at(3, 0) = weighted_average(above[1], above[2], above[3]);
997
55.0k
    } else if (mode == B_VR_PRED) {
998
        // this is 22.5-deg prediction
999
12.7k
        at(0, 3) = weighted_average(left[2], left[1], left[0]);
1000
12.7k
        at(0, 2) = weighted_average(left[1], left[0], corner);
1001
12.7k
        at(1, 3) = at(0, 1) = weighted_average(left[0], corner, above[0]);
1002
12.7k
        at(1, 2) = at(0, 0) = average(corner, above[0]);
1003
12.7k
        at(2, 3) = at(1, 1) = weighted_average(corner, above[0], above[1]);
1004
12.7k
        at(2, 2) = at(1, 0) = average(above[0], above[1]);
1005
12.7k
        at(3, 3) = at(2, 1) = weighted_average(above[0], above[1], above[2]);
1006
12.7k
        at(3, 2) = at(2, 0) = average(above[1], above[2]);
1007
12.7k
        at(3, 1) = weighted_average(above[1], above[2], above[3]);
1008
12.7k
        at(3, 0) = average(above[2], above[3]);
1009
42.2k
    } else if (mode == B_VL_PRED) {
1010
        // this is 22.5-deg prediction
1011
13.8k
        at(0, 0) = average(above[0], above[1]);
1012
13.8k
        at(0, 1) = weighted_average(above[0], above[1], above[2]);
1013
13.8k
        at(0, 2) = at(1, 0) = average(above[1], above[2]);
1014
13.8k
        at(1, 1) = at(0, 3) = weighted_average(above[1], above[2], above[3]);
1015
13.8k
        at(1, 2) = at(2, 0) = average(above[2], above[3]);
1016
13.8k
        at(1, 3) = at(2, 1) = weighted_average(above[2], above[3], above[4]);
1017
13.8k
        at(2, 2) = at(3, 0) = average(above[3], above[4]);
1018
13.8k
        at(2, 3) = at(3, 1) = weighted_average(above[3], above[4], above[5]);
1019
        /* Last two values do not strictly follow the pattern. */
1020
13.8k
        at(3, 2) = weighted_average(above[4], above[5], above[6]);
1021
13.8k
        at(3, 3) = weighted_average(above[5], above[6], above[7]);
1022
28.3k
    } else if (mode == B_HD_PRED) {
1023
        // this is 22.5-deg prediction
1024
10.8k
        at(0, 3) = average(left[3], left[2]);
1025
10.8k
        at(1, 3) = weighted_average(left[3], left[2], left[1]);
1026
10.8k
        at(0, 2) = at(2, 3) = average(left[2], left[1]);
1027
10.8k
        at(1, 2) = at(3, 3) = weighted_average(left[2], left[1], left[0]);
1028
10.8k
        at(2, 2) = at(0, 1) = average(left[1], left[0]);
1029
10.8k
        at(3, 2) = at(1, 1) = weighted_average(left[1], left[0], corner);
1030
10.8k
        at(2, 1) = at(0, 0) = average(left[0], corner);
1031
10.8k
        at(3, 1) = at(1, 0) = weighted_average(left[0], corner, above[0]);
1032
10.8k
        at(2, 0) = weighted_average(corner, above[0], above[1]);
1033
10.8k
        at(3, 0) = weighted_average(above[0], above[1], above[2]);
1034
17.5k
    } else {
1035
17.5k
        VERIFY(mode == B_HU_PRED);
1036
        // this is 22.5-deg prediction
1037
17.5k
        at(0, 0) = average(left[0], left[1]);
1038
17.5k
        at(1, 0) = weighted_average(left[0], left[1], left[2]);
1039
17.5k
        at(2, 0) = at(0, 1) = average(left[1], left[2]);
1040
17.5k
        at(3, 0) = at(1, 1) = weighted_average(left[1], left[2], left[3]);
1041
17.5k
        at(2, 1) = at(0, 2) = average(left[2], left[3]);
1042
17.5k
        at(3, 1) = at(1, 2) = weighted_average(left[2], left[3], left[3]); // Intentionally 2, 3, 3
1043
        /* Not possible to follow pattern for much of the bottom
1044
           row because no (nearby) already-constructed pixels lie
1045
           on the diagonals in question. */
1046
17.5k
        at(2, 2) = at(3, 2) = at(0, 3) = at(1, 3) = at(2, 3) = at(3, 3) = left[3];
1047
17.5k
    }
1048
1.21M
}
1049
1050
template<int N>
1051
void add_idct_to_prediction(Bytes prediction, Coefficients coefficients, int x, int y)
1052
3.33M
{
1053
3.33M
    Coefficients idct_output;
1054
3.33M
    short_idct4x4llm_c(coefficients, idct_output, 4 * sizeof(i16));
1055
1056
    // https://datatracker.ietf.org/doc/html/rfc6386#section-14.5 "Summation of Predictor and Residue"
1057
    // FIXME: Could omit the clamp() call if FrameHeader.clamping_type == ClampingSpecification::NoClampingNecessary.
1058
16.6M
    for (int py = 0; py < 4; ++py) {
1059
66.7M
        for (int px = 0; px < 4; ++px) {
1060
53.4M
            u8& p = prediction[(4 * y + py) * N + (4 * x + px)];
1061
53.4M
            p = clamp(p + idct_output[py * 4 + px], 0, 255);
1062
53.4M
        }
1063
13.3M
    }
1064
3.33M
}
WebPLoaderLossy.cpp:void Gfx::(anonymous namespace)::add_idct_to_prediction<16>(AK::Span<unsigned char>, short*, int, int)
Line
Count
Source
1052
2.22M
{
1053
2.22M
    Coefficients idct_output;
1054
2.22M
    short_idct4x4llm_c(coefficients, idct_output, 4 * sizeof(i16));
1055
1056
    // https://datatracker.ietf.org/doc/html/rfc6386#section-14.5 "Summation of Predictor and Residue"
1057
    // FIXME: Could omit the clamp() call if FrameHeader.clamping_type == ClampingSpecification::NoClampingNecessary.
1058
11.1M
    for (int py = 0; py < 4; ++py) {
1059
44.5M
        for (int px = 0; px < 4; ++px) {
1060
35.6M
            u8& p = prediction[(4 * y + py) * N + (4 * x + px)];
1061
35.6M
            p = clamp(p + idct_output[py * 4 + px], 0, 255);
1062
35.6M
        }
1063
8.90M
    }
1064
2.22M
}
WebPLoaderLossy.cpp:void Gfx::(anonymous namespace)::add_idct_to_prediction<8>(AK::Span<unsigned char>, short*, int, int)
Line
Count
Source
1052
1.11M
{
1053
1.11M
    Coefficients idct_output;
1054
1.11M
    short_idct4x4llm_c(coefficients, idct_output, 4 * sizeof(i16));
1055
1056
    // https://datatracker.ietf.org/doc/html/rfc6386#section-14.5 "Summation of Predictor and Residue"
1057
    // FIXME: Could omit the clamp() call if FrameHeader.clamping_type == ClampingSpecification::NoClampingNecessary.
1058
5.56M
    for (int py = 0; py < 4; ++py) {
1059
22.2M
        for (int px = 0; px < 4; ++px) {
1060
17.8M
            u8& p = prediction[(4 * y + py) * N + (4 * x + px)];
1061
17.8M
            p = clamp(p + idct_output[py * 4 + px], 0, 255);
1062
17.8M
        }
1063
4.45M
    }
1064
1.11M
}
1065
1066
template<int N>
1067
void process_macroblock(Bytes output, IntraMacroblockMode mode, int mb_x, int mb_y, ReadonlyBytes left, ReadonlyBytes above, u8 truemotion_corner, Coefficients coefficients_array[])
1068
341k
{
1069
341k
    predict_macroblock<4 * N>(output, mode, mb_x, mb_y, left, above, truemotion_corner);
1070
1071
    // https://datatracker.ietf.org/doc/html/rfc6386#section-14.4 "Implementation of the DCT Inversion"
1072
    // Loop over the 4x4 subblocks
1073
1.15M
    for (int y = 0, i = 0; y < N; ++y)
1074
2.93M
        for (int x = 0; x < N; ++x, ++i)
1075
2.12M
            add_idct_to_prediction<4 * N>(output, coefficients_array[i], x, y);
1076
341k
}
WebPLoaderLossy.cpp:void Gfx::(anonymous namespace)::process_macroblock<4>(AK::Span<unsigned char>, Gfx::IntraMacroblockMode, int, int, AK::Span<unsigned char const>, AK::Span<unsigned char const>, unsigned char, short (*) [16])
Line
Count
Source
1068
63.2k
{
1069
63.2k
    predict_macroblock<4 * N>(output, mode, mb_x, mb_y, left, above, truemotion_corner);
1070
1071
    // https://datatracker.ietf.org/doc/html/rfc6386#section-14.4 "Implementation of the DCT Inversion"
1072
    // Loop over the 4x4 subblocks
1073
316k
    for (int y = 0, i = 0; y < N; ++y)
1074
1.26M
        for (int x = 0; x < N; ++x, ++i)
1075
1.01M
            add_idct_to_prediction<4 * N>(output, coefficients_array[i], x, y);
1076
63.2k
}
WebPLoaderLossy.cpp:void Gfx::(anonymous namespace)::process_macroblock<2>(AK::Span<unsigned char>, Gfx::IntraMacroblockMode, int, int, AK::Span<unsigned char const>, AK::Span<unsigned char const>, unsigned char, short (*) [16])
Line
Count
Source
1068
278k
{
1069
278k
    predict_macroblock<4 * N>(output, mode, mb_x, mb_y, left, above, truemotion_corner);
1070
1071
    // https://datatracker.ietf.org/doc/html/rfc6386#section-14.4 "Implementation of the DCT Inversion"
1072
    // Loop over the 4x4 subblocks
1073
834k
    for (int y = 0, i = 0; y < N; ++y)
1074
1.66M
        for (int x = 0; x < N; ++x, ++i)
1075
1.11M
            add_idct_to_prediction<4 * N>(output, coefficients_array[i], x, y);
1076
278k
}
1077
1078
void process_subblocks(Bytes y_output, MacroblockMetadata const& metadata, int mb_x, ReadonlyBytes predicted_y_left, ReadonlyBytes predicted_y_above, u8 y_truemotion_corner, Coefficients coefficients_array[], int macroblock_width)
1079
75.9k
{
1080
    // Loop over the 4x4 subblocks
1081
379k
    for (int y = 0; y < 4; ++y) {
1082
1.51M
        for (int x = 0; x < 4; ++x) {
1083
1.21M
            u8 corner = y_truemotion_corner;
1084
1.21M
            if (x > 0 && y == 0)
1085
227k
                corner = predicted_y_above[mb_x * 16 + 4 * x - 1];
1086
986k
            else if (x > 0 && y > 0)
1087
683k
                corner = y_output[(4 * y - 1) * 16 + 4 * x - 1];
1088
303k
            else if (x == 0 && y > 0)
1089
227k
                corner = predicted_y_left[4 * y - 1];
1090
1091
1.21M
            u8 left[4], above[8];
1092
6.07M
            for (int i = 0; i < 4; ++i) {
1093
4.85M
                if (x == 0)
1094
1.21M
                    left[i] = predicted_y_left[4 * y + i];
1095
3.64M
                else
1096
3.64M
                    left[i] = y_output[(4 * y + i) * 16 + 4 * x - 1];
1097
4.85M
            }
1098
            // Subblock prediction can read 8 pixels above the block.
1099
            // For rightmost subblocks, the right 4 pixels there aren't initialized yet, so those get the 4 pixels to the right above the macroblock.
1100
            // For the rightmost macroblock, there's no macroblock to its right, so there they get the rightmost pixel above.
1101
            // But in the 0th row, there's no pixel above, so there they become 127.
1102
10.9M
            for (int i = 0; i < 8; ++i) {
1103
9.71M
                if (x == 3 && i >= 4) {                 // rightmost subblock, 4 right pixels?
1104
1.21M
                    if (mb_x == macroblock_width - 1) { // rightmost macroblock
1105
                        // predicted_y_above is initialized to 127 above the first row, so no need for an explicit branch for mb_y == 0.
1106
183k
                        above[i] = predicted_y_above[mb_x * 16 + 4 * x + 3];
1107
1.03M
                    } else {
1108
1.03M
                        above[i] = predicted_y_above[mb_x * 16 + 4 * x + i];
1109
1.03M
                    }
1110
8.50M
                } else if (y == 0) {
1111
2.12M
                    above[i] = predicted_y_above[mb_x * 16 + 4 * x + i];
1112
6.37M
                } else {
1113
6.37M
                    above[i] = y_output[(4 * y - 1) * 16 + 4 * x + i];
1114
6.37M
                }
1115
9.71M
            }
1116
1117
1.21M
            predict_y_subblock(y_output, metadata.intra_b_modes[y * 4 + x], x, y, left, above, corner);
1118
1119
            // Have to do IDCT summation here, since its results affect prediction of next subblock already.
1120
1.21M
            add_idct_to_prediction<16>(y_output, coefficients_array[4 * y + x], x, y);
1121
1.21M
        }
1122
303k
    }
1123
75.9k
}
1124
1125
void convert_yuv_to_rgb(Bitmap& bitmap, int mb_x, int mb_y, ReadonlyBytes y_data, ReadonlyBytes u_data, ReadonlyBytes v_data)
1126
139k
{
1127
2.36M
    for (int y = 0; y < 16; ++y) {
1128
37.8M
        for (int x = 0; x < 16; ++x) {
1129
35.6M
            u8 Y = y_data[y * 16 + x];
1130
1131
            // FIXME: Could do nicer upsampling than just nearest neighbor
1132
35.6M
            u8 U = u_data[(y / 2) * 8 + x / 2];
1133
35.6M
            u8 V = v_data[(y / 2) * 8 + x / 2];
1134
1135
            // XXX: These numbers are from the fixed-point values in libwebp's yuv.h. There's probably a better reference somewhere.
1136
35.6M
            int r = 1.1655 * Y + 1.596 * V - 222.4;
1137
35.6M
            int g = 1.1655 * Y - 0.3917 * U - 0.8129 * V + 136.0625;
1138
35.6M
            int b = 1.1655 * Y + 2.0172 * U - 276.33;
1139
1140
35.6M
            bitmap.scanline(mb_y * 16 + y)[mb_x * 16 + x] = Color(clamp(r, 0, 255), clamp(g, 0, 255), clamp(b, 0, 255)).value();
1141
35.6M
        }
1142
2.22M
    }
1143
139k
}
1144
1145
ErrorOr<void> decode_VP8_image_data(Gfx::Bitmap& bitmap, FrameHeader const& header, Vector<ReadonlyBytes> data_partitions, int macroblock_width, int macroblock_height, Vector<MacroblockMetadata> const& macroblock_metadata)
1146
852
{
1147
1148
852
    Vector<BooleanDecoder> streams;
1149
944
    for (auto data : data_partitions) {
1150
944
        auto decoder = TRY(BooleanDecoder::initialize(data));
1151
936
        TRY(streams.try_append(move(decoder)));
1152
936
    }
1153
1154
852
    CoefficientReadingContext coefficient_reading_context;
1155
844
    TRY(coefficient_reading_context.initialize(macroblock_width));
1156
1157
844
    Vector<u8> predicted_y_above;
1158
844
    TRY(predicted_y_above.try_resize(macroblock_width * 16));
1159
573k
    for (size_t i = 0; i < predicted_y_above.size(); ++i)
1160
572k
        predicted_y_above[i] = 127;
1161
1162
844
    Vector<u8> predicted_u_above;
1163
844
    TRY(predicted_u_above.try_resize(macroblock_width * 8));
1164
287k
    for (size_t i = 0; i < predicted_u_above.size(); ++i)
1165
286k
        predicted_u_above[i] = 127;
1166
1167
844
    Vector<u8> predicted_v_above;
1168
844
    TRY(predicted_v_above.try_resize(macroblock_width * 8));
1169
287k
    for (size_t i = 0; i < predicted_v_above.size(); ++i)
1170
286k
        predicted_v_above[i] = 127;
1171
1172
26.3k
    for (int mb_y = 0, macroblock_index = 0; mb_y < macroblock_height; ++mb_y) {
1173
25.4k
        BooleanDecoder& decoder = streams[mb_y % streams.size()];
1174
1175
25.4k
        coefficient_reading_context.start_new_row();
1176
1177
25.4k
        u8 predicted_y_left[16] { 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129 };
1178
25.4k
        u8 predicted_u_left[8] { 129, 129, 129, 129, 129, 129, 129, 129 };
1179
25.4k
        u8 predicted_v_left[8] { 129, 129, 129, 129, 129, 129, 129, 129 };
1180
1181
        // The spec doesn't say if this should be 127, 129, or something else.
1182
        // But ReconstructRow in frame_dec.c in libwebp suggests 129.
1183
25.4k
        u8 y_truemotion_corner = 129;
1184
25.4k
        u8 u_truemotion_corner = 129;
1185
25.4k
        u8 v_truemotion_corner = 129;
1186
1187
164k
        for (int mb_x = 0; mb_x < macroblock_width; ++mb_x, ++macroblock_index) {
1188
139k
            auto const& metadata = macroblock_metadata[macroblock_index];
1189
1190
139k
            auto coefficients = read_macroblock_coefficients(decoder, header, coefficient_reading_context, metadata, mb_x);
1191
1192
139k
            u8 y_data[16 * 16] {};
1193
139k
            if (metadata.intra_y_mode == B_PRED)
1194
75.9k
                process_subblocks(y_data, metadata, mb_x, predicted_y_left, predicted_y_above, y_truemotion_corner, coefficients.y_coeffs, macroblock_width);
1195
63.2k
            else
1196
63.2k
                process_macroblock<4>(y_data, metadata.intra_y_mode, mb_x, mb_y, predicted_y_left, predicted_y_above, y_truemotion_corner, coefficients.y_coeffs);
1197
1198
139k
            u8 u_data[8 * 8] {};
1199
139k
            process_macroblock<2>(u_data, metadata.uv_mode, mb_x, mb_y, predicted_u_left, predicted_u_above, u_truemotion_corner, coefficients.u_coeffs);
1200
1201
139k
            u8 v_data[8 * 8] {};
1202
139k
            process_macroblock<2>(v_data, metadata.uv_mode, mb_x, mb_y, predicted_v_left, predicted_v_above, v_truemotion_corner, coefficients.v_coeffs);
1203
1204
            // FIXME: insert loop filtering here
1205
1206
139k
            convert_yuv_to_rgb(bitmap, mb_x, mb_y, y_data, u_data, v_data);
1207
1208
139k
            y_truemotion_corner = predicted_y_above[mb_x * 16 + 15];
1209
2.36M
            for (int i = 0; i < 16; ++i)
1210
2.22M
                predicted_y_left[i] = y_data[15 + i * 16];
1211
2.36M
            for (int i = 0; i < 16; ++i)
1212
2.22M
                predicted_y_above[mb_x * 16 + i] = y_data[15 * 16 + i];
1213
1214
139k
            u_truemotion_corner = predicted_u_above[mb_x * 8 + 7];
1215
1.25M
            for (int i = 0; i < 8; ++i)
1216
1.11M
                predicted_u_left[i] = u_data[7 + i * 8];
1217
1.25M
            for (int i = 0; i < 8; ++i)
1218
1.11M
                predicted_u_above[mb_x * 8 + i] = u_data[7 * 8 + i];
1219
1220
139k
            v_truemotion_corner = predicted_v_above[mb_x * 8 + 7];
1221
1.25M
            for (int i = 0; i < 8; ++i)
1222
1.11M
                predicted_v_left[i] = v_data[7 + i * 8];
1223
1.25M
            for (int i = 0; i < 8; ++i)
1224
1.11M
                predicted_v_above[mb_x * 8 + i] = v_data[7 * 8 + i];
1225
139k
        }
1226
25.4k
    }
1227
1228
844
    for (auto& decoder : streams)
1229
861
        TRY(decoder.finish_decode());
1230
1231
844
    return {};
1232
844
}
1233
1234
static ErrorOr<Vector<ReadonlyBytes>> split_data_partitions(ReadonlyBytes second_partition, u8 number_of_dct_partitions)
1235
918
{
1236
918
    Vector<ReadonlyBytes> data_partitions;
1237
    // https://datatracker.ietf.org/doc/html/rfc6386#section-9.5 "Token Partition and Partition Data Offsets"
1238
    // "If the number of data partitions is
1239
    //  greater than 1, the size of each partition (except the last) is
1240
    //  written in 3 bytes (24 bits).  The size of the last partition is the
1241
    //  remainder of the data not used by any of the previous partitions.
1242
    //  The partitioned data are consecutive in the bitstream, so the size
1243
    //  can also be used to calculate the offset of each partition."
1244
    // In practice, virtually all lossy webp files have a single data partition.
1245
918
    VERIFY(number_of_dct_partitions >= 1);
1246
918
    VERIFY(number_of_dct_partitions <= 8);
1247
1248
918
    size_t sizes_size = (number_of_dct_partitions - 1) * 3;
1249
918
    if (second_partition.size() < sizes_size)
1250
5
        return Error::from_string_literal("WebPImageDecoderPlugin: not enough data for partition sizes");
1251
1252
913
    ReadonlyBytes sizes = second_partition.slice(0, sizes_size);
1253
913
    ReadonlyBytes data = second_partition.slice(sizes_size);
1254
1255
1.10k
    for (int i = 0; i < number_of_dct_partitions - 1; ++i) {
1256
253
        u32 partition_size = sizes[0] | (sizes[1] << 8) | (sizes[2] << 16);
1257
253
        dbgln_if(WEBP_DEBUG, "partition_size {}", partition_size);
1258
253
        sizes = sizes.slice(3);
1259
253
        if (partition_size > data.size())
1260
61
            return Error::from_string_literal("WebPImageDecoderPlugin: not enough data for partition data");
1261
384
        TRY(data_partitions.try_append(data.slice(0, partition_size)));
1262
384
        data = data.slice(partition_size);
1263
384
    }
1264
913
    TRY(data_partitions.try_append(data));
1265
852
    return data_partitions;
1266
852
}
1267
1268
}
1269
1270
ErrorOr<NonnullRefPtr<Bitmap>> decode_webp_chunk_VP8_contents(VP8Header const& vp8_header, bool include_alpha_channel)
1271
1.03k
{
1272
1.03k
    VERIFY(vp8_header.keyframe_data.has_value());
1273
1274
    // The first partition stores header, per-segment state, and macroblock metadata.
1275
1.03k
    auto decoder = TRY(BooleanDecoder::initialize(vp8_header.first_partition));
1276
1277
1.03k
    auto header = TRY(decode_VP8_frame_header(decoder));
1278
1279
    // https://datatracker.ietf.org/doc/html/rfc6386#section-2 "Format Overview"
1280
    // "Internally, VP8 decomposes each output frame into an array of
1281
    //  macroblocks.  A macroblock is a square array of pixels whose Y
1282
    //  dimensions are 16x16 and whose U and V dimensions are 8x8."
1283
1.03k
    int macroblock_width = ceil_div(vp8_header.keyframe_data->width, 16);
1284
1.03k
    int macroblock_height = ceil_div(vp8_header.keyframe_data->height, 16);
1285
1286
1.03k
    auto macroblock_metadata = TRY(decode_VP8_macroblock_metadata(decoder, header, macroblock_width, macroblock_height));
1287
1288
1.03k
    TRY(decoder.finish_decode());
1289
    // Done with the first partition!
1290
1291
937
    auto bitmap_format = include_alpha_channel ? BitmapFormat::BGRA8888 : BitmapFormat::BGRx8888;
1292
937
    auto bitmap = TRY(Bitmap::create(bitmap_format, { macroblock_width * 16, macroblock_height * 16 }));
1293
1294
918
    auto data_partitions = TRY(split_data_partitions(vp8_header.second_partition, header.number_of_dct_partitions));
1295
852
    TRY(decode_VP8_image_data(*bitmap, header, move(data_partitions), macroblock_width, macroblock_height, macroblock_metadata));
1296
1297
291
    auto width = static_cast<int>(vp8_header.keyframe_data->width);
1298
291
    auto height = static_cast<int>(vp8_header.keyframe_data->height);
1299
291
    if (bitmap->physical_size() == IntSize { width, height })
1300
10
        return bitmap;
1301
281
    return bitmap->cropped({ 0, 0, width, height });
1302
291
}
1303
1304
}