Coverage Report

Created: 2026-09-14 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibMedia/Video/VP9/Decoder.cpp
Line
Count
Source
1
/*
2
 * Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
3
 * Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
4
 *
5
 * SPDX-License-Identifier: BSD-2-Clause
6
 */
7
8
#include <AK/IntegralMath.h>
9
#include <AK/TypedTransfer.h>
10
#include <LibGfx/Size.h>
11
#include <LibMedia/Color/CodingIndependentCodePoints.h>
12
13
#include "Context.h"
14
#include "Decoder.h"
15
#include "Utilities.h"
16
17
#if defined(AK_COMPILER_GCC)
18
#    pragma GCC optimize("O3")
19
#endif
20
21
namespace Media::Video::VP9 {
22
23
Decoder::Decoder()
24
757
    : m_parser(make<Parser>(*this))
25
757
{
26
757
}
27
28
DecoderErrorOr<void> Decoder::receive_sample(Duration timestamp, ReadonlyBytes chunk_data)
29
757
{
30
757
    auto superframe_sizes = m_parser->parse_superframe_sizes(chunk_data);
31
32
757
    if (superframe_sizes.is_empty()) {
33
235
        return decode_frame(timestamp, chunk_data);
34
235
    }
35
36
522
    size_t offset = 0;
37
38
2.24k
    for (auto superframe_size : superframe_sizes) {
39
2.24k
        auto checked_size = Checked<size_t>(superframe_size);
40
2.24k
        checked_size += offset;
41
2.24k
        if (checked_size.has_overflow() || checked_size.value() > chunk_data.size())
42
312
            return DecoderError::with_description(DecoderErrorCategory::Corrupted, "Superframe size invalid"sv);
43
1.92k
        auto frame_data = chunk_data.slice(offset, superframe_size);
44
1.92k
        TRY(decode_frame(timestamp, frame_data));
45
1.72k
        offset = checked_size.value();
46
1.72k
    }
47
48
3
    return {};
49
522
}
50
51
DecoderErrorOr<void> Decoder::decode_frame(Duration timestamp, ReadonlyBytes frame_data)
52
2.16k
{
53
    // 1. The syntax elements for the coded frame are extracted as specified in sections 6 and 7. The syntax
54
    // tables include function calls indicating when the block decode processes should be triggered.
55
2.16k
    auto frame_context = TRY(m_parser->parse_frame(frame_data));
56
57
    // 2. If loop_filter_level is not equal to 0, the loop filter process as specified in section 8.8 is invoked once the
58
    // coded frame has been decoded.
59
    // FIXME: Implement loop filtering.
60
61
    // 3. If all of the following conditions are true, PrevSegmentIds[ row ][ col ] is set equal to
62
    // SegmentIds[ row ][ col ] for row = 0..MiRows-1, for col = 0..MiCols-1:
63
    // − show_existing_frame is equal to 0,
64
    // − segmentation_enabled is equal to 1,
65
    // − segmentation_update_map is equal to 1.
66
    // This is handled by update_reference_frames.
67
68
    // 4. The output process as specified in section 8.9 is invoked.
69
1.80k
    if (frame_context.shows_a_frame()) {
70
1.04k
        switch (frame_context.color_config.bit_depth) {
71
1.01k
        case 8:
72
1.01k
            TRY(create_video_frame<u8>(timestamp, frame_context));
73
1.01k
            break;
74
5
        case 10:
75
23
        case 12:
76
23
            TRY(create_video_frame<u16>(timestamp, frame_context));
77
23
            break;
78
1.04k
        }
79
1.04k
    }
80
81
    // 5. The reference frame update process as specified in section 8.10 is invoked.
82
1.80k
    TRY(update_reference_frames(frame_context));
83
1.80k
    return {};
84
1.80k
}
85
86
inline CodingIndependentCodePoints get_cicp_color_space(FrameContext const& frame_context)
87
1.04k
{
88
1.04k
    ColorPrimaries color_primaries;
89
1.04k
    TransferCharacteristics transfer_characteristics;
90
1.04k
    MatrixCoefficients matrix_coefficients;
91
92
1.04k
    switch (frame_context.color_config.color_space) {
93
938
    case ColorSpace::Unknown:
94
938
        color_primaries = ColorPrimaries::Unspecified;
95
938
        transfer_characteristics = TransferCharacteristics::Unspecified;
96
938
        matrix_coefficients = MatrixCoefficients::Unspecified;
97
938
        break;
98
28
    case ColorSpace::Bt601:
99
28
        color_primaries = ColorPrimaries::BT601;
100
28
        transfer_characteristics = TransferCharacteristics::BT601;
101
28
        matrix_coefficients = MatrixCoefficients::BT601;
102
28
        break;
103
24
    case ColorSpace::Bt709:
104
24
        color_primaries = ColorPrimaries::BT709;
105
24
        transfer_characteristics = TransferCharacteristics::BT709;
106
24
        matrix_coefficients = MatrixCoefficients::BT709;
107
24
        break;
108
8
    case ColorSpace::Smpte170:
109
        // https://www.kernel.org/doc/html/v4.9/media/uapi/v4l/pixfmt-007.html#colorspace-smpte-170m-v4l2-colorspace-smpte170m
110
8
        color_primaries = ColorPrimaries::BT601;
111
8
        transfer_characteristics = TransferCharacteristics::BT709;
112
8
        matrix_coefficients = MatrixCoefficients::BT601;
113
8
        break;
114
36
    case ColorSpace::Smpte240:
115
36
        color_primaries = ColorPrimaries::SMPTE240;
116
36
        transfer_characteristics = TransferCharacteristics::SMPTE240;
117
36
        matrix_coefficients = MatrixCoefficients::SMPTE240;
118
36
        break;
119
7
    case ColorSpace::Bt2020:
120
7
        color_primaries = ColorPrimaries::BT2020;
121
        // Bit depth doesn't actually matter to our transfer functions since we
122
        // convert in floats of range 0-1 (for now?), but just for correctness set
123
        // the TC to match the bit depth here.
124
7
        if (frame_context.color_config.bit_depth == 12)
125
0
            transfer_characteristics = TransferCharacteristics::BT2020BitDepth12;
126
7
        else if (frame_context.color_config.bit_depth == 10)
127
0
            transfer_characteristics = TransferCharacteristics::BT2020BitDepth10;
128
7
        else
129
7
            transfer_characteristics = TransferCharacteristics::BT709;
130
7
        matrix_coefficients = MatrixCoefficients::BT2020NonConstantLuminance;
131
7
        break;
132
0
    case ColorSpace::RGB:
133
0
        color_primaries = ColorPrimaries::BT709;
134
0
        transfer_characteristics = TransferCharacteristics::Linear;
135
0
        matrix_coefficients = MatrixCoefficients::Identity;
136
0
        break;
137
0
    case ColorSpace::Reserved:
138
0
        VERIFY_NOT_REACHED();
139
0
        break;
140
1.04k
    }
141
142
1.04k
    return { color_primaries, transfer_characteristics, matrix_coefficients, frame_context.color_config.color_range };
143
1.04k
}
144
145
template<typename T>
146
DecoderErrorOr<void> Decoder::create_video_frame(Duration timestamp, FrameContext const& frame_context)
147
1.04k
{
148
    // (8.9) Output process
149
150
    // FIXME: If show_existing_frame is set, output from FrameStore[frame_to_show_map_index] here instead.
151
1.04k
    if (frame_context.shows_existing_frame()) {
152
0
        dbgln("FIXME: Show an existing reference frame.");
153
0
    }
154
155
    // FIXME: The math isn't entirely accurate to spec. output_uv_size is probably incorrect for certain
156
    //        sizes, as the spec seems to prefer that the halved sizes be ceiled.
157
1.04k
    u32 decoded_y_width = frame_context.decoded_size(false).width();
158
1.04k
    auto decoded_uv_width = frame_context.decoded_size(true).width();
159
160
1.04k
    Subsampling subsampling { frame_context.color_config.subsampling_x, frame_context.color_config.subsampling_y };
161
1.04k
    auto output_y_size = frame_context.size().to_type<size_t>();
162
1.04k
    auto output_uv_size = subsampling.subsampled_size(output_y_size);
163
164
1.04k
    auto frame = DECODER_TRY_ALLOC(SubsampledYUVFrame::try_create(
165
1.04k
        timestamp,
166
1.04k
        { output_y_size.width(), output_y_size.height() },
167
1.04k
        frame_context.color_config.bit_depth, get_cicp_color_space(frame_context),
168
1.04k
        subsampling));
169
4.16k
    for (u32 plane = 0; plane < 3; plane++) {
170
3.12k
        auto* buffer = frame->get_plane_data<T>(plane);
171
3.12k
        auto decoded_width = plane == 0 ? decoded_y_width : decoded_uv_width;
172
3.12k
        auto output_size = plane == 0 ? output_y_size : output_uv_size;
173
3.12k
        auto const* decoded_buffer = get_output_buffer(plane).data();
174
175
2.92M
        for (u32 row = 0; row < output_size.height(); row++) {
176
246M
            for (u32 column = 0; column < output_size.width(); column++)
177
243M
                buffer[row * output_size.width() + column] = static_cast<T>(decoded_buffer[row * decoded_width + column]);
178
2.92M
        }
179
3.12k
    }
180
181
1.04k
    m_video_frame_queue.enqueue(move(frame));
182
183
1.04k
    return {};
184
1.04k
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::create_video_frame<unsigned char>(AK::Duration, Media::Video::VP9::FrameContext const&)
Line
Count
Source
147
1.01k
{
148
    // (8.9) Output process
149
150
    // FIXME: If show_existing_frame is set, output from FrameStore[frame_to_show_map_index] here instead.
151
1.01k
    if (frame_context.shows_existing_frame()) {
152
0
        dbgln("FIXME: Show an existing reference frame.");
153
0
    }
154
155
    // FIXME: The math isn't entirely accurate to spec. output_uv_size is probably incorrect for certain
156
    //        sizes, as the spec seems to prefer that the halved sizes be ceiled.
157
1.01k
    u32 decoded_y_width = frame_context.decoded_size(false).width();
158
1.01k
    auto decoded_uv_width = frame_context.decoded_size(true).width();
159
160
1.01k
    Subsampling subsampling { frame_context.color_config.subsampling_x, frame_context.color_config.subsampling_y };
161
1.01k
    auto output_y_size = frame_context.size().to_type<size_t>();
162
1.01k
    auto output_uv_size = subsampling.subsampled_size(output_y_size);
163
164
1.01k
    auto frame = DECODER_TRY_ALLOC(SubsampledYUVFrame::try_create(
165
1.01k
        timestamp,
166
1.01k
        { output_y_size.width(), output_y_size.height() },
167
1.01k
        frame_context.color_config.bit_depth, get_cicp_color_space(frame_context),
168
1.01k
        subsampling));
169
4.07k
    for (u32 plane = 0; plane < 3; plane++) {
170
3.05k
        auto* buffer = frame->get_plane_data<T>(plane);
171
3.05k
        auto decoded_width = plane == 0 ? decoded_y_width : decoded_uv_width;
172
3.05k
        auto output_size = plane == 0 ? output_y_size : output_uv_size;
173
3.05k
        auto const* decoded_buffer = get_output_buffer(plane).data();
174
175
2.06M
        for (u32 row = 0; row < output_size.height(); row++) {
176
212M
            for (u32 column = 0; column < output_size.width(); column++)
177
210M
                buffer[row * output_size.width() + column] = static_cast<T>(decoded_buffer[row * decoded_width + column]);
178
2.06M
        }
179
3.05k
    }
180
181
1.01k
    m_video_frame_queue.enqueue(move(frame));
182
183
1.01k
    return {};
184
1.01k
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::create_video_frame<unsigned short>(AK::Duration, Media::Video::VP9::FrameContext const&)
Line
Count
Source
147
23
{
148
    // (8.9) Output process
149
150
    // FIXME: If show_existing_frame is set, output from FrameStore[frame_to_show_map_index] here instead.
151
23
    if (frame_context.shows_existing_frame()) {
152
0
        dbgln("FIXME: Show an existing reference frame.");
153
0
    }
154
155
    // FIXME: The math isn't entirely accurate to spec. output_uv_size is probably incorrect for certain
156
    //        sizes, as the spec seems to prefer that the halved sizes be ceiled.
157
23
    u32 decoded_y_width = frame_context.decoded_size(false).width();
158
23
    auto decoded_uv_width = frame_context.decoded_size(true).width();
159
160
23
    Subsampling subsampling { frame_context.color_config.subsampling_x, frame_context.color_config.subsampling_y };
161
23
    auto output_y_size = frame_context.size().to_type<size_t>();
162
23
    auto output_uv_size = subsampling.subsampled_size(output_y_size);
163
164
23
    auto frame = DECODER_TRY_ALLOC(SubsampledYUVFrame::try_create(
165
23
        timestamp,
166
23
        { output_y_size.width(), output_y_size.height() },
167
23
        frame_context.color_config.bit_depth, get_cicp_color_space(frame_context),
168
23
        subsampling));
169
92
    for (u32 plane = 0; plane < 3; plane++) {
170
69
        auto* buffer = frame->get_plane_data<T>(plane);
171
69
        auto decoded_width = plane == 0 ? decoded_y_width : decoded_uv_width;
172
69
        auto output_size = plane == 0 ? output_y_size : output_uv_size;
173
69
        auto const* decoded_buffer = get_output_buffer(plane).data();
174
175
856k
        for (u32 row = 0; row < output_size.height(); row++) {
176
33.6M
            for (u32 column = 0; column < output_size.width(); column++)
177
32.7M
                buffer[row * output_size.width() + column] = static_cast<T>(decoded_buffer[row * decoded_width + column]);
178
856k
        }
179
69
    }
180
181
23
    m_video_frame_queue.enqueue(move(frame));
182
183
23
    return {};
184
23
}
185
186
DecoderErrorOr<void> Decoder::allocate_buffers(FrameContext const& frame_context)
187
2.05k
{
188
8.22k
    for (size_t plane = 0; plane < 3; plane++) {
189
6.17k
        auto size = frame_context.decoded_size(plane > 0);
190
191
6.17k
        auto& output_buffer = get_output_buffer(plane);
192
6.17k
        output_buffer.clear_with_capacity();
193
6.17k
        DECODER_TRY_ALLOC(output_buffer.try_resize_and_keep_capacity(size.width() * size.height()));
194
6.17k
    }
195
2.05k
    return {};
196
2.05k
}
197
198
Vector<u16>& Decoder::get_output_buffer(u8 plane)
199
24.9M
{
200
24.9M
    return m_output_buffers[plane];
201
24.9M
}
202
203
DecoderErrorOr<NonnullOwnPtr<VideoFrame>> Decoder::get_decoded_frame()
204
0
{
205
0
    if (m_video_frame_queue.is_empty())
206
0
        return DecoderError::format(DecoderErrorCategory::NeedsMoreInput, "No video frame in queue.");
207
208
0
    return m_video_frame_queue.dequeue();
209
0
}
210
211
void Decoder::flush()
212
0
{
213
0
    m_video_frame_queue.clear();
214
0
}
215
216
template<typename T>
217
static inline i32 rounded_right_shift(T value, u8 bits)
218
2.66G
{
219
2.66G
    value = (value + static_cast<T>(1u << (bits - 1u))) >> bits;
220
2.66G
    return static_cast<i32>(value);
221
2.66G
}
Decoder.cpp:int Media::Video::VP9::rounded_right_shift<unsigned int>(unsigned int, unsigned char)
Line
Count
Source
218
1.86M
{
219
1.86M
    value = (value + static_cast<T>(1u << (bits - 1u))) >> bits;
220
1.86M
    return static_cast<i32>(value);
221
1.86M
}
Decoder.cpp:int Media::Video::VP9::rounded_right_shift<int>(int, unsigned char)
Line
Count
Source
218
641M
{
219
641M
    value = (value + static_cast<T>(1u << (bits - 1u))) >> bits;
220
641M
    return static_cast<i32>(value);
221
641M
}
Decoder.cpp:int Media::Video::VP9::rounded_right_shift<long>(long, unsigned char)
Line
Count
Source
218
2.01G
{
219
2.01G
    value = (value + static_cast<T>(1u << (bits - 1u))) >> bits;
220
2.01G
    return static_cast<i32>(value);
221
2.01G
}
222
223
u8 Decoder::merge_prob(u8 pre_prob, u32 count_0, u32 count_1, u8 count_sat, u8 max_update_factor)
224
1.86M
{
225
1.86M
    auto total_decode_count = count_0 + count_1;
226
1.86M
    u8 prob = 128;
227
1.86M
    if (total_decode_count != 0) {
228
131k
        prob = static_cast<u8>(clip_3(1u, 255u, (count_0 * 256 + (total_decode_count >> 1)) / total_decode_count));
229
131k
    }
230
1.86M
    auto count = min(total_decode_count, count_sat);
231
1.86M
    auto factor = (max_update_factor * count) / count_sat;
232
1.86M
    return rounded_right_shift(pre_prob * (256 - factor) + (prob * factor), 8);
233
1.86M
}
234
235
u32 Decoder::merge_probs(int const* tree, int index, u8* probs, u32* counts, u8 count_sat, u8 max_update_factor)
236
1.83M
{
237
1.83M
    auto s = tree[index];
238
1.83M
    auto left_count = (s <= 0) ? counts[-s] : merge_probs(tree, s, probs, counts, count_sat, max_update_factor);
239
1.83M
    auto r = tree[index + 1];
240
1.83M
    auto right_count = (r <= 0) ? counts[-r] : merge_probs(tree, r, probs, counts, count_sat, max_update_factor);
241
1.83M
    probs[index >> 1] = merge_prob(probs[index >> 1], left_count, right_count, count_sat, max_update_factor);
242
1.83M
    return left_count + right_count;
243
1.83M
}
244
245
DecoderErrorOr<void> Decoder::adapt_coef_probs(FrameContext const& frame_context)
246
1.04k
{
247
1.04k
    u8 update_factor;
248
1.04k
    if (!frame_context.is_inter_predicted() || m_parser->m_previous_frame_type != FrameType::KeyFrame)
249
794
        update_factor = 112;
250
253
    else
251
253
        update_factor = 128;
252
253
5.23k
    for (size_t t = 0; t < 4; t++) {
254
12.5k
        for (size_t i = 0; i < 2; i++) {
255
25.1k
            for (size_t j = 0; j < 2; j++) {
256
117k
                for (size_t k = 0; k < 6; k++) {
257
100k
                    size_t max_l = (k == 0) ? 3 : 6;
258
653k
                    for (size_t l = 0; l < max_l; l++) {
259
552k
                        auto& coef_probs = m_parser->m_probability_tables->coef_probs()[t][i][j][k][l];
260
552k
                        merge_probs(small_token_tree, 2, coef_probs,
261
552k
                            frame_context.counter->m_counts_token[t][i][j][k][l],
262
552k
                            24, update_factor);
263
552k
                        merge_probs(binary_tree, 0, coef_probs,
264
552k
                            frame_context.counter->m_counts_more_coefs[t][i][j][k][l],
265
552k
                            24, update_factor);
266
552k
                    }
267
100k
                }
268
16.7k
            }
269
8.37k
        }
270
4.18k
    }
271
272
1.04k
    return {};
273
1.04k
}
274
275
#define ADAPT_PROB_TABLE(name, size)                                     \
276
2.87k
    do {                                                                 \
277
15.0k
        for (size_t i = 0; i < (size); i++) {                            \
278
12.2k
            auto table = probs.name##_prob();                            \
279
12.2k
            table[i] = adapt_prob(table[i], counter.m_counts_##name[i]); \
280
12.2k
        }                                                                \
281
2.87k
    } while (0)
282
283
#define ADAPT_TREE(tree_name, prob_name, count_name, size)                                                 \
284
3.21k
    do {                                                                                                   \
285
31.1k
        for (size_t i = 0; i < (size); i++) {                                                              \
286
27.9k
            adapt_probs(tree_name##_tree, probs.prob_name##_probs()[i], counter.m_counts_##count_name[i]); \
287
27.9k
        }                                                                                                  \
288
3.21k
    } while (0)
289
290
DecoderErrorOr<void> Decoder::adapt_non_coef_probs(FrameContext const& frame_context)
291
719
{
292
719
    auto& probs = *m_parser->m_probability_tables;
293
719
    auto& counter = *frame_context.counter;
294
719
    ADAPT_PROB_TABLE(is_inter, IS_INTER_CONTEXTS);
295
719
    ADAPT_PROB_TABLE(comp_mode, COMP_MODE_CONTEXTS);
296
719
    ADAPT_PROB_TABLE(comp_ref, REF_CONTEXTS);
297
4.31k
    for (size_t i = 0; i < REF_CONTEXTS; i++) {
298
10.7k
        for (size_t j = 0; j < 2; j++)
299
7.19k
            probs.single_ref_prob()[i][j] = adapt_prob(probs.single_ref_prob()[i][j], counter.m_counts_single_ref[i][j]);
300
3.59k
    }
301
719
    ADAPT_TREE(inter_mode, inter_mode, inter_mode, INTER_MODE_CONTEXTS);
302
719
    ADAPT_TREE(intra_mode, y_mode, intra_mode, BLOCK_SIZE_GROUPS);
303
719
    ADAPT_TREE(intra_mode, uv_mode, uv_mode, INTRA_MODES);
304
719
    ADAPT_TREE(partition, partition, partition, PARTITION_CONTEXTS);
305
719
    ADAPT_PROB_TABLE(skip, SKIP_CONTEXTS);
306
719
    if (frame_context.interpolation_filter == Switchable) {
307
340
        ADAPT_TREE(interp_filter, interp_filter, interp_filter, INTERP_FILTER_CONTEXTS);
308
340
    }
309
719
    if (frame_context.transform_mode == TransformMode::Select) {
310
87
        for (size_t i = 0; i < TX_SIZE_CONTEXTS; i++) {
311
58
            auto& tx_probs = probs.tx_probs();
312
58
            auto& tx_counts = counter.m_counts_tx_size;
313
58
            adapt_probs(tx_size_8_tree, tx_probs[Transform_8x8][i], tx_counts[Transform_8x8][i]);
314
58
            adapt_probs(tx_size_16_tree, tx_probs[Transform_16x16][i], tx_counts[Transform_16x16][i]);
315
58
            adapt_probs(tx_size_32_tree, tx_probs[Transform_32x32][i], tx_counts[Transform_32x32][i]);
316
58
        }
317
29
    }
318
719
    adapt_probs(mv_joint_tree, probs.mv_joint_probs(), counter.m_counts_mv_joint);
319
2.15k
    for (size_t i = 0; i < 2; i++) {
320
1.43k
        probs.mv_sign_prob()[i] = adapt_prob(probs.mv_sign_prob()[i], counter.m_counts_mv_sign[i]);
321
1.43k
        adapt_probs(mv_class_tree, probs.mv_class_probs()[i], counter.m_counts_mv_class[i]);
322
1.43k
        probs.mv_class0_bit_prob()[i] = adapt_prob(probs.mv_class0_bit_prob()[i], counter.m_counts_mv_class0_bit[i]);
323
15.8k
        for (size_t j = 0; j < MV_OFFSET_BITS; j++)
324
14.3k
            probs.mv_bits_prob()[i][j] = adapt_prob(probs.mv_bits_prob()[i][j], counter.m_counts_mv_bits[i][j]);
325
4.31k
        for (size_t j = 0; j < CLASS0_SIZE; j++)
326
2.87k
            adapt_probs(mv_fr_tree, probs.mv_class0_fr_probs()[i][j], counter.m_counts_mv_class0_fr[i][j]);
327
1.43k
        adapt_probs(mv_fr_tree, probs.mv_fr_probs()[i], counter.m_counts_mv_fr[i]);
328
1.43k
        if (frame_context.high_precision_motion_vectors_allowed) {
329
650
            probs.mv_class0_hp_prob()[i] = adapt_prob(probs.mv_class0_hp_prob()[i], counter.m_counts_mv_class0_hp[i]);
330
650
            probs.mv_hp_prob()[i] = adapt_prob(probs.mv_hp_prob()[i], counter.m_counts_mv_hp[i]);
331
650
        }
332
1.43k
    }
333
719
    return {};
334
719
}
335
336
void Decoder::adapt_probs(int const* tree, u8* probs, u32* counts)
337
34.6k
{
338
34.6k
    merge_probs(tree, 0, probs, counts, COUNT_SAT, MAX_UPDATE_FACTOR);
339
34.6k
}
340
341
u8 Decoder::adapt_prob(u8 prob, u32 counts[2])
342
37.9k
{
343
37.9k
    return merge_prob(prob, counts[0], counts[1], COUNT_SAT, MAX_UPDATE_FACTOR);
344
37.9k
}
345
346
DecoderErrorOr<void> Decoder::predict_intra(u8 plane, BlockContext const& block_context, u32 x, u32 y, bool have_left, bool have_above, bool not_on_right, TransformSize tx_size, u32 block_index)
347
16.2M
{
348
16.2M
    auto& frame_buffer = get_output_buffer(plane);
349
350
    // 8.5.1 Intra prediction process
351
352
    // The intra prediction process is invoked for intra coded blocks to predict a part of the block corresponding to a
353
    // transform block. When the transform size is smaller than the block size, this process can be invoked multiple
354
    // times within a single block for the same plane, and the invocations are in raster order within the block.
355
356
    // The variable mode is specified by:
357
    //     1. If plane is greater than 0, mode is set equal to uv_mode.
358
    //     2. Otherwise, if MiSize is greater than or equal to BLOCK_8X8, mode is set equal to y_mode.
359
    //     3. Otherwise, mode is set equal to sub_modes[ blockIdx ].
360
16.2M
    PredictionMode mode;
361
16.2M
    if (plane > 0)
362
6.45M
        mode = block_context.uv_prediction_mode;
363
9.77M
    else if (block_context.size >= Block_8x8)
364
8.88M
        mode = block_context.y_prediction_mode();
365
896k
    else
366
896k
        mode = block_context.sub_block_prediction_modes[block_index];
367
368
    // The variable log2Size specifying the base 2 logarithm of the width of the transform block is set equal to txSz + 2.
369
16.2M
    u8 log2_of_block_size = tx_size + 2;
370
    // The variable size is set equal to 1 << log2Size.
371
16.2M
    u8 block_size = 1 << log2_of_block_size;
372
373
    // The variable maxX is set equal to (MiCols * 8) - 1.
374
    // The variable maxY is set equal to (MiRows * 8) - 1.
375
    // If plane is greater than 0, then:
376
    //  − maxX is set equal to ((MiCols * 8) >> subsampling_x) - 1.
377
    //  − maxY is set equal to ((MiRows * 8) >> subsampling_y) - 1.
378
16.2M
    auto output_size = block_context.frame_context.decoded_size(plane > 0);
379
16.2M
    auto max_x = output_size.width() - 1;
380
16.2M
    auto max_y = output_size.height() - 1;
381
382
1.50G
    auto const frame_buffer_at = [&](u32 row, u32 column) -> u16& {
383
1.50G
        return frame_buffer[row * output_size.width() + column];
384
1.50G
    };
385
386
    // The array aboveRow[ i ] for i = 0..size-1 is specified by:
387
    //     ..
388
    // The array aboveRow[ i ] for i = size..2*size-1 is specified by:
389
    //     ..
390
    // The array aboveRow[ i ] for i = -1 is specified by:
391
    //     ..
392
393
    // NOTE: above_row is an array ranging from 0 to (2*block_size).
394
    //       There are three sections to the array:
395
    //           - [0]
396
    //           - [1 .. block_size]
397
    //           - [block_size + 1 .. block_size * 2]
398
    //       The array indices must be offset by 1 to accommodate index -1.
399
16.2M
    Array<Intermediate, maximum_block_dimensions * 2 + 1> above_row;
400
445M
    auto above_row_at = [&](i32 index) -> Intermediate& {
401
445M
        return above_row[index + 1];
402
445M
    };
403
404
    // NOTE: This value is pre-calculated since it is reused in spec below.
405
    //       Use this to replace spec text "(1<<(BitDepth-1))".
406
16.2M
    Intermediate half_sample_value = (1 << (block_context.frame_context.color_config.bit_depth - 1));
407
408
    // The array aboveRow[ i ] for i = 0..size-1 is specified by:
409
16.2M
    if (!have_above) {
410
        // 1. If haveAbove is equal to 0, aboveRow[ i ] is set equal to (1<<(BitDepth-1)) - 1.
411
        // FIXME: Use memset?
412
1.64M
        for (auto i = 0u; i < block_size; i++)
413
1.42M
            above_row_at(i) = half_sample_value - 1;
414
16.0M
    } else {
415
        // 2. Otherwise, aboveRow[ i ] is set equal to CurrFrame[ plane ][ y-1 ][ Min(maxX, x+i) ].
416
115M
        for (auto i = 0u; i < block_size; i++)
417
99.9M
            above_row_at(i) = frame_buffer_at(y - 1, min(max_x, x + i));
418
16.0M
    }
419
420
    // The array aboveRow[ i ] for i = size..2*size-1 is specified by:
421
16.2M
    if (have_above && not_on_right && tx_size == Transform_4x4) {
422
        // 1. If haveAbove is equal to 1 and notOnRight is equal to 1 and txSz is equal to 0,
423
        //    aboveRow[ i ] is set equal to CurrFrame[ plane ][ y-1 ][ Min(maxX, x+i) ].
424
54.0M
        for (auto i = block_size; i < block_size * 2; i++)
425
43.2M
            above_row_at(i) = frame_buffer_at(y - 1, min(max_x, x + i));
426
10.8M
    } else {
427
        // 2. Otherwise, aboveRow[ i ] is set equal to aboveRow[ size-1 ].
428
63.6M
        for (auto i = block_size; i < block_size * 2; i++)
429
58.2M
            above_row_at(i) = above_row_at(block_size - 1);
430
5.41M
    }
431
432
    // The array aboveRow[ i ] for i = -1 is specified by:
433
16.2M
    if (have_above && have_left) {
434
        // 1. If haveAbove is equal to 1 and haveLeft is equal to 1, aboveRow[ -1 ] is set equal to
435
        //    CurrFrame[ plane ][ y-1 ][ Min(maxX, x-1) ].
436
15.1M
        above_row_at(-1) = frame_buffer_at(y - 1, min(max_x, x - 1));
437
15.1M
    } else if (have_above) {
438
        // 2. Otherwise if haveAbove is equal to 1, aboveRow[ -1] is set equal to (1<<(BitDepth-1)) + 1.
439
828k
        above_row_at(-1) = half_sample_value + 1;
440
828k
    } else {
441
        // 3. Otherwise, aboveRow[ -1 ] is set equal to (1<<(BitDepth-1)) - 1
442
222k
        above_row_at(-1) = half_sample_value - 1;
443
222k
    }
444
445
    // The array leftCol[ i ] for i = 0..size-1 is specified by:
446
16.2M
    Array<Intermediate, maximum_block_dimensions> left_column;
447
16.2M
    if (have_left) {
448
        // − If haveLeft is equal to 1, leftCol[ i ] is set equal to CurrFrame[ plane ][ Min(maxY, y+i) ][ x-1 ].
449
110M
        for (auto i = 0u; i < block_size; i++)
450
95.1M
            left_column[i] = frame_buffer_at(min(max_y, y + i), x - 1);
451
15.3M
    } else {
452
        // − Otherwise, leftCol[ i ] is set equal to (1<<(BitDepth-1)) + 1.
453
7.10M
        for (auto i = 0u; i < block_size; i++)
454
6.26M
            left_column[i] = half_sample_value + 1;
455
834k
    }
456
457
    // A 2D array named pred containing the intra predicted samples is constructed as follows:
458
16.2M
    Array<Intermediate, maximum_block_size> predicted_samples;
459
2.55G
    auto const predicted_sample_at = [&](u32 row, u32 column) -> Intermediate& {
460
2.55G
        return predicted_samples[row * block_size + column];
461
2.55G
    };
462
463
    // FIXME: One of the two below should be a simple memcpy of 1D arrays.
464
16.2M
    switch (mode) {
465
374k
    case PredictionMode::VPred:
466
        // − If mode is equal to V_PRED, pred[ i ][ j ] is set equal to aboveRow[ j ] with j = 0..size-1 and i = 0..size-1
467
        // (each row of the block is filled with a copy of aboveRow).
468
2.39M
        for (auto j = 0u; j < block_size; j++) {
469
18.3M
            for (auto i = 0u; i < block_size; i++)
470
16.3M
                predicted_sample_at(i, j) = above_row_at(j);
471
2.02M
        }
472
374k
        break;
473
631k
    case PredictionMode::HPred:
474
        // − Otherwise if mode is equal to H_PRED, pred[ i ][ j ] is set equal to leftCol[ i ] with j = 0..size-1 and i =
475
        // 0..size-1 (each column of the block is filled with a copy of leftCol).
476
4.06M
        for (auto j = 0u; j < block_size; j++) {
477
31.7M
            for (auto i = 0u; i < block_size; i++)
478
28.3M
                predicted_sample_at(i, j) = left_column[i];
479
3.43M
        }
480
631k
        break;
481
491k
    case PredictionMode::D207Pred:
482
        // − Otherwise if mode is equal to D207_PRED, the following applies:
483
        // 1. pred[ size - 1 ][ j ] = leftCol[ size - 1] for j = 0..size-1
484
2.90M
        for (auto j = 0u; j < block_size; j++)
485
2.41M
            predicted_sample_at(block_size - 1, j) = left_column[block_size - 1];
486
        // 2. pred[ i ][ 0 ] = Round2( leftCol[ i ] + leftCol[ i + 1 ], 1 ) for i = 0..size-2
487
2.41M
        for (auto i = 0u; i < block_size - 1u; i++)
488
1.92M
            predicted_sample_at(i, 0) = rounded_right_shift(left_column[i] + left_column[i + 1], 1);
489
        // 3. pred[ i ][ 1 ] = Round2( leftCol[ i ] + 2 * leftCol[ i + 1 ] + leftCol[ i + 2 ], 2 ) for i = 0..size-3
490
1.92M
        for (auto i = 0u; i < block_size - 2u; i++)
491
1.43M
            predicted_sample_at(i, 1) = rounded_right_shift(left_column[i] + (2 * left_column[i + 1]) + left_column[i + 2], 2);
492
        // 4. pred[ size - 2 ][ 1 ] = Round2( leftCol[ size - 2 ] + 3 * leftCol[ size - 1 ], 2 )
493
491k
        predicted_sample_at(block_size - 2, 1) = rounded_right_shift(left_column[block_size - 2] + (3 * left_column[block_size - 1]), 2);
494
        // 5. pred[ i ][ j ] = pred[ i + 1 ][ j - 2 ] for i = (size-2)..0, for j = 2..size-1
495
        // NOTE – In the last step i iterates in reverse order.
496
1.92M
        for (auto i = block_size - 2u;;) {
497
12.5M
            for (auto j = 2u; j < block_size; j++)
498
10.6M
                predicted_sample_at(i, j) = predicted_sample_at(i + 1, j - 2);
499
1.92M
            if (i == 0)
500
491k
                break;
501
1.43M
            i--;
502
1.43M
        }
503
491k
        break;
504
128k
    case PredictionMode::D45Pred:
505
        // Otherwise if mode is equal to D45_PRED,
506
        // for i = 0..size-1, for j = 0..size-1.
507
850k
        for (auto i = 0u; i < block_size; i++) {
508
7.00M
            for (auto j = 0; j < block_size; j++) {
509
                // pred[ i ][ j ] is set equal to (i + j + 2 < size * 2) ?
510
6.28M
                if (i + j + 2 < block_size * 2)
511
                    // Round2( aboveRow[ i + j ] + aboveRow[ i + j + 1 ] * 2 + aboveRow[ i + j + 2 ], 2 ) :
512
6.15M
                    predicted_sample_at(i, j) = rounded_right_shift(above_row_at(i + j) + above_row_at(i + j + 1) * 2 + above_row_at(i + j + 2), 2);
513
127k
                else
514
                    // aboveRow[ 2 * size - 1 ]
515
127k
                    predicted_sample_at(i, j) = above_row_at(2 * block_size - 1);
516
6.28M
            }
517
722k
        }
518
128k
        break;
519
128k
    case PredictionMode::D63Pred:
520
        // Otherwise if mode is equal to D63_PRED,
521
844k
        for (auto i = 0u; i < block_size; i++) {
522
6.80M
            for (auto j = 0u; j < block_size; j++) {
523
                // i/2 + j
524
6.08M
                auto row_index = (i / 2) + j;
525
                // pred[ i ][ j ] is set equal to (i & 1) ?
526
6.08M
                if (i & 1)
527
                    // Round2( aboveRow[ i/2 + j ] + aboveRow[ i/2 + j + 1 ] * 2 + aboveRow[ i/2 + j + 2 ], 2 ) :
528
3.04M
                    predicted_sample_at(i, j) = rounded_right_shift(above_row_at(row_index) + above_row_at(row_index + 1) * 2 + above_row_at(row_index + 2), 2);
529
3.04M
                else
530
                    // Round2( aboveRow[ i/2 + j ] + aboveRow[ i/2 + j + 1 ], 1 ) for i = 0..size-1, for j = 0..size-1.
531
3.04M
                    predicted_sample_at(i, j) = rounded_right_shift(above_row_at(row_index) + above_row_at(row_index + 1), 1);
532
6.08M
            }
533
715k
        }
534
128k
        break;
535
121k
    case PredictionMode::D117Pred:
536
        // Otherwise if mode is equal to D117_PRED, the following applies:
537
        // 1. pred[ 0 ][ j ] = Round2( aboveRow[ j - 1 ] + aboveRow[ j ], 1 ) for j = 0..size-1
538
775k
        for (auto j = 0; j < block_size; j++)
539
653k
            predicted_sample_at(0, j) = rounded_right_shift(above_row_at(j - 1) + above_row_at(j), 1);
540
        // 2. pred[ 1 ][ 0 ] = Round2( leftCol[ 0 ] + 2 * aboveRow[ -1 ] + aboveRow[ 0 ], 2 )
541
121k
        predicted_sample_at(1, 0) = rounded_right_shift(left_column[0] + 2 * above_row_at(-1) + above_row_at(0), 2);
542
        // 3. pred[ 1 ][ j ] = Round2( aboveRow[ j - 2 ] + 2 * aboveRow[ j - 1 ] + aboveRow[ j ], 2 ) for j = 1..size-1
543
653k
        for (auto j = 1; j < block_size; j++)
544
532k
            predicted_sample_at(1, j) = rounded_right_shift(above_row_at(j - 2) + 2 * above_row_at(j - 1) + above_row_at(j), 2);
545
        // 4. pred[ 2 ][ 0 ] = Round2( aboveRow[ -1 ] + 2 * leftCol[ 0 ] + leftCol[ 1 ], 2 )
546
121k
        predicted_sample_at(2, 0) = rounded_right_shift(above_row_at(-1) + 2 * left_column[0] + left_column[1], 2);
547
        // 5. pred[ i ][ 0 ] = Round2( leftCol[ i - 3 ] + 2 * leftCol[ i - 2 ] + leftCol[ i - 1 ], 2 ) for i = 3..size-1
548
411k
        for (auto i = 3u; i < block_size; i++)
549
290k
            predicted_sample_at(i, 0) = rounded_right_shift(left_column[i - 3] + 2 * left_column[i - 2] + left_column[i - 1], 2);
550
        // 6. pred[ i ][ j ] = pred[ i - 2 ][ j - 1 ] for i = 2..size-1, for j = 1..size-1
551
532k
        for (auto i = 2u; i < block_size; i++) {
552
3.95M
            for (auto j = 1u; j < block_size; j++)
553
3.54M
                predicted_sample_at(i, j) = predicted_sample_at(i - 2, j - 1);
554
411k
        }
555
121k
        break;
556
235k
    case PredictionMode::D135Pred:
557
        // Otherwise if mode is equal to D135_PRED, the following applies:
558
        // 1. pred[ 0 ][ 0 ] = Round2( leftCol[ 0 ] + 2 * aboveRow[ -1 ] + aboveRow[ 0 ], 2 )
559
235k
        predicted_sample_at(0, 0) = rounded_right_shift(left_column[0] + 2 * above_row_at(-1) + above_row_at(0), 2);
560
        // 2. pred[ 0 ][ j ] = Round2( aboveRow[ j - 2 ] + 2 * aboveRow[ j - 1 ] + aboveRow[ j ], 2 ) for j = 1..size-1
561
1.31M
        for (auto j = 1; j < block_size; j++)
562
1.08M
            predicted_sample_at(0, j) = rounded_right_shift(above_row_at(j - 2) + 2 * above_row_at(j - 1) + above_row_at(j), 2);
563
        // 3. pred[ 1 ][ 0 ] = Round2( aboveRow [ -1 ] + 2 * leftCol[ 0 ] + leftCol[ 1 ], 2 ) for i = 1..size-1
564
235k
        predicted_sample_at(1, 0) = rounded_right_shift(above_row_at(-1) + 2 * left_column[0] + left_column[1], 2);
565
        // 4. pred[ i ][ 0 ] = Round2( leftCol[ i - 2 ] + 2 * leftCol[ i - 1 ] + leftCol[ i ], 2 ) for i = 2..size-1
566
1.08M
        for (auto i = 2u; i < block_size; i++)
567
845k
            predicted_sample_at(i, 0) = rounded_right_shift(left_column[i - 2] + 2 * left_column[i - 1] + left_column[i], 2);
568
        // 5. pred[ i ][ j ] = pred[ i - 1 ][ j - 1 ] for i = 1..size-1, for j = 1..size-1
569
1.31M
        for (auto i = 1u; i < block_size; i++) {
570
9.96M
            for (auto j = 1; j < block_size; j++)
571
8.88M
                predicted_sample_at(i, j) = predicted_sample_at(i - 1, j - 1);
572
1.08M
        }
573
235k
        break;
574
183k
    case PredictionMode::D153Pred:
575
        // Otherwise if mode is equal to D153_PRED, the following applies:
576
        // 1. pred[ 0 ][ 0 ] = Round2( leftCol[ 0 ] + aboveRow[ -1 ], 1 )
577
183k
        predicted_sample_at(0, 0) = rounded_right_shift(left_column[0] + above_row_at(-1), 1);
578
        // 2. pred[ i ][ 0 ] = Round2( leftCol[ i - 1] + leftCol[ i ], 1 ) for i = 1..size-1
579
1.00M
        for (auto i = 1u; i < block_size; i++)
580
824k
            predicted_sample_at(i, 0) = rounded_right_shift(left_column[i - 1] + left_column[i], 1);
581
        // 3. pred[ 0 ][ 1 ] = Round2( leftCol[ 0 ] + 2 * aboveRow[ -1 ] + aboveRow[ 0 ], 2 )
582
183k
        predicted_sample_at(0, 1) = rounded_right_shift(left_column[0] + 2 * above_row_at(-1) + above_row_at(0), 2);
583
        // 4. pred[ 1 ][ 1 ] = Round2( aboveRow[ -1 ] + 2 * leftCol [ 0 ] + leftCol [ 1 ], 2 )
584
183k
        predicted_sample_at(1, 1) = rounded_right_shift(above_row_at(-1) + 2 * left_column[0] + left_column[1], 2);
585
        // 5. pred[ i ][ 1 ] = Round2( leftCol[ i - 2 ] + 2 * leftCol[ i - 1 ] + leftCol[ i ], 2 ) for i = 2..size-1
586
824k
        for (auto i = 2u; i < block_size; i++)
587
640k
            predicted_sample_at(i, 1) = rounded_right_shift(left_column[i - 2] + 2 * left_column[i - 1] + left_column[i], 2);
588
        // 6. pred[ 0 ][ j ] = Round2( aboveRow[ j - 3 ] + 2 * aboveRow[ j - 2 ] + aboveRow[ j - 1 ], 2 ) for j = 2..size-1
589
824k
        for (auto j = 2; j < block_size; j++)
590
640k
            predicted_sample_at(0, j) = rounded_right_shift(above_row_at(j - 3) + 2 * above_row_at(j - 2) + above_row_at(j - 1), 2);
591
        // 7. pred[ i ][ j ] = pred[ i - 1 ][ j - 2 ] for i = 1..size-1, for j = 2..size-1
592
1.00M
        for (auto i = 1u; i < block_size; i++) {
593
6.60M
            for (auto j = 2u; j < block_size; j++)
594
5.77M
                predicted_sample_at(i, j) = predicted_sample_at(i - 1, j - 2);
595
824k
        }
596
183k
        break;
597
231k
    case PredictionMode::TmPred:
598
        // Otherwise if mode is equal to TM_PRED,
599
        // pred[ i ][ j ] is set equal to Clip1( aboveRow[ j ] + leftCol[ i ] - aboveRow[ -1 ] )
600
        // for i = 0..size-1, for j = 0..size-1.
601
1.54M
        for (auto i = 0u; i < block_size; i++) {
602
12.6M
            for (auto j = 0u; j < block_size; j++)
603
11.3M
                predicted_sample_at(i, j) = clip_1(block_context.frame_context.color_config.bit_depth, above_row_at(j) + left_column[i] - above_row_at(-1));
604
1.31M
        }
605
231k
        break;
606
13.6M
    case PredictionMode::DcPred: {
607
13.6M
        Intermediate average = 0;
608
609
13.6M
        if (have_left && have_above) {
610
            // Otherwise if mode is equal to DC_PRED and haveLeft is equal to 1 and haveAbove is equal to 1,
611
            // The variable avg (the average of the samples in union of aboveRow and leftCol)
612
            // is specified as follows:
613
            // sum = 0
614
            // for ( k = 0; k < size; k++ ) {
615
            //     sum += leftCol[ k ]
616
            //     sum += aboveRow[ k ]
617
            // }
618
            // avg = (sum + size) >> (log2Size + 1)
619
12.8M
            Intermediate sum = 0;
620
94.3M
            for (auto k = 0u; k < block_size; k++) {
621
81.4M
                sum += left_column[k];
622
81.4M
                sum += above_row_at(k);
623
81.4M
            }
624
12.8M
            average = (sum + block_size) >> (log2_of_block_size + 1);
625
12.8M
        } else if (have_left && !have_above) {
626
            // Otherwise if mode is equal to DC_PRED and haveLeft is equal to 1 and haveAbove is equal to 0,
627
            // The variable leftAvg is specified as follows:
628
            // sum = 0
629
            // for ( k = 0; k < size; k++ ) {
630
            //     sum += leftCol[ k ]
631
            // }
632
            // leftAvg = (sum + (1 << (log2Size - 1) ) ) >> log2Size
633
139k
            Intermediate sum = 0;
634
1.05M
            for (auto k = 0u; k < block_size; k++)
635
915k
                sum += left_column[k];
636
139k
            average = (sum + (1 << (log2_of_block_size - 1))) >> log2_of_block_size;
637
702k
        } else if (!have_left && have_above) {
638
            // Otherwise if mode is equal to DC_PRED and haveLeft is equal to 0 and haveAbove is equal to 1,
639
            // The variable aboveAvg is specified as follows:
640
            // sum = 0
641
            // for ( k = 0; k < size; k++ ) {
642
            // sum += aboveRow[ k ]
643
            // }
644
            // aboveAvg = (sum + (1 << (log2Size - 1) ) ) >> log2Size
645
699k
            Intermediate sum = 0;
646
6.17M
            for (auto k = 0u; k < block_size; k++)
647
5.47M
                sum += above_row_at(k);
648
699k
            average = (sum + (1 << (log2_of_block_size - 1))) >> log2_of_block_size;
649
18.4E
        } else {
650
            // Otherwise (mode is DC_PRED),
651
            // pred[ i ][ j ] is set equal to 1<<(BitDepth - 1) with i = 0..size-1 and j = 0..size-1.
652
18.4E
            average = 1 << (block_context.frame_context.color_config.bit_depth - 1);
653
18.4E
        }
654
655
        // pred[ i ][ j ] is set equal to avg with i = 0..size-1 and j = 0..size-1.
656
101M
        for (auto i = 0u; i < block_size; i++) {
657
1.26G
            for (auto j = 0u; j < block_size; j++)
658
1.17G
                predicted_sample_at(i, j) = average;
659
87.8M
        }
660
13.6M
        break;
661
0
    }
662
0
    default:
663
0
        dbgln("Unknown prediction mode {}", static_cast<u8>(mode));
664
0
        VERIFY_NOT_REACHED();
665
16.2M
    }
666
667
    // The current frame is updated as follows:
668
    // − CurrFrame[ plane ][ y + i ][ x + j ] is set equal to pred[ i ][ j ] for i = 0..size-1 and j = 0..size-1.
669
16.2M
    auto width_in_frame_buffer = min(static_cast<u32>(block_size), max_x - x + 1);
670
16.2M
    auto height_in_frame_buffer = min(static_cast<u32>(block_size), max_y - y + 1);
671
672
117M
    for (auto i = 0u; i < height_in_frame_buffer; i++) {
673
1.35G
        for (auto j = 0u; j < width_in_frame_buffer; j++)
674
1.25G
            frame_buffer_at(y + i, x + j) = predicted_sample_at(i, j);
675
101M
    }
676
677
16.2M
    return {};
678
16.2M
}
679
680
MotionVector Decoder::select_motion_vector(u8 plane, BlockContext const& block_context, ReferenceIndex reference_index, u32 block_index)
681
184k
{
682
    // The inputs to this process are:
683
    // − a variable plane specifying which plane is being predicted,
684
    // − a variable refList specifying that we should select the motion vector from BlockMvs[ refList ],
685
    // − a variable blockIdx, specifying how much of the block has already been predicted in units of 4x4 samples.
686
    // The output of this process is a 2 element array called mv containing the motion vector for this block.
687
688
    // The purpose of this process is to find the motion vector for this block. Motion vectors are specified for each
689
    // luma block, but a chroma block may cover more than one luma block due to subsampling. In this case, an
690
    // average motion vector is constructed for the chroma block.
691
692
    // The functions round_mv_comp_q2 and round_mv_comp_q4 perform division with rounding to the nearest
693
    // integer and are specified as:
694
184k
    auto round_mv_comp_q2 = [&](MotionVector in) {
695
        // return (value < 0 ? value - 1 : value + 1) / 2
696
0
        return MotionVector {
697
0
            (in.row() < 0 ? in.row() - 1 : in.row() + 1) / 2,
698
0
            (in.column() < 0 ? in.column() - 1 : in.column() + 1) / 2
699
0
        };
700
0
    };
701
184k
    auto round_mv_comp_q4 = [&](MotionVector in) {
702
        // return (value < 0 ? value - 2 : value + 2) / 4
703
25.7k
        return MotionVector {
704
25.7k
            (in.row() < 0 ? in.row() - 2 : in.row() + 2) / 4,
705
25.7k
            (in.column() < 0 ? in.column() - 2 : in.column() + 2) / 4
706
25.7k
        };
707
25.7k
    };
708
709
184k
    auto vectors = block_context.sub_block_motion_vectors;
710
711
    // The motion vector array mv is derived as follows:
712
    // − If plane is equal to 0, or MiSize is greater than or equal to BLOCK_8X8, mv is set equal to
713
    // BlockMvs[ refList ][ blockIdx ].
714
184k
    if (plane == 0 || block_context.size >= Block_8x8)
715
158k
        return vectors[block_index][reference_index];
716
    // − Otherwise, if subsampling_x is equal to 0 and subsampling_y is equal to 0, mv is set equal to
717
    // BlockMvs[ refList ][ blockIdx ].
718
25.7k
    if (!block_context.frame_context.color_config.subsampling_x && !block_context.frame_context.color_config.subsampling_y)
719
0
        return vectors[block_index][reference_index];
720
    // − Otherwise, if subsampling_x is equal to 0 and subsampling_y is equal to 1, mv[ comp ] is set equal to
721
    // round_mv_comp_q2( BlockMvs[ refList ][ blockIdx ][ comp ] + BlockMvs[ refList ][ blockIdx + 2 ][ comp ] )
722
    // for comp = 0..1.
723
25.7k
    if (!block_context.frame_context.color_config.subsampling_x && block_context.frame_context.color_config.subsampling_y)
724
0
        return round_mv_comp_q2(vectors[block_index][reference_index] + vectors[block_index + 2][reference_index]);
725
    // − Otherwise, if subsampling_x is equal to 1 and subsampling_y is equal to 0, mv[ comp ] is set equal to
726
    // round_mv_comp_q2( BlockMvs[ refList ][ blockIdx ][ comp ] + BlockMvs[ refList ][ blockIdx + 1 ][ comp ] )
727
    // for comp = 0..1.
728
25.7k
    if (block_context.frame_context.color_config.subsampling_x && !block_context.frame_context.color_config.subsampling_y)
729
0
        return round_mv_comp_q2(vectors[block_index][reference_index] + vectors[block_index + 1][reference_index]);
730
    // − Otherwise, (subsampling_x is equal to 1 and subsampling_y is equal to 1), mv[ comp ] is set equal to
731
    // round_mv_comp_q4( BlockMvs[ refList ][ 0 ][ comp ] + BlockMvs[ refList ][ 1 ][ comp ] +
732
    // BlockMvs[ refList ][ 2 ][ comp ] + BlockMvs[ refList ][ 3 ][ comp ] ) for comp = 0..1.
733
25.7k
    VERIFY(block_context.frame_context.color_config.subsampling_x && block_context.frame_context.color_config.subsampling_y);
734
25.7k
    return round_mv_comp_q4(vectors[0][reference_index] + vectors[1][reference_index]
735
25.7k
        + vectors[2][reference_index] + vectors[3][reference_index]);
736
25.7k
}
737
738
MotionVector Decoder::clamp_motion_vector(u8 plane, BlockContext const& block_context, u32 block_row, u32 block_column, MotionVector vector)
739
184k
{
740
    // FIXME: This function is named very similarly to Parser::clamp_mv. Rename one or the other?
741
742
    // The purpose of this process is to change the motion vector into the appropriate precision for the current plane
743
    // and to clamp motion vectors that go too far off the edge of the frame.
744
    // The variables sx and sy are set equal to the subsampling for the current plane as follows:
745
    // − If plane is equal to 0, sx is set equal to 0 and sy is set equal to 0.
746
    // − Otherwise, sx is set equal to subsampling_x and sy is set equal to subsampling_y.
747
184k
    bool subsampling_x = plane > 0 ? block_context.frame_context.color_config.subsampling_x : false;
748
184k
    bool subsampling_y = plane > 0 ? block_context.frame_context.color_config.subsampling_y : false;
749
750
    // The output array clampedMv is specified by the following steps:
751
184k
    i32 blocks_high = num_8x8_blocks_high_lookup[block_context.size];
752
    // Casts must be done here to prevent subtraction underflow from wrapping the values.
753
184k
    i32 mb_to_top_edge = -(static_cast<i32>(block_row * MI_SIZE) * 16) >> subsampling_y;
754
184k
    i32 mb_to_bottom_edge = (((static_cast<i32>(block_context.frame_context.rows()) - blocks_high - static_cast<i32>(block_row)) * MI_SIZE) * 16) >> subsampling_y;
755
756
184k
    i32 blocks_wide = num_8x8_blocks_wide_lookup[block_context.size];
757
184k
    i32 mb_to_left_edge = -(static_cast<i32>(block_column * MI_SIZE) * 16) >> subsampling_x;
758
184k
    i32 mb_to_right_edge = (((static_cast<i32>(block_context.frame_context.columns()) - blocks_wide - static_cast<i32>(block_column)) * MI_SIZE) * 16) >> subsampling_x;
759
760
184k
    i32 subpel_left = (INTERP_EXTEND + ((blocks_wide * MI_SIZE) >> subsampling_x)) << SUBPEL_BITS;
761
184k
    i32 subpel_right = subpel_left - SUBPEL_SHIFTS;
762
184k
    i32 subpel_top = (INTERP_EXTEND + ((blocks_high * MI_SIZE) >> subsampling_y)) << SUBPEL_BITS;
763
184k
    i32 subpel_bottom = subpel_top - SUBPEL_SHIFTS;
764
184k
    return {
765
184k
        clip_3(mb_to_top_edge - subpel_top, mb_to_bottom_edge + subpel_bottom, (2 * vector.row()) >> subsampling_y),
766
184k
        clip_3(mb_to_left_edge - subpel_left, mb_to_right_edge + subpel_right, (2 * vector.column()) >> subsampling_x)
767
184k
    };
768
184k
}
769
770
static constexpr i32 maximum_scaled_step = 80;
771
772
DecoderErrorOr<void> Decoder::prepare_referenced_frame(Gfx::Size<u32> frame_size, u8 reference_frame_index)
773
3.81k
{
774
3.81k
    ReferenceFrame& reference_frame = m_parser->m_reference_frames[reference_frame_index];
775
776
    // 8.5.2.3 Motion vector scaling process
777
    // The inputs to this process are:
778
    // − a variable plane specifying which plane is being predicted,
779
    // − a variable refList specifying that we should scale to match reference frame ref_frame[ refList ],
780
    // − variables x and y specifying the location of the top left sample in the CurrFrame[ plane ] array of the region
781
    // to be predicted,
782
    // − a variable clampedMv specifying the clamped motion vector.
783
    // The outputs of this process are the variables startX and startY giving the reference block location in units of
784
    // 1/16 th of a sample, and variables xStep and yStep giving the step size in units of 1/16 th of a sample.
785
    // This process is responsible for computing the sampling locations in the reference frame based on the motion
786
    // vector. The sampling locations are also adjusted to compensate for any difference in the size of the reference
787
    // frame compared to the current frame.
788
789
    // It is a requirement of bitstream conformance that all the following conditions are satisfied:
790
    // − 2 * FrameWidth >= RefFrameWidth[ refIdx ]
791
    // − 2 * FrameHeight >= RefFrameHeight[ refIdx ]
792
    // − FrameWidth <= 16 * RefFrameWidth[ refIdx ]
793
    // − FrameHeight <= 16 * RefFrameHeight[ refIdx ]
794
3.81k
    if (!reference_frame.is_valid())
795
3
        return DecoderError::format(DecoderErrorCategory::Corrupted, "Attempted to use reference frame {} that has not been saved", reference_frame_index);
796
3.81k
    auto double_frame_size = frame_size.scaled(2);
797
3.81k
    if (double_frame_size.width() < reference_frame.size.width() || double_frame_size.height() < reference_frame.size.height())
798
4
        return DecoderError::format(DecoderErrorCategory::Corrupted, "Inter frame size is too small relative to reference frame {}", reference_frame_index);
799
3.80k
    if (!reference_frame.size.scaled(16).contains(frame_size))
800
2
        return DecoderError::format(DecoderErrorCategory::Corrupted, "Inter frame size is too large relative to reference frame {}", reference_frame_index);
801
802
    // FIXME: Convert all the operations in this function to vector operations supported by
803
    //        MotionVector.
804
805
    // A variable xScale is set equal to (RefFrameWidth[ refIdx ] << REF_SCALE_SHIFT) / FrameWidth.
806
    // A variable yScale is set equal to (RefFrameHeight[ refIdx ] << REF_SCALE_SHIFT) / FrameHeight.
807
    // (xScale and yScale specify the size of the reference frame relative to the current frame in units where 16 is
808
    // equivalent to the reference frame having the same size.)
809
    // NOTE: This spec note above seems to be incorrect. The 1:1 scale value would be 16,384.
810
3.80k
    i32 x_scale = (reference_frame.size.width() << REF_SCALE_SHIFT) / frame_size.width();
811
3.80k
    i32 y_scale = (reference_frame.size.height() << REF_SCALE_SHIFT) / frame_size.height();
812
813
    // The output variable stepX is set equal to (16 * xScale) >> REF_SCALE_SHIFT.
814
    // The output variable stepY is set equal to (16 * yScale) >> REF_SCALE_SHIFT.
815
3.80k
    i32 scaled_step_x = (16 * x_scale) >> REF_SCALE_SHIFT;
816
3.80k
    i32 scaled_step_y = (16 * y_scale) >> REF_SCALE_SHIFT;
817
818
    // 5. The block inter prediction process in section 8.5.2.4 is invoked with plane, refList, startX, startY, stepX,
819
    // stepY, w, h as inputs and the output is assigned to the 2D array preds[ refList ].
820
821
    // 8.5.2.4 Block inter prediction process
822
    // The inputs to this process are:
823
    // − a variable plane,
824
    // − a variable refList specifying that we should predict from ref_frame[ refList ],
825
    // − variables x and y giving the block location in units of 1/16 th of a sample,
826
    // − variables xStep and yStep giving the step size in units of 1/16 th of a sample. (These will be at most equal
827
    // to 80 due to the restrictions on scaling between reference frames.)
828
3.80k
    VERIFY(scaled_step_x <= maximum_scaled_step && scaled_step_y <= maximum_scaled_step);
829
    // − variables w and h giving the width and height of the block in units of samples
830
    // The output from this process is the 2D array named pred containing inter predicted samples.
831
832
3.80k
    reference_frame.x_scale = x_scale;
833
3.80k
    reference_frame.y_scale = x_scale;
834
3.80k
    reference_frame.scaled_step_x = scaled_step_x;
835
3.80k
    reference_frame.scaled_step_y = scaled_step_y;
836
837
3.80k
    return {};
838
3.80k
}
839
840
DecoderErrorOr<void> Decoder::predict_inter_block(u8 plane, BlockContext const& block_context, ReferenceIndex reference_index, u32 block_row, u32 block_column, u32 x, u32 y, u32 width, u32 height, u32 block_index, Span<u16> block_buffer)
841
184k
{
842
184k
    VERIFY(width <= maximum_block_dimensions && height <= maximum_block_dimensions);
843
    // 2. The motion vector selection process in section 8.5.2.1 is invoked with plane, refList, blockIdx as inputs
844
    // and the output being the motion vector mv.
845
184k
    auto motion_vector = select_motion_vector(plane, block_context, reference_index, block_index);
846
847
    // 3. The motion vector clamping process in section 8.5.2.2 is invoked with plane, mv as inputs and the output
848
    // being the clamped motion vector clampedMv
849
184k
    auto clamped_vector = clamp_motion_vector(plane, block_context, block_row, block_column, motion_vector);
850
851
    // 4. The motion vector scaling process in section 8.5.2.3 is invoked with plane, refList, x, y, clampedMv as
852
    // inputs and the output being the initial location startX, startY, and the step sizes stepX, stepY.
853
854
    // 8.5.2.3 Motion vector scaling process
855
    // The inputs to this process are:
856
    // − a variable plane specifying which plane is being predicted,
857
    // − a variable refList specifying that we should scale to match reference frame ref_frame[ refList ],
858
    // − variables x and y specifying the location of the top left sample in the CurrFrame[ plane ] array of the region
859
    // to be predicted,
860
    // − a variable clampedMv specifying the clamped motion vector.
861
    // The outputs of this process are the variables startX and startY giving the reference block location in units of
862
    // 1/16 th of a sample, and variables xStep and yStep giving the step size in units of 1/16 th of a sample.
863
    // This process is responsible for computing the sampling locations in the reference frame based on the motion
864
    // vector. The sampling locations are also adjusted to compensate for any difference in the size of the reference
865
    // frame compared to the current frame.
866
867
    // NOTE: Some of this is done in advance by Decoder::prepare_referenced_frame().
868
869
    // A variable refIdx specifying which reference frame is being used is set equal to
870
    // ref_frame_idx[ ref_frame[ refList ] - LAST_FRAME ].
871
184k
    auto reference_frame_index = block_context.frame_context.reference_frame_indices[block_context.reference_frame_types[reference_index] - ReferenceFrameType::LastFrame];
872
184k
    auto const& reference_frame = m_parser->m_reference_frames[reference_frame_index];
873
874
    // Scale values range from 8192 to 262144.
875
    // 16384 = 1:1, higher values indicate the reference frame is larger than the current frame.
876
184k
    auto x_scale = reference_frame.x_scale;
877
184k
    auto y_scale = reference_frame.y_scale;
878
879
    // The amount of subpixels between each sample of this block. Non-16 values will cause the output to be scaled.
880
184k
    auto scaled_step_x = reference_frame.scaled_step_x;
881
184k
    auto scaled_step_y = reference_frame.scaled_step_y;
882
883
    // The variable baseX is set equal to (x * xScale) >> REF_SCALE_SHIFT.
884
    // The variable baseY is set equal to (y * yScale) >> REF_SCALE_SHIFT.
885
    // (baseX and baseY specify the location of the block in the reference frame if a zero motion vector is used).
886
184k
    i32 base_x = (x * x_scale) >> REF_SCALE_SHIFT;
887
184k
    i32 base_y = (y * y_scale) >> REF_SCALE_SHIFT;
888
889
    // The variable lumaX is set equal to (plane > 0) ? x << subsampling_x : x.
890
    // The variable lumaY is set equal to (plane > 0) ? y << subsampling_y : y.
891
    // (lumaX and lumaY specify the location of the block to be predicted in the current frame in units of luma
892
    // samples.)
893
184k
    bool subsampling_x = plane > 0 ? block_context.frame_context.color_config.subsampling_x : false;
894
184k
    bool subsampling_y = plane > 0 ? block_context.frame_context.color_config.subsampling_y : false;
895
184k
    i32 luma_x = x << subsampling_x;
896
184k
    i32 luma_y = y << subsampling_y;
897
898
    // The variable fracX is set equal to ( (16 * lumaX * xScale) >> REF_SCALE_SHIFT) & SUBPEL_MASK.
899
    // The variable fracY is set equal to ( (16 * lumaY * yScale) >> REF_SCALE_SHIFT) & SUBPEL_MASK.
900
184k
    i32 frac_x = ((16 * luma_x * x_scale) >> REF_SCALE_SHIFT) & SUBPEL_MASK;
901
184k
    i32 frac_y = ((16 * luma_y * y_scale) >> REF_SCALE_SHIFT) & SUBPEL_MASK;
902
903
    // The variable dX is set equal to ( (clampedMv[ 1 ] * xScale) >> REF_SCALE_SHIFT) + fracX.
904
    // The variable dY is set equal to ( (clampedMv[ 0 ] * yScale) >> REF_SCALE_SHIFT) + fracY.
905
    // (dX and dY specify a scaled motion vector.)
906
184k
    i32 scaled_vector_x = ((clamped_vector.column() * x_scale) >> REF_SCALE_SHIFT) + frac_x;
907
184k
    i32 scaled_vector_y = ((clamped_vector.row() * y_scale) >> REF_SCALE_SHIFT) + frac_y;
908
909
    // The output variable startX is set equal to (baseX << SUBPEL_BITS) + dX.
910
    // The output variable startY is set equal to (baseY << SUBPEL_BITS) + dY.
911
184k
    i32 offset_scaled_block_x = (base_x << SUBPEL_BITS) + scaled_vector_x;
912
184k
    i32 offset_scaled_block_y = (base_y << SUBPEL_BITS) + scaled_vector_y;
913
914
    // A variable ref specifying the reference frame contents is set equal to FrameStore[ refIdx ].
915
184k
    auto& reference_frame_buffer = reference_frame.frame_planes[plane];
916
184k
    auto reference_frame_width = Subsampling::subsampled_size(subsampling_x, reference_frame.size.width()) + MV_BORDER * 2;
917
918
    // The variable lastX is set equal to ( (RefFrameWidth[ refIdx ] + subX) >> subX) - 1.
919
    // The variable lastY is set equal to ( (RefFrameHeight[ refIdx ] + subY) >> subY) - 1.
920
    // (lastX and lastY specify the coordinates of the bottom right sample of the reference plane.)
921
    // Ad-hoc: These variables are not needed, since the reference frame is expanded to contain the samples that
922
    // may be referenced by motion vectors on the edge of the frame.
923
924
    // The sub-sample interpolation is effected via two one-dimensional convolutions. First a horizontal filter is used
925
    // to build up a temporary array, and then this array is vertically filtered to obtain the final prediction. The
926
    // fractional parts of the motion vectors determine the filtering process. If the fractional part is zero, then the
927
    // filtering is equivalent to a straight sample copy.
928
    // The filtering is applied as follows:
929
930
184k
    constexpr auto sample_offset = 3;
931
932
184k
    auto subpixel_row_from_reference_row = [offset_scaled_block_y](u32 row) {
933
184k
        return (offset_scaled_block_y >> SUBPEL_BITS) + static_cast<i32>(row);
934
184k
    };
935
184k
    auto reference_index_for_row = [reference_frame_width](i32 row) {
936
184k
        return static_cast<size_t>(MV_BORDER + row) * reference_frame_width;
937
184k
    };
938
939
    // The variable intermediateHeight specifying the height required for the intermediate array is set equal to (((h -
940
    // 1) * yStep + 15) >> 4) + 8.
941
184k
    static constexpr auto maximum_intermediate_height = (((maximum_block_dimensions - 1) * maximum_scaled_step + 15) >> 4) + 8;
942
184k
    auto const intermediate_height = (((height - 1) * scaled_step_y + 15) >> 4) + 8;
943
184k
    VERIFY(intermediate_height <= maximum_intermediate_height);
944
    // Check our reference frame bounds before starting the loop.
945
184k
    auto const last_possible_reference_index = reference_index_for_row(subpixel_row_from_reference_row(intermediate_height - sample_offset));
946
184k
    VERIFY(reference_frame_buffer.size() >= last_possible_reference_index);
947
948
184k
    VERIFY(block_buffer.size() >= static_cast<size_t>(width) * height);
949
950
184k
    auto const reference_block_x = MV_BORDER + (offset_scaled_block_x >> SUBPEL_BITS);
951
184k
    auto const reference_block_y = MV_BORDER + (offset_scaled_block_y >> SUBPEL_BITS);
952
184k
    auto const reference_subpixel_x = offset_scaled_block_x & SUBPEL_MASK;
953
184k
    auto const reference_subpixel_y = offset_scaled_block_y & SUBPEL_MASK;
954
955
    // OPTIMIZATION: If the fractional part of a component of the motion vector is 0, we want to do a fast path
956
    //               skipping one or both of the convolutions.
957
184k
    bool const copy_x = reference_subpixel_x == 0;
958
184k
    bool const copy_y = reference_subpixel_y == 0;
959
184k
    bool const unscaled_x = scaled_step_x == 16;
960
184k
    bool const unscaled_y = scaled_step_y == 16;
961
962
    // The array intermediate is specified as follows:
963
    // Note: Height is specified by `intermediate_height`, width is specified by `width`
964
184k
    Array<u16, maximum_intermediate_height * maximum_block_dimensions> intermediate_buffer;
965
184k
    auto const bit_depth = block_context.frame_context.color_config.bit_depth;
966
184k
    auto const* reference_start = reference_frame_buffer.data() + reference_block_y * reference_frame_width + reference_block_x;
967
968
    // FIXME: We are using 16-bit products to vectorize the filter loops, but when filtering in a high bit-depth video, they will truncate.
969
    //        Instead of hardcoding them, we should have the bit depth as a template parameter, and the accumulators can select a size based
970
    //        on whether the bit depth > 8.
971
    //        Note that we only get a benefit from this on the default CPU target. If we enable AVX2 here, we may want to specialize the
972
    //        function for the CPU target and remove the cast to i16 so that it doesn't have to truncate on AVX2, where it can do the full
973
    //        unrolled 32-bit product loops in one vector.
974
975
184k
    if (unscaled_x && unscaled_y && bit_depth == 8) {
976
144k
        if (copy_x && copy_y) {
977
            // We can memcpy here to avoid doing any real work.
978
59.1k
            auto const* reference_scan_line = &reference_frame_buffer[reference_block_y * reference_frame_width + reference_block_x];
979
59.1k
            auto* destination_scan_line = block_buffer.data();
980
981
469k
            for (auto row = 0u; row < height; row++) {
982
409k
                memcpy(destination_scan_line, reference_scan_line, width * sizeof(*destination_scan_line));
983
409k
                reference_scan_line += reference_frame_width;
984
409k
                destination_scan_line += width;
985
409k
            }
986
987
59.1k
            return {};
988
59.1k
        }
989
990
85.0k
        auto horizontal_convolution_unscaled = [](auto bit_depth, auto* destination, auto width, auto height, auto const* source, auto source_stride, auto filter, auto subpixel_x) {
991
68.3k
            source -= sample_offset;
992
68.3k
            auto const source_end_skip = source_stride - width;
993
994
825k
            for (auto row = 0u; row < height; row++) {
995
9.16M
                for (auto column = 0u; column < width; column++) {
996
8.40M
                    i32 accumulated_samples = 0;
997
75.6M
                    for (auto t = 0; t < 8; t++) {
998
67.2M
                        auto sample = source[t];
999
67.2M
                        accumulated_samples += static_cast<i16>(subpel_filters[filter][subpixel_x][t] * sample);
1000
67.2M
                    }
1001
1002
8.40M
                    *destination = clip_1(bit_depth, rounded_right_shift(accumulated_samples, 7));
1003
8.40M
                    source++;
1004
8.40M
                    destination++;
1005
8.40M
                }
1006
757k
                source += source_end_skip;
1007
757k
            }
1008
68.3k
        };
1009
1010
85.0k
        if (copy_y) {
1011
26.9k
            horizontal_convolution_unscaled(bit_depth, block_buffer.data(), width, height, reference_start, reference_frame_width, block_context.interpolation_filter, reference_subpixel_x);
1012
26.9k
            return {};
1013
26.9k
        }
1014
1015
58.1k
        auto vertical_convolution_unscaled = [](auto bit_depth, auto* destination, auto width, auto height, auto const* source, auto source_stride, auto filter, auto subpixel_y) {
1016
58.1k
            auto const source_end_skip = source_stride - width;
1017
1018
457k
            for (auto row = 0u; row < height; row++) {
1019
5.22M
                for (auto column = 0u; column < width; column++) {
1020
4.82M
                    auto const* scan_column = source;
1021
4.82M
                    i32 accumulated_samples = 0;
1022
43.3M
                    for (auto t = 0; t < 8; t++) {
1023
38.5M
                        auto sample = *scan_column;
1024
38.5M
                        accumulated_samples += static_cast<i16>(subpel_filters[filter][subpixel_y][t] * sample);
1025
38.5M
                        scan_column += source_stride;
1026
38.5M
                    }
1027
4.82M
                    *destination = clip_1(bit_depth, rounded_right_shift(accumulated_samples, 7));
1028
4.82M
                    source++;
1029
4.82M
                    destination++;
1030
4.82M
                }
1031
399k
                source += source_end_skip;
1032
399k
            }
1033
58.1k
        };
1034
1035
58.1k
        if (copy_x) {
1036
16.7k
            vertical_convolution_unscaled(bit_depth, block_buffer.data(), width, height, reference_start - (sample_offset * reference_frame_width), reference_frame_width, block_context.interpolation_filter, reference_subpixel_y);
1037
16.7k
            return {};
1038
16.7k
        }
1039
1040
41.3k
        horizontal_convolution_unscaled(bit_depth, intermediate_buffer.data(), width, intermediate_height, reference_start - (sample_offset * reference_frame_width), reference_frame_width, block_context.interpolation_filter, reference_subpixel_x);
1041
41.3k
        vertical_convolution_unscaled(bit_depth, block_buffer.data(), width, height, intermediate_buffer.data(), width, block_context.interpolation_filter, reference_subpixel_y);
1042
41.3k
        return {};
1043
58.1k
    }
1044
1045
    // NOTE: Accumulators below are 32-bit to allow high bit-depth videos to decode without overflows.
1046
    //       These should be changed when the accumulators above are.
1047
1048
40.4k
    auto horizontal_convolution_scaled = [](auto bit_depth, auto* destination, auto width, auto height, auto const* source, auto source_stride, auto filter, auto subpixel_x, auto scale_x) {
1049
40.4k
        source -= sample_offset;
1050
1051
511k
        for (auto row = 0u; row < height; row++) {
1052
470k
            auto scan_subpixel = subpixel_x;
1053
4.82M
            for (auto column = 0u; column < width; column++) {
1054
4.35M
                auto const* scan_line = source + (scan_subpixel >> 4);
1055
4.35M
                i32 accumulated_samples = 0;
1056
39.1M
                for (auto t = 0; t < 8; t++) {
1057
34.8M
                    auto sample = scan_line[t];
1058
34.8M
                    accumulated_samples += subpel_filters[filter][scan_subpixel & SUBPEL_MASK][t] * sample;
1059
34.8M
                }
1060
1061
4.35M
                *destination = clip_1(bit_depth, rounded_right_shift(accumulated_samples, 7));
1062
4.35M
                destination++;
1063
4.35M
                scan_subpixel += scale_x;
1064
4.35M
            }
1065
470k
            source += source_stride;
1066
470k
        }
1067
40.4k
    };
1068
1069
40.4k
    auto vertical_convolution_scaled = [](auto bit_depth, auto* destination, auto width, auto height, auto const* source, auto source_stride, auto filter, auto subpixel_y, auto scale_y) {
1070
289k
        for (auto row = 0u; row < height; row++) {
1071
248k
            auto const* source_column_base = source + (subpixel_y >> SUBPEL_BITS) * source_stride;
1072
1073
4.75M
            for (auto column = 0u; column < width; column++) {
1074
4.50M
                auto const* scan_column = source_column_base + column;
1075
4.50M
                i32 accumulated_samples = 0;
1076
40.5M
                for (auto t = 0; t < 8; t++) {
1077
36.0M
                    auto sample = *scan_column;
1078
36.0M
                    accumulated_samples += subpel_filters[filter][subpixel_y & SUBPEL_MASK][t] * sample;
1079
36.0M
                    scan_column += source_stride;
1080
36.0M
                }
1081
1082
4.50M
                *destination = clip_1(bit_depth, rounded_right_shift(accumulated_samples, 7));
1083
4.50M
                destination++;
1084
4.50M
            }
1085
248k
            subpixel_y += scale_y;
1086
248k
        }
1087
40.4k
    };
1088
1089
40.4k
    horizontal_convolution_scaled(bit_depth, intermediate_buffer.data(), width, intermediate_height, reference_start - (sample_offset * reference_frame_width), reference_frame_width, block_context.interpolation_filter, offset_scaled_block_x & SUBPEL_MASK, scaled_step_x);
1090
40.4k
    vertical_convolution_scaled(bit_depth, block_buffer.data(), width, height, intermediate_buffer.data(), width, block_context.interpolation_filter, reference_subpixel_y, scaled_step_y);
1091
1092
40.4k
    return {};
1093
184k
}
1094
1095
DecoderErrorOr<void> Decoder::predict_inter(u8 plane, BlockContext const& block_context, u32 x, u32 y, u32 width, u32 height, u32 block_index)
1096
136k
{
1097
    // The inter prediction process is invoked for inter coded blocks. When MiSize is smaller than BLOCK_8X8, the
1098
    // prediction is done with a granularity of 4x4 samples, otherwise the whole plane is predicted at the same time.
1099
    // The inputs to this process are:
1100
    // − a variable plane specifying which plane is being predicted,
1101
    // − variables x and y specifying the location of the top left sample in the CurrFrame[ plane ] array of the region
1102
    // to be predicted,
1103
    // − variables w and h specifying the width and height of the region to be predicted,
1104
    // − a variable blockIdx, specifying how much of the block has already been predicted in units of 4x4 samples.
1105
    // The outputs of this process are inter predicted samples in the current frame CurrFrame.
1106
1107
    // The prediction arrays are formed by the following ordered steps:
1108
    // 1. The variable refList is set equal to 0.
1109
    // 2. through 5.
1110
136k
    Array<u16, maximum_block_size> predicted_buffer;
1111
136k
    auto predicted_span = predicted_buffer.span().trim(width * height);
1112
136k
    TRY(predict_inter_block(plane, block_context, ReferenceIndex::Primary, block_context.row, block_context.column, x, y, width, height, block_index, predicted_span));
1113
14.1M
    auto predicted_buffer_at = [&](Span<u16> buffer, u32 row, u32 column) -> u16& {
1114
14.1M
        return buffer[row * width + column];
1115
14.1M
    };
1116
1117
    // 6. If isCompound is equal to 1, then the variable refList is set equal to 1 and steps 2, 3, 4 and 5 are repeated
1118
    // to form the prediction for the second reference.
1119
    // The inter predicted samples are then derived as follows:
1120
136k
    auto& frame_buffer = get_output_buffer(plane);
1121
136k
    VERIFY(!frame_buffer.is_empty());
1122
136k
    auto frame_size = block_context.frame_context.decoded_size(plane > 0);
1123
11.6M
    auto frame_buffer_at = [&](u32 row, u32 column) -> u16& {
1124
11.6M
        return frame_buffer[row * frame_size.width() + column];
1125
11.6M
    };
1126
1127
136k
    auto width_in_frame_buffer = min(width, frame_size.width() - x);
1128
136k
    auto height_in_frame_buffer = min(height, frame_size.height() - y);
1129
1130
    // The variable isCompound is set equal to ref_frame[ 1 ] > NONE.
1131
    // − If isCompound is equal to 0, CurrFrame[ plane ][ y + i ][ x + j ] is set equal to preds[ 0 ][ i ][ j ] for i = 0..h-1
1132
    // and j = 0..w-1.
1133
136k
    if (!block_context.is_compound()) {
1134
712k
        for (auto i = 0u; i < height_in_frame_buffer; i++) {
1135
9.75M
            for (auto j = 0u; j < width_in_frame_buffer; j++)
1136
9.13M
                frame_buffer_at(y + i, x + j) = predicted_buffer_at(predicted_span, i, j);
1137
623k
        }
1138
1139
88.5k
        return {};
1140
88.5k
    }
1141
1142
    // − Otherwise, CurrFrame[ plane ][ y + i ][ x + j ] is set equal to Round2( preds[ 0 ][ i ][ j ] + preds[ 1 ][ i ][ j ], 1 )
1143
    // for i = 0..h-1 and j = 0..w-1.
1144
48.0k
    Array<u16, maximum_block_size> second_predicted_buffer;
1145
48.0k
    auto second_predicted_span = second_predicted_buffer.span().trim(width * height);
1146
48.0k
    TRY(predict_inter_block(plane, block_context, ReferenceIndex::Secondary, block_context.row, block_context.column, x, y, width, height, block_index, second_predicted_span));
1147
1148
323k
    for (auto i = 0u; i < height_in_frame_buffer; i++) {
1149
2.78M
        for (auto j = 0u; j < width_in_frame_buffer; j++)
1150
2.51M
            frame_buffer_at(y + i, x + j) = rounded_right_shift(predicted_buffer_at(predicted_span, i, j) + predicted_buffer_at(second_predicted_span, i, j), 1);
1151
275k
    }
1152
1153
48.0k
    return {};
1154
48.0k
}
1155
1156
inline u16 dc_q(u8 bit_depth, u8 b)
1157
33.6k
{
1158
    // The function dc_q( b ) is specified as dc_qlookup[ (BitDepth-8) >> 1 ][ Clip3( 0, 255, b ) ] where dc_lookup is
1159
    // defined as follows:
1160
33.6k
    constexpr u16 dc_qlookup[3][256] = {
1161
33.6k
        { 4, 8, 8, 9, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 28, 29, 30, 31, 32, 32, 33, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42, 43, 43, 44, 45, 46, 47, 48, 48, 49, 50, 51, 52, 53, 53, 54, 55, 56, 57, 57, 58, 59, 60, 61, 62, 62, 63, 64, 65, 66, 66, 67, 68, 69, 70, 70, 71, 72, 73, 74, 74, 75, 76, 77, 78, 78, 79, 80, 81, 81, 82, 83, 84, 85, 85, 87, 88, 90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 108, 110, 111, 113, 114, 116, 117, 118, 120, 121, 123, 125, 127, 129, 131, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 161, 164, 166, 169, 172, 174, 177, 180, 182, 185, 187, 190, 192, 195, 199, 202, 205, 208, 211, 214, 217, 220, 223, 226, 230, 233, 237, 240, 243, 247, 250, 253, 257, 261, 265, 269, 272, 276, 280, 284, 288, 292, 296, 300, 304, 309, 313, 317, 322, 326, 330, 335, 340, 344, 349, 354, 359, 364, 369, 374, 379, 384, 389, 395, 400, 406, 411, 417, 423, 429, 435, 441, 447, 454, 461, 467, 475, 482, 489, 497, 505, 513, 522, 530, 539, 549, 559, 569, 579, 590, 602, 614, 626, 640, 654, 668, 684, 700, 717, 736, 755, 775, 796, 819, 843, 869, 896, 925, 955, 988, 1022, 1058, 1098, 1139, 1184, 1232, 1282, 1336 },
1162
33.6k
        { 4, 9, 10, 13, 15, 17, 20, 22, 25, 28, 31, 34, 37, 40, 43, 47, 50, 53, 57, 60, 64, 68, 71, 75, 78, 82, 86, 90, 93, 97, 101, 105, 109, 113, 116, 120, 124, 128, 132, 136, 140, 143, 147, 151, 155, 159, 163, 166, 170, 174, 178, 182, 185, 189, 193, 197, 200, 204, 208, 212, 215, 219, 223, 226, 230, 233, 237, 241, 244, 248, 251, 255, 259, 262, 266, 269, 273, 276, 280, 283, 287, 290, 293, 297, 300, 304, 307, 310, 314, 317, 321, 324, 327, 331, 334, 337, 343, 350, 356, 362, 369, 375, 381, 387, 394, 400, 406, 412, 418, 424, 430, 436, 442, 448, 454, 460, 466, 472, 478, 484, 490, 499, 507, 516, 525, 533, 542, 550, 559, 567, 576, 584, 592, 601, 609, 617, 625, 634, 644, 655, 666, 676, 687, 698, 708, 718, 729, 739, 749, 759, 770, 782, 795, 807, 819, 831, 844, 856, 868, 880, 891, 906, 920, 933, 947, 961, 975, 988, 1001, 1015, 1030, 1045, 1061, 1076, 1090, 1105, 1120, 1137, 1153, 1170, 1186, 1202, 1218, 1236, 1253, 1271, 1288, 1306, 1323, 1342, 1361, 1379, 1398, 1416, 1436, 1456, 1476, 1496, 1516, 1537, 1559, 1580, 1601, 1624, 1647, 1670, 1692, 1717, 1741, 1766, 1791, 1817, 1844, 1871, 1900, 1929, 1958, 1990, 2021, 2054, 2088, 2123, 2159, 2197, 2236, 2276, 2319, 2363, 2410, 2458, 2508, 2561, 2616, 2675, 2737, 2802, 2871, 2944, 3020, 3102, 3188, 3280, 3375, 3478, 3586, 3702, 3823, 3953, 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347 },
1163
33.6k
        { 4, 12, 18, 25, 33, 41, 50, 60, 70, 80, 91, 103, 115, 127, 140, 153, 166, 180, 194, 208, 222, 237, 251, 266, 281, 296, 312, 327, 343, 358, 374, 390, 405, 421, 437, 453, 469, 484, 500, 516, 532, 548, 564, 580, 596, 611, 627, 643, 659, 674, 690, 706, 721, 737, 752, 768, 783, 798, 814, 829, 844, 859, 874, 889, 904, 919, 934, 949, 964, 978, 993, 1008, 1022, 1037, 1051, 1065, 1080, 1094, 1108, 1122, 1136, 1151, 1165, 1179, 1192, 1206, 1220, 1234, 1248, 1261, 1275, 1288, 1302, 1315, 1329, 1342, 1368, 1393, 1419, 1444, 1469, 1494, 1519, 1544, 1569, 1594, 1618, 1643, 1668, 1692, 1717, 1741, 1765, 1789, 1814, 1838, 1862, 1885, 1909, 1933, 1957, 1992, 2027, 2061, 2096, 2130, 2165, 2199, 2233, 2267, 2300, 2334, 2367, 2400, 2434, 2467, 2499, 2532, 2575, 2618, 2661, 2704, 2746, 2788, 2830, 2872, 2913, 2954, 2995, 3036, 3076, 3127, 3177, 3226, 3275, 3324, 3373, 3421, 3469, 3517, 3565, 3621, 3677, 3733, 3788, 3843, 3897, 3951, 4005, 4058, 4119, 4181, 4241, 4301, 4361, 4420, 4479, 4546, 4612, 4677, 4742, 4807, 4871, 4942, 5013, 5083, 5153, 5222, 5291, 5367, 5442, 5517, 5591, 5665, 5745, 5825, 5905, 5984, 6063, 6149, 6234, 6319, 6404, 6495, 6587, 6678, 6769, 6867, 6966, 7064, 7163, 7269, 7376, 7483, 7599, 7715, 7832, 7958, 8085, 8214, 8352, 8492, 8635, 8788, 8945, 9104, 9275, 9450, 9639, 9832, 10031, 10245, 10465, 10702, 10946, 11210, 11482, 11776, 12081, 12409, 12750, 13118, 13501, 13913, 14343, 14807, 15290, 15812, 16356, 16943, 17575, 18237, 18949, 19718, 20521, 21387 }
1164
33.6k
    };
1165
1166
33.6k
    return dc_qlookup[(bit_depth - 8) >> 1][clip_3<u8>(0, 255, b)];
1167
33.6k
}
1168
1169
inline u16 ac_q(u8 bit_depth, u8 b)
1170
33.6k
{
1171
    // The function ac_q( b ) is specified as ac_qlookup[ (BitDepth-8) >> 1 ][ Clip3( 0, 255, b ) ] where ac_lookup is
1172
    // defined as follows:
1173
33.6k
    constexpr u16 ac_qlookup[3][256] = {
1174
33.6k
        { 4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 155, 158, 161, 164, 167, 170, 173, 176, 179, 182, 185, 188, 191, 194, 197, 200, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255, 260, 265, 270, 275, 280, 285, 290, 295, 300, 305, 311, 317, 323, 329, 335, 341, 347, 353, 359, 366, 373, 380, 387, 394, 401, 408, 416, 424, 432, 440, 448, 456, 465, 474, 483, 492, 501, 510, 520, 530, 540, 550, 560, 571, 582, 593, 604, 615, 627, 639, 651, 663, 676, 689, 702, 715, 729, 743, 757, 771, 786, 801, 816, 832, 848, 864, 881, 898, 915, 933, 951, 969, 988, 1007, 1026, 1046, 1066, 1087, 1108, 1129, 1151, 1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343, 1369, 1396, 1423, 1451, 1479, 1508, 1537, 1567, 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828 },
1175
33.6k
        { 4, 9, 11, 13, 16, 18, 21, 24, 27, 30, 33, 37, 40, 44, 48, 51, 55, 59, 63, 67, 71, 75, 79, 83, 88, 92, 96, 100, 105, 109, 114, 118, 122, 127, 131, 136, 140, 145, 149, 154, 158, 163, 168, 172, 177, 181, 186, 190, 195, 199, 204, 208, 213, 217, 222, 226, 231, 235, 240, 244, 249, 253, 258, 262, 267, 271, 275, 280, 284, 289, 293, 297, 302, 306, 311, 315, 319, 324, 328, 332, 337, 341, 345, 349, 354, 358, 362, 367, 371, 375, 379, 384, 388, 392, 396, 401, 409, 417, 425, 433, 441, 449, 458, 466, 474, 482, 490, 498, 506, 514, 523, 531, 539, 547, 555, 563, 571, 579, 588, 596, 604, 616, 628, 640, 652, 664, 676, 688, 700, 713, 725, 737, 749, 761, 773, 785, 797, 809, 825, 841, 857, 873, 889, 905, 922, 938, 954, 970, 986, 1002, 1018, 1038, 1058, 1078, 1098, 1118, 1138, 1158, 1178, 1198, 1218, 1242, 1266, 1290, 1314, 1338, 1362, 1386, 1411, 1435, 1463, 1491, 1519, 1547, 1575, 1603, 1631, 1663, 1695, 1727, 1759, 1791, 1823, 1859, 1895, 1931, 1967, 2003, 2039, 2079, 2119, 2159, 2199, 2239, 2283, 2327, 2371, 2415, 2459, 2507, 2555, 2603, 2651, 2703, 2755, 2807, 2859, 2915, 2971, 3027, 3083, 3143, 3203, 3263, 3327, 3391, 3455, 3523, 3591, 3659, 3731, 3803, 3876, 3952, 4028, 4104, 4184, 4264, 4348, 4432, 4516, 4604, 4692, 4784, 4876, 4972, 5068, 5168, 5268, 5372, 5476, 5584, 5692, 5804, 5916, 6032, 6148, 6268, 6388, 6512, 6640, 6768, 6900, 7036, 7172, 7312 },
1176
33.6k
        { 4, 13, 19, 27, 35, 44, 54, 64, 75, 87, 99, 112, 126, 139, 154, 168, 183, 199, 214, 230, 247, 263, 280, 297, 314, 331, 349, 366, 384, 402, 420, 438, 456, 475, 493, 511, 530, 548, 567, 586, 604, 623, 642, 660, 679, 698, 716, 735, 753, 772, 791, 809, 828, 846, 865, 884, 902, 920, 939, 957, 976, 994, 1012, 1030, 1049, 1067, 1085, 1103, 1121, 1139, 1157, 1175, 1193, 1211, 1229, 1246, 1264, 1282, 1299, 1317, 1335, 1352, 1370, 1387, 1405, 1422, 1440, 1457, 1474, 1491, 1509, 1526, 1543, 1560, 1577, 1595, 1627, 1660, 1693, 1725, 1758, 1791, 1824, 1856, 1889, 1922, 1954, 1987, 2020, 2052, 2085, 2118, 2150, 2183, 2216, 2248, 2281, 2313, 2346, 2378, 2411, 2459, 2508, 2556, 2605, 2653, 2701, 2750, 2798, 2847, 2895, 2943, 2992, 3040, 3088, 3137, 3185, 3234, 3298, 3362, 3426, 3491, 3555, 3619, 3684, 3748, 3812, 3876, 3941, 4005, 4069, 4149, 4230, 4310, 4390, 4470, 4550, 4631, 4711, 4791, 4871, 4967, 5064, 5160, 5256, 5352, 5448, 5544, 5641, 5737, 5849, 5961, 6073, 6185, 6297, 6410, 6522, 6650, 6778, 6906, 7034, 7162, 7290, 7435, 7579, 7723, 7867, 8011, 8155, 8315, 8475, 8635, 8795, 8956, 9132, 9308, 9484, 9660, 9836, 10028, 10220, 10412, 10604, 10812, 11020, 11228, 11437, 11661, 11885, 12109, 12333, 12573, 12813, 13053, 13309, 13565, 13821, 14093, 14365, 14637, 14925, 15213, 15502, 15806, 16110, 16414, 16734, 17054, 17390, 17726, 18062, 18414, 18766, 19134, 19502, 19886, 20270, 20670, 21070, 21486, 21902, 22334, 22766, 23214, 23662, 24126, 24590, 25070, 25551, 26047, 26559, 27071, 27599, 28143, 28687, 29247 }
1177
33.6k
    };
1178
1179
33.6k
    return ac_qlookup[(bit_depth - 8) >> 1][clip_3<u8>(0, 255, b)];
1180
33.6k
}
1181
1182
u8 Decoder::get_base_quantizer_index(SegmentFeatureStatus alternative_quantizer_feature, bool should_use_absolute_segment_base_quantizer, u8 base_quantizer_index)
1183
16.8k
{
1184
    // The function get_qindex( ) returns the quantizer index for the current block and is specified by the following:
1185
    // − If seg_feature_active( SEG_LVL_ALT_Q ) is equal to 1 the following ordered steps apply:
1186
16.8k
    if (alternative_quantizer_feature.enabled) {
1187
        // 1. Set the variable data equal to FeatureData[ segment_id ][ SEG_LVL_ALT_Q ].
1188
1.90k
        auto data = alternative_quantizer_feature.value;
1189
1190
        // 2. If segmentation_abs_or_delta_update is equal to 0, set data equal to base_q_idx + data
1191
1.90k
        if (!should_use_absolute_segment_base_quantizer) {
1192
27
            data += base_quantizer_index;
1193
27
        }
1194
1195
        // 3. Return Clip3( 0, 255, data ).
1196
1.90k
        return clip_3<u8>(0, 255, data);
1197
1.90k
    }
1198
1199
    // − Otherwise, return base_q_idx.
1200
14.9k
    return base_quantizer_index;
1201
16.8k
}
1202
1203
u16 Decoder::get_dc_quantizer(u8 bit_depth, u8 base, i8 delta)
1204
33.6k
{
1205
    // NOTE: Delta is selected by the caller based on whether it is for the Y or UV planes.
1206
1207
    // The function get_dc_quant( plane ) returns the quantizer value for the dc coefficient for a particular plane and
1208
    // is derived as follows:
1209
    // − If plane is equal to 0, return dc_q( get_qindex( ) + delta_q_y_dc ).
1210
    // − Otherwise, return dc_q( get_qindex( ) + delta_q_uv_dc ).
1211
33.6k
    return dc_q(bit_depth, static_cast<u8>(base + delta));
1212
33.6k
}
1213
1214
u16 Decoder::get_ac_quantizer(u8 bit_depth, u8 base, i8 delta)
1215
33.6k
{
1216
    // NOTE: Delta is selected by the caller based on whether it is for the Y or UV planes.
1217
1218
    // The function get_ac_quant( plane ) returns the quantizer value for the ac coefficient for a particular plane and
1219
    // is derived as follows:
1220
    // − If plane is equal to 0, return ac_q( get_qindex( ) ).
1221
    // − Otherwise, return ac_q( get_qindex( ) + delta_q_uv_ac ).
1222
33.6k
    return ac_q(bit_depth, static_cast<u8>(base + delta));
1223
33.6k
}
1224
1225
DecoderErrorOr<void> Decoder::reconstruct(u8 plane, BlockContext const& block_context, u32 transform_block_x, u32 transform_block_y, TransformSize transform_block_size, TransformSet transform_set)
1226
8.55M
{
1227
    // 8.6.2 Reconstruct process
1228
1229
    // The variable n (specifying the base 2 logarithm of the width of the transform block) is set equal to 2 + txSz.
1230
8.55M
    u8 log2_of_block_size = 2u + transform_block_size;
1231
8.55M
    switch (log2_of_block_size) {
1232
6.98M
    case 2:
1233
6.98M
        return reconstruct_templated<2>(plane, block_context, transform_block_x, transform_block_y, transform_set);
1234
1.01M
    case 3:
1235
1.01M
        return reconstruct_templated<3>(plane, block_context, transform_block_x, transform_block_y, transform_set);
1236
170k
    case 4:
1237
170k
        return reconstruct_templated<4>(plane, block_context, transform_block_x, transform_block_y, transform_set);
1238
382k
    case 5:
1239
382k
        return reconstruct_templated<5>(plane, block_context, transform_block_x, transform_block_y, transform_set);
1240
0
    default:
1241
0
        VERIFY_NOT_REACHED();
1242
8.55M
    }
1243
8.55M
}
1244
1245
template<u8 log2_of_block_size>
1246
DecoderErrorOr<void> Decoder::reconstruct_templated(u8 plane, BlockContext const& block_context, u32 transform_block_x, u32 transform_block_y, TransformSet transform_set)
1247
8.56M
{
1248
    // 8.6.2 Reconstruct process, continued:
1249
1250
    // The variable dqDenom is set equal to 2 if txSz is equal to Transform_32X32, otherwise dqDenom is set equal to 1.
1251
8.56M
    constexpr Intermediate dq_denominator = log2_of_block_size == 5 ? 2 : 1;
1252
    // The variable n0 (specifying the width of the transform block) is set equal to 1 << n.
1253
8.56M
    constexpr auto block_size = 1u << log2_of_block_size;
1254
1255
    // 1. Dequant[ i ][ j ] is set equal to ( Tokens[ i * n0 + j ] * get_ac_quant( plane ) ) / dqDenom
1256
    //    for i = 0..(n0-1), for j = 0..(n0-1)
1257
8.56M
    Array<Intermediate, block_size * block_size> dequantized;
1258
8.56M
    auto quantizers = block_context.frame_context.segment_quantizers[block_context.segment_id];
1259
8.56M
    Intermediate ac_quant = plane == 0 ? quantizers.y_ac_quantizer : quantizers.uv_ac_quantizer;
1260
8.56M
    auto const* tokens_raw = block_context.residual_tokens.data();
1261
620M
    for (u32 i = 0; i < dequantized.size(); i++) {
1262
611M
        dequantized[i] = (tokens_raw[i] * ac_quant) / dq_denominator;
1263
611M
    }
1264
1265
    // 2. Dequant[ 0 ][ 0 ] is set equal to ( Tokens[ 0 ] * get_dc_quant( plane ) ) / dqDenom
1266
8.56M
    dequantized[0] = (block_context.residual_tokens[0] * (plane == 0 ? quantizers.y_dc_quantizer : quantizers.uv_dc_quantizer)) / dq_denominator;
1267
1268
    // It is a requirement of bitstream conformance that the values written into the Dequant array in steps 1 and 2
1269
    // are representable by a signed integer with 8 + BitDepth bits.
1270
    // Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal
1271
    // to allow these bounds to be violated. Therefore, we can avoid the performance cost here.
1272
1273
    // 3. Invoke the 2D inverse transform block process defined in section 8.7.2 with the variable n as input.
1274
    //    The inverse transform outputs are stored back to the Dequant buffer.
1275
8.56M
    TRY(inverse_transform_2d<log2_of_block_size>(block_context, dequantized, transform_set));
1276
1277
    // 4. CurrFrame[ plane ][ y + i ][ x + j ] is set equal to Clip1( CurrFrame[ plane ][ y + i ][ x + j ] + Dequant[ i ][ j ] )
1278
    //    for i = 0..(n0-1) and j = 0..(n0-1).
1279
8.56M
    auto& current_buffer = get_output_buffer(plane);
1280
8.56M
    auto frame_size = block_context.frame_context.decoded_size(plane > 0);
1281
8.56M
    auto width_in_frame_buffer = min(block_size, frame_size.width() - transform_block_x);
1282
8.56M
    auto height_in_frame_buffer = min(block_size, frame_size.height() - transform_block_y);
1283
1284
59.4M
    for (auto i = 0u; i < height_in_frame_buffer; i++) {
1285
635M
        for (auto j = 0u; j < width_in_frame_buffer; j++) {
1286
584M
            auto index = (transform_block_y + i) * frame_size.width() + transform_block_x + j;
1287
584M
            auto dequantized_value = dequantized[i * block_size + j];
1288
584M
            current_buffer[index] = clip_1(block_context.frame_context.color_config.bit_depth, current_buffer[index] + dequantized_value);
1289
584M
        }
1290
50.8M
    }
1291
1292
8.56M
    return {};
1293
8.56M
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::reconstruct_templated<(unsigned char)2>(unsigned char, Media::Video::VP9::BlockContext const&, unsigned int, unsigned int, Media::Video::VP9::TransformSet)
Line
Count
Source
1247
6.98M
{
1248
    // 8.6.2 Reconstruct process, continued:
1249
1250
    // The variable dqDenom is set equal to 2 if txSz is equal to Transform_32X32, otherwise dqDenom is set equal to 1.
1251
6.98M
    constexpr Intermediate dq_denominator = log2_of_block_size == 5 ? 2 : 1;
1252
    // The variable n0 (specifying the width of the transform block) is set equal to 1 << n.
1253
6.98M
    constexpr auto block_size = 1u << log2_of_block_size;
1254
1255
    // 1. Dequant[ i ][ j ] is set equal to ( Tokens[ i * n0 + j ] * get_ac_quant( plane ) ) / dqDenom
1256
    //    for i = 0..(n0-1), for j = 0..(n0-1)
1257
6.98M
    Array<Intermediate, block_size * block_size> dequantized;
1258
6.98M
    auto quantizers = block_context.frame_context.segment_quantizers[block_context.segment_id];
1259
6.98M
    Intermediate ac_quant = plane == 0 ? quantizers.y_ac_quantizer : quantizers.uv_ac_quantizer;
1260
6.98M
    auto const* tokens_raw = block_context.residual_tokens.data();
1261
118M
    for (u32 i = 0; i < dequantized.size(); i++) {
1262
111M
        dequantized[i] = (tokens_raw[i] * ac_quant) / dq_denominator;
1263
111M
    }
1264
1265
    // 2. Dequant[ 0 ][ 0 ] is set equal to ( Tokens[ 0 ] * get_dc_quant( plane ) ) / dqDenom
1266
6.98M
    dequantized[0] = (block_context.residual_tokens[0] * (plane == 0 ? quantizers.y_dc_quantizer : quantizers.uv_dc_quantizer)) / dq_denominator;
1267
1268
    // It is a requirement of bitstream conformance that the values written into the Dequant array in steps 1 and 2
1269
    // are representable by a signed integer with 8 + BitDepth bits.
1270
    // Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal
1271
    // to allow these bounds to be violated. Therefore, we can avoid the performance cost here.
1272
1273
    // 3. Invoke the 2D inverse transform block process defined in section 8.7.2 with the variable n as input.
1274
    //    The inverse transform outputs are stored back to the Dequant buffer.
1275
6.98M
    TRY(inverse_transform_2d<log2_of_block_size>(block_context, dequantized, transform_set));
1276
1277
    // 4. CurrFrame[ plane ][ y + i ][ x + j ] is set equal to Clip1( CurrFrame[ plane ][ y + i ][ x + j ] + Dequant[ i ][ j ] )
1278
    //    for i = 0..(n0-1) and j = 0..(n0-1).
1279
6.98M
    auto& current_buffer = get_output_buffer(plane);
1280
6.98M
    auto frame_size = block_context.frame_context.decoded_size(plane > 0);
1281
6.98M
    auto width_in_frame_buffer = min(block_size, frame_size.width() - transform_block_x);
1282
6.98M
    auto height_in_frame_buffer = min(block_size, frame_size.height() - transform_block_y);
1283
1284
34.8M
    for (auto i = 0u; i < height_in_frame_buffer; i++) {
1285
139M
        for (auto j = 0u; j < width_in_frame_buffer; j++) {
1286
111M
            auto index = (transform_block_y + i) * frame_size.width() + transform_block_x + j;
1287
111M
            auto dequantized_value = dequantized[i * block_size + j];
1288
111M
            current_buffer[index] = clip_1(block_context.frame_context.color_config.bit_depth, current_buffer[index] + dequantized_value);
1289
111M
        }
1290
27.8M
    }
1291
1292
6.98M
    return {};
1293
6.98M
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::reconstruct_templated<(unsigned char)3>(unsigned char, Media::Video::VP9::BlockContext const&, unsigned int, unsigned int, Media::Video::VP9::TransformSet)
Line
Count
Source
1247
1.01M
{
1248
    // 8.6.2 Reconstruct process, continued:
1249
1250
    // The variable dqDenom is set equal to 2 if txSz is equal to Transform_32X32, otherwise dqDenom is set equal to 1.
1251
1.01M
    constexpr Intermediate dq_denominator = log2_of_block_size == 5 ? 2 : 1;
1252
    // The variable n0 (specifying the width of the transform block) is set equal to 1 << n.
1253
1.01M
    constexpr auto block_size = 1u << log2_of_block_size;
1254
1255
    // 1. Dequant[ i ][ j ] is set equal to ( Tokens[ i * n0 + j ] * get_ac_quant( plane ) ) / dqDenom
1256
    //    for i = 0..(n0-1), for j = 0..(n0-1)
1257
1.01M
    Array<Intermediate, block_size * block_size> dequantized;
1258
1.01M
    auto quantizers = block_context.frame_context.segment_quantizers[block_context.segment_id];
1259
1.01M
    Intermediate ac_quant = plane == 0 ? quantizers.y_ac_quantizer : quantizers.uv_ac_quantizer;
1260
1.01M
    auto const* tokens_raw = block_context.residual_tokens.data();
1261
66.1M
    for (u32 i = 0; i < dequantized.size(); i++) {
1262
65.1M
        dequantized[i] = (tokens_raw[i] * ac_quant) / dq_denominator;
1263
65.1M
    }
1264
1265
    // 2. Dequant[ 0 ][ 0 ] is set equal to ( Tokens[ 0 ] * get_dc_quant( plane ) ) / dqDenom
1266
1.01M
    dequantized[0] = (block_context.residual_tokens[0] * (plane == 0 ? quantizers.y_dc_quantizer : quantizers.uv_dc_quantizer)) / dq_denominator;
1267
1268
    // It is a requirement of bitstream conformance that the values written into the Dequant array in steps 1 and 2
1269
    // are representable by a signed integer with 8 + BitDepth bits.
1270
    // Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal
1271
    // to allow these bounds to be violated. Therefore, we can avoid the performance cost here.
1272
1273
    // 3. Invoke the 2D inverse transform block process defined in section 8.7.2 with the variable n as input.
1274
    //    The inverse transform outputs are stored back to the Dequant buffer.
1275
1.01M
    TRY(inverse_transform_2d<log2_of_block_size>(block_context, dequantized, transform_set));
1276
1277
    // 4. CurrFrame[ plane ][ y + i ][ x + j ] is set equal to Clip1( CurrFrame[ plane ][ y + i ][ x + j ] + Dequant[ i ][ j ] )
1278
    //    for i = 0..(n0-1) and j = 0..(n0-1).
1279
1.01M
    auto& current_buffer = get_output_buffer(plane);
1280
1.01M
    auto frame_size = block_context.frame_context.decoded_size(plane > 0);
1281
1.01M
    auto width_in_frame_buffer = min(block_size, frame_size.width() - transform_block_x);
1282
1.01M
    auto height_in_frame_buffer = min(block_size, frame_size.height() - transform_block_y);
1283
1284
9.15M
    for (auto i = 0u; i < height_in_frame_buffer; i++) {
1285
70.8M
        for (auto j = 0u; j < width_in_frame_buffer; j++) {
1286
62.7M
            auto index = (transform_block_y + i) * frame_size.width() + transform_block_x + j;
1287
62.7M
            auto dequantized_value = dequantized[i * block_size + j];
1288
62.7M
            current_buffer[index] = clip_1(block_context.frame_context.color_config.bit_depth, current_buffer[index] + dequantized_value);
1289
62.7M
        }
1290
8.13M
    }
1291
1292
1.01M
    return {};
1293
1.01M
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::reconstruct_templated<(unsigned char)4>(unsigned char, Media::Video::VP9::BlockContext const&, unsigned int, unsigned int, Media::Video::VP9::TransformSet)
Line
Count
Source
1247
170k
{
1248
    // 8.6.2 Reconstruct process, continued:
1249
1250
    // The variable dqDenom is set equal to 2 if txSz is equal to Transform_32X32, otherwise dqDenom is set equal to 1.
1251
170k
    constexpr Intermediate dq_denominator = log2_of_block_size == 5 ? 2 : 1;
1252
    // The variable n0 (specifying the width of the transform block) is set equal to 1 << n.
1253
170k
    constexpr auto block_size = 1u << log2_of_block_size;
1254
1255
    // 1. Dequant[ i ][ j ] is set equal to ( Tokens[ i * n0 + j ] * get_ac_quant( plane ) ) / dqDenom
1256
    //    for i = 0..(n0-1), for j = 0..(n0-1)
1257
170k
    Array<Intermediate, block_size * block_size> dequantized;
1258
170k
    auto quantizers = block_context.frame_context.segment_quantizers[block_context.segment_id];
1259
170k
    Intermediate ac_quant = plane == 0 ? quantizers.y_ac_quantizer : quantizers.uv_ac_quantizer;
1260
170k
    auto const* tokens_raw = block_context.residual_tokens.data();
1261
43.7M
    for (u32 i = 0; i < dequantized.size(); i++) {
1262
43.6M
        dequantized[i] = (tokens_raw[i] * ac_quant) / dq_denominator;
1263
43.6M
    }
1264
1265
    // 2. Dequant[ 0 ][ 0 ] is set equal to ( Tokens[ 0 ] * get_dc_quant( plane ) ) / dqDenom
1266
170k
    dequantized[0] = (block_context.residual_tokens[0] * (plane == 0 ? quantizers.y_dc_quantizer : quantizers.uv_dc_quantizer)) / dq_denominator;
1267
1268
    // It is a requirement of bitstream conformance that the values written into the Dequant array in steps 1 and 2
1269
    // are representable by a signed integer with 8 + BitDepth bits.
1270
    // Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal
1271
    // to allow these bounds to be violated. Therefore, we can avoid the performance cost here.
1272
1273
    // 3. Invoke the 2D inverse transform block process defined in section 8.7.2 with the variable n as input.
1274
    //    The inverse transform outputs are stored back to the Dequant buffer.
1275
170k
    TRY(inverse_transform_2d<log2_of_block_size>(block_context, dequantized, transform_set));
1276
1277
    // 4. CurrFrame[ plane ][ y + i ][ x + j ] is set equal to Clip1( CurrFrame[ plane ][ y + i ][ x + j ] + Dequant[ i ][ j ] )
1278
    //    for i = 0..(n0-1) and j = 0..(n0-1).
1279
170k
    auto& current_buffer = get_output_buffer(plane);
1280
170k
    auto frame_size = block_context.frame_context.decoded_size(plane > 0);
1281
170k
    auto width_in_frame_buffer = min(block_size, frame_size.width() - transform_block_x);
1282
170k
    auto height_in_frame_buffer = min(block_size, frame_size.height() - transform_block_y);
1283
1284
2.89M
    for (auto i = 0u; i < height_in_frame_buffer; i++) {
1285
37.8M
        for (auto j = 0u; j < width_in_frame_buffer; j++) {
1286
35.1M
            auto index = (transform_block_y + i) * frame_size.width() + transform_block_x + j;
1287
35.1M
            auto dequantized_value = dequantized[i * block_size + j];
1288
35.1M
            current_buffer[index] = clip_1(block_context.frame_context.color_config.bit_depth, current_buffer[index] + dequantized_value);
1289
35.1M
        }
1290
2.72M
    }
1291
1292
170k
    return {};
1293
170k
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::reconstruct_templated<(unsigned char)5>(unsigned char, Media::Video::VP9::BlockContext const&, unsigned int, unsigned int, Media::Video::VP9::TransformSet)
Line
Count
Source
1247
382k
{
1248
    // 8.6.2 Reconstruct process, continued:
1249
1250
    // The variable dqDenom is set equal to 2 if txSz is equal to Transform_32X32, otherwise dqDenom is set equal to 1.
1251
382k
    constexpr Intermediate dq_denominator = log2_of_block_size == 5 ? 2 : 1;
1252
    // The variable n0 (specifying the width of the transform block) is set equal to 1 << n.
1253
382k
    constexpr auto block_size = 1u << log2_of_block_size;
1254
1255
    // 1. Dequant[ i ][ j ] is set equal to ( Tokens[ i * n0 + j ] * get_ac_quant( plane ) ) / dqDenom
1256
    //    for i = 0..(n0-1), for j = 0..(n0-1)
1257
382k
    Array<Intermediate, block_size * block_size> dequantized;
1258
382k
    auto quantizers = block_context.frame_context.segment_quantizers[block_context.segment_id];
1259
382k
    Intermediate ac_quant = plane == 0 ? quantizers.y_ac_quantizer : quantizers.uv_ac_quantizer;
1260
382k
    auto const* tokens_raw = block_context.residual_tokens.data();
1261
391M
    for (u32 i = 0; i < dequantized.size(); i++) {
1262
391M
        dequantized[i] = (tokens_raw[i] * ac_quant) / dq_denominator;
1263
391M
    }
1264
1265
    // 2. Dequant[ 0 ][ 0 ] is set equal to ( Tokens[ 0 ] * get_dc_quant( plane ) ) / dqDenom
1266
382k
    dequantized[0] = (block_context.residual_tokens[0] * (plane == 0 ? quantizers.y_dc_quantizer : quantizers.uv_dc_quantizer)) / dq_denominator;
1267
1268
    // It is a requirement of bitstream conformance that the values written into the Dequant array in steps 1 and 2
1269
    // are representable by a signed integer with 8 + BitDepth bits.
1270
    // Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal
1271
    // to allow these bounds to be violated. Therefore, we can avoid the performance cost here.
1272
1273
    // 3. Invoke the 2D inverse transform block process defined in section 8.7.2 with the variable n as input.
1274
    //    The inverse transform outputs are stored back to the Dequant buffer.
1275
382k
    TRY(inverse_transform_2d<log2_of_block_size>(block_context, dequantized, transform_set));
1276
1277
    // 4. CurrFrame[ plane ][ y + i ][ x + j ] is set equal to Clip1( CurrFrame[ plane ][ y + i ][ x + j ] + Dequant[ i ][ j ] )
1278
    //    for i = 0..(n0-1) and j = 0..(n0-1).
1279
382k
    auto& current_buffer = get_output_buffer(plane);
1280
382k
    auto frame_size = block_context.frame_context.decoded_size(plane > 0);
1281
382k
    auto width_in_frame_buffer = min(block_size, frame_size.width() - transform_block_x);
1282
382k
    auto height_in_frame_buffer = min(block_size, frame_size.height() - transform_block_y);
1283
1284
12.5M
    for (auto i = 0u; i < height_in_frame_buffer; i++) {
1285
387M
        for (auto j = 0u; j < width_in_frame_buffer; j++) {
1286
375M
            auto index = (transform_block_y + i) * frame_size.width() + transform_block_x + j;
1287
375M
            auto dequantized_value = dequantized[i * block_size + j];
1288
375M
            current_buffer[index] = clip_1(block_context.frame_context.color_config.bit_depth, current_buffer[index] + dequantized_value);
1289
375M
        }
1290
12.1M
    }
1291
1292
382k
    return {};
1293
382k
}
1294
1295
inline DecoderErrorOr<void> Decoder::inverse_walsh_hadamard_transform(Span<Intermediate> data, u8 log2_of_block_size, u8 shift)
1296
7.24M
{
1297
    // The input to this process is a variable shift that specifies the amount of pre-scaling.
1298
    // This process does an in-place transform of the array T (of length 4) by the following ordered steps:
1299
7.24M
    if (1 << log2_of_block_size != 4)
1300
0
        return DecoderError::corrupted("Block size was not 4"sv);
1301
1302
7.24M
    auto a = data[0] >> shift;
1303
7.24M
    auto c = data[1] >> shift;
1304
7.24M
    auto d = data[2] >> shift;
1305
7.24M
    auto b = data[3] >> shift;
1306
7.24M
    a += c;
1307
7.24M
    d -= b;
1308
7.24M
    auto average_of_a_and_d = (a - d) >> 1;
1309
7.24M
    b = average_of_a_and_d - b;
1310
7.24M
    c = average_of_a_and_d - c;
1311
7.24M
    a -= b;
1312
7.24M
    d += c;
1313
7.24M
    data[0] = a;
1314
7.24M
    data[1] = b;
1315
7.24M
    data[2] = c;
1316
7.24M
    data[3] = d;
1317
7.24M
    return {};
1318
7.24M
}
1319
1320
inline i32 Decoder::cos64(u8 angle)
1321
2.02G
{
1322
2.02G
    i32 const cos64_lookup[33] = { 16384, 16364, 16305, 16207, 16069, 15893, 15679, 15426, 15137, 14811, 14449, 14053, 13623, 13160, 12665, 12140, 11585, 11003, 10394, 9760, 9102, 8423, 7723, 7005, 6270, 5520, 4756, 3981, 3196, 2404, 1606, 804, 0 };
1323
1324
    // 1. Set a variable angle2 equal to angle & 127.
1325
2.02G
    angle &= 127;
1326
    // 2. If angle2 is greater than or equal to 0 and less than or equal to 32, return cos64_lookup[ angle2 ].
1327
2.02G
    if (angle <= 32)
1328
900M
        return cos64_lookup[angle];
1329
    // 3. If angle2 is greater than 32 and less than or equal to 64, return cos64_lookup[ 64 - angle2 ] * -1.
1330
1.12G
    if (angle <= 64)
1331
127M
        return -cos64_lookup[64 - angle];
1332
    // 4. If angle2 is greater than 64 and less than or equal to 96, return cos64_lookup[ angle2 - 64 ] * -1.
1333
1.00G
    if (angle <= 96)
1334
128M
        return -cos64_lookup[angle - 64];
1335
    // 5. Otherwise (if angle2 is greater than 96 and less than 128), return cos64_lookup[ 128 - angle2 ].
1336
871M
    return cos64_lookup[128 - angle];
1337
1.00G
}
1338
1339
inline i32 Decoder::sin64(u8 angle)
1340
1.02G
{
1341
1.02G
    if (angle < 32)
1342
898M
        angle += 128;
1343
1.02G
    return cos64(angle - 32u);
1344
1.02G
}
1345
1346
// (8.7.1.1) The function B( a, b, angle, 0 ) performs a butterfly rotation.
1347
inline void Decoder::butterfly_rotation_in_place(Span<Intermediate> data, size_t index_a, size_t index_b, u8 angle, bool flip)
1348
1.00G
{
1349
1.00G
    auto cos = cos64(angle);
1350
1.00G
    auto sin = sin64(angle);
1351
    // 1. The variable x is set equal to T[ a ] * cos64( angle ) - T[ b ] * sin64( angle ).
1352
1.00G
    i64 rotated_a = static_cast<i64>(data[index_a]) * cos - static_cast<i64>(data[index_b]) * sin;
1353
    // 2. The variable y is set equal to T[ a ] * sin64( angle ) + T[ b ] * cos64( angle ).
1354
1.00G
    i64 rotated_b = static_cast<i64>(data[index_a]) * sin + static_cast<i64>(data[index_b]) * cos;
1355
    // 3. T[ a ] is set equal to Round2( x, 14 ).
1356
1.00G
    data[index_a] = rounded_right_shift(rotated_a, 14);
1357
    // 4. T[ b ] is set equal to Round2( y, 14 ).
1358
1.00G
    data[index_b] = rounded_right_shift(rotated_b, 14);
1359
1360
    // The function B( a ,b, angle, 1 ) performs a butterfly rotation and flip specified by the following ordered steps:
1361
    // 1. The function B( a, b, angle, 0 ) is invoked.
1362
    // 2. The contents of T[ a ] and T[ b ] are exchanged.
1363
1.00G
    if (flip)
1364
534M
        swap(data[index_a], data[index_b]);
1365
1366
    // It is a requirement of bitstream conformance that the values saved into the array T by this function are
1367
    // representable by a signed integer using 8 + BitDepth bits of precision.
1368
    // Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal
1369
    // to allow these bounds to be violated. Therefore, we can avoid the performance cost here.
1370
1.00G
}
1371
1372
// (8.7.1.1) The function H( a, b, 0 ) performs a Hadamard rotation.
1373
inline void Decoder::hadamard_rotation_in_place(Span<Intermediate> data, size_t index_a, size_t index_b, bool flip)
1374
1.86G
{
1375
    // The function H( a, b, 1 ) performs a Hadamard rotation with flipped indices and is specified as follows:
1376
    // 1. The function H( b, a, 0 ) is invoked.
1377
1.86G
    if (flip)
1378
447M
        swap(index_a, index_b);
1379
1380
    // The function H( a, b, 0 ) performs a Hadamard rotation specified by the following ordered steps:
1381
1382
    // 1. The variable x is set equal to T[ a ].
1383
1.86G
    auto a_value = data[index_a];
1384
    // 2. The variable y is set equal to T[ b ].
1385
1.86G
    auto b_value = data[index_b];
1386
    // 3. T[ a ] is set equal to x + y.
1387
1.86G
    data[index_a] = a_value + b_value;
1388
    // 4. T[ b ] is set equal to x - y.
1389
1.86G
    data[index_b] = a_value - b_value;
1390
1391
    // It is a requirement of bitstream conformance that the values saved into the array T by this function are
1392
    // representable by a signed integer using 8 + BitDepth bits of precision.
1393
    // Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal
1394
    // to allow these bounds to be violated. Therefore, we can avoid the performance cost here.
1395
1.86G
}
1396
1397
template<u8 log2_of_block_size>
1398
inline DecoderErrorOr<void> Decoder::inverse_discrete_cosine_transform_array_permutation(Span<Intermediate> data)
1399
90.5M
{
1400
90.5M
    static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range.");
1401
1402
90.5M
    constexpr u8 block_size = 1 << log2_of_block_size;
1403
1404
    // This process performs an in-place permutation of the array T of length 2^n for 2 ≤ n ≤ 5 which is required before
1405
    // execution of the inverse DCT process.
1406
90.5M
    if (log2_of_block_size < 2 || log2_of_block_size > 5)
1407
0
        return DecoderError::corrupted("Block size was out of range"sv);
1408
1409
    // 1.1. A temporary array named copyT is set equal to T.
1410
90.5M
    Array<Intermediate, block_size> data_copy;
1411
90.5M
    AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size);
1412
1413
    // 1.2. T[ i ] is set equal to copyT[ brev( n, i ) ] for i = 0..((1<<n) - 1).
1414
1.24G
    for (auto i = 0u; i < block_size; i++)
1415
1.15G
        data[i] = data_copy[brev<log2_of_block_size>(i)];
1416
1417
90.5M
    return {};
1418
90.5M
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_discrete_cosine_transform_array_permutation<(unsigned char)2>(AK::Span<int>)
Line
Count
Source
1399
46.3M
{
1400
46.3M
    static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range.");
1401
1402
46.3M
    constexpr u8 block_size = 1 << log2_of_block_size;
1403
1404
    // This process performs an in-place permutation of the array T of length 2^n for 2 ≤ n ≤ 5 which is required before
1405
    // execution of the inverse DCT process.
1406
46.3M
    if (log2_of_block_size < 2 || log2_of_block_size > 5)
1407
0
        return DecoderError::corrupted("Block size was out of range"sv);
1408
1409
    // 1.1. A temporary array named copyT is set equal to T.
1410
46.3M
    Array<Intermediate, block_size> data_copy;
1411
46.3M
    AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size);
1412
1413
    // 1.2. T[ i ] is set equal to copyT[ brev( n, i ) ] for i = 0..((1<<n) - 1).
1414
231M
    for (auto i = 0u; i < block_size; i++)
1415
184M
        data[i] = data_copy[brev<log2_of_block_size>(i)];
1416
1417
46.3M
    return {};
1418
46.3M
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_discrete_cosine_transform_array_permutation<(unsigned char)3>(AK::Span<int>)
Line
Count
Source
1399
14.9M
{
1400
14.9M
    static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range.");
1401
1402
14.9M
    constexpr u8 block_size = 1 << log2_of_block_size;
1403
1404
    // This process performs an in-place permutation of the array T of length 2^n for 2 ≤ n ≤ 5 which is required before
1405
    // execution of the inverse DCT process.
1406
14.9M
    if (log2_of_block_size < 2 || log2_of_block_size > 5)
1407
0
        return DecoderError::corrupted("Block size was out of range"sv);
1408
1409
    // 1.1. A temporary array named copyT is set equal to T.
1410
14.9M
    Array<Intermediate, block_size> data_copy;
1411
14.9M
    AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size);
1412
1413
    // 1.2. T[ i ] is set equal to copyT[ brev( n, i ) ] for i = 0..((1<<n) - 1).
1414
134M
    for (auto i = 0u; i < block_size; i++)
1415
119M
        data[i] = data_copy[brev<log2_of_block_size>(i)];
1416
1417
14.9M
    return {};
1418
14.9M
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_discrete_cosine_transform_array_permutation<(unsigned char)4>(AK::Span<int>)
Line
Count
Source
1399
4.82M
{
1400
4.82M
    static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range.");
1401
1402
4.82M
    constexpr u8 block_size = 1 << log2_of_block_size;
1403
1404
    // This process performs an in-place permutation of the array T of length 2^n for 2 ≤ n ≤ 5 which is required before
1405
    // execution of the inverse DCT process.
1406
4.82M
    if (log2_of_block_size < 2 || log2_of_block_size > 5)
1407
0
        return DecoderError::corrupted("Block size was out of range"sv);
1408
1409
    // 1.1. A temporary array named copyT is set equal to T.
1410
4.82M
    Array<Intermediate, block_size> data_copy;
1411
4.82M
    AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size);
1412
1413
    // 1.2. T[ i ] is set equal to copyT[ brev( n, i ) ] for i = 0..((1<<n) - 1).
1414
81.9M
    for (auto i = 0u; i < block_size; i++)
1415
77.1M
        data[i] = data_copy[brev<log2_of_block_size>(i)];
1416
1417
4.82M
    return {};
1418
4.82M
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_discrete_cosine_transform_array_permutation<(unsigned char)5>(AK::Span<int>)
Line
Count
Source
1399
24.3M
{
1400
24.3M
    static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range.");
1401
1402
24.3M
    constexpr u8 block_size = 1 << log2_of_block_size;
1403
1404
    // This process performs an in-place permutation of the array T of length 2^n for 2 ≤ n ≤ 5 which is required before
1405
    // execution of the inverse DCT process.
1406
24.3M
    if (log2_of_block_size < 2 || log2_of_block_size > 5)
1407
0
        return DecoderError::corrupted("Block size was out of range"sv);
1408
1409
    // 1.1. A temporary array named copyT is set equal to T.
1410
24.3M
    Array<Intermediate, block_size> data_copy;
1411
24.3M
    AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size);
1412
1413
    // 1.2. T[ i ] is set equal to copyT[ brev( n, i ) ] for i = 0..((1<<n) - 1).
1414
799M
    for (auto i = 0u; i < block_size; i++)
1415
774M
        data[i] = data_copy[brev<log2_of_block_size>(i)];
1416
1417
24.3M
    return {};
1418
24.3M
}
1419
1420
template<u8 log2_of_block_size>
1421
ALWAYS_INLINE DecoderErrorOr<void> Decoder::inverse_discrete_cosine_transform(Span<Intermediate> data)
1422
188M
{
1423
188M
    static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range.");
1424
1425
    // 2.1. The variable n0 is set equal to 1<<n.
1426
188M
    constexpr u8 block_size = 1 << log2_of_block_size;
1427
1428
    // 8.7.1.3 Inverse DCT process
1429
1430
    // 2.2. The variable n1 is set equal to 1<<(n-1).
1431
188M
    constexpr u8 half_block_size = block_size >> 1;
1432
    // 2.3 The variable n2 is set equal to 1<<(n-2).
1433
188M
    constexpr u8 quarter_block_size = half_block_size >> 1;
1434
    // 2.4 The variable n3 is set equal to 1<<(n-3).
1435
188M
    constexpr u8 eighth_block_size = quarter_block_size >> 1;
1436
1437
    // 2.5 If n is equal to 2, invoke B( 0, 1, 16, 1 ), otherwise recursively invoke the inverse DCT defined in this
1438
    // section with the variable n set equal to n - 1.
1439
    if constexpr (log2_of_block_size == 2)
1440
90.5M
        butterfly_rotation_in_place(data, 0, 1, 16, true);
1441
    else
1442
97.9M
        TRY(inverse_discrete_cosine_transform<log2_of_block_size - 1>(data));
1443
1444
    // 2.6 Invoke B( n1+i, n0-1-i, 32-brev( 5, n1+i), 0 ) for i = 0..(n2-1).
1445
677M
    for (auto i = 0u; i < quarter_block_size; i++) {
1446
488M
        auto index = half_block_size + i;
1447
488M
        butterfly_rotation_in_place(data, index, block_size - 1 - i, 32 - brev<5>(index), false);
1448
488M
    }
1449
1450
    // 2.7 If n is greater than or equal to 3:
1451
188M
    if constexpr (log2_of_block_size >= 3) {
1452
        // a. Invoke H( n1+4*i+2*j, n1+1+4*i+2*j, j ) for i = 0..(n3-1), j = 0..1.
1453
297M
        for (auto i = 0u; i < eighth_block_size; i++) {
1454
599M
            for (auto j = 0u; j < 2; j++) {
1455
399M
                auto index = half_block_size + (4 * i) + (2 * j);
1456
399M
                hadamard_rotation_in_place(data, index, index + 1, j);
1457
399M
            }
1458
200M
        }
1459
97.9M
    }
1460
1461
    // 4. If n is equal to 5:
1462
188M
    if constexpr (log2_of_block_size == 5) {
1463
        // a. Invoke B( n0-n+3-n2*j-4*i, n1+n-4+n2*j+4*i, 28-16*i+56*j, 1 ) for i = 0..1, j = 0..1.
1464
73.1M
        for (auto i = 0u; i < 2; i++) {
1465
145M
            for (auto j = 0u; j < 2; j++) {
1466
97.0M
                auto index_a = block_size - log2_of_block_size + 3 - (quarter_block_size * j) - (4 * i);
1467
97.0M
                auto index_b = half_block_size + log2_of_block_size - 4 + (quarter_block_size * j) + (4 * i);
1468
97.0M
                auto angle = 28 - (16 * i) + (56 * j);
1469
97.0M
                butterfly_rotation_in_place(data, index_a, index_b, angle, true);
1470
97.0M
            }
1471
48.6M
        }
1472
1473
        // b. Invoke H( n1+n3*j+i, n1+n2-5+n3*j-i, j&1 ) for i = 0..1, j = 0..3.
1474
73.2M
        for (auto i = 0u; i < 2; i++) {
1475
243M
            for (auto j = 0u; j < 4; j++) {
1476
195M
                auto index_a = half_block_size + (eighth_block_size * j) + i;
1477
195M
                auto index_b = half_block_size + quarter_block_size - 5 + (eighth_block_size * j) - i;
1478
195M
                hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0);
1479
195M
            }
1480
48.7M
        }
1481
24.4M
    }
1482
1483
    // 5. If n is greater than or equal to 4:
1484
188M
    if constexpr (log2_of_block_size >= 4) {
1485
        // a. Invoke B( n0-n+2-i-n2*j, n1+n-3+i+n2*j, 24+48*j, 1 ) for i = 0..(n==5), j = 0..1.
1486
131M
        for (auto i = 0u; i <= (log2_of_block_size == 5); i++) {
1487
233M
            for (auto j = 0u; j < 2; j++) {
1488
155M
                auto index_a = block_size - log2_of_block_size + 2 - i - (quarter_block_size * j);
1489
155M
                auto index_b = half_block_size + log2_of_block_size - 3 + i + (quarter_block_size * j);
1490
155M
                butterfly_rotation_in_place(data, index_a, index_b, 24 + (48 * j), true);
1491
155M
            }
1492
77.9M
        }
1493
1494
        // b. Invoke H( n1+n2*j+i, n1+n2-1+n2*j-i, j&1 ) for i = 0..(2n-7), j = 0..1.
1495
209M
        for (auto i = 0u; i < (2 * log2_of_block_size) - 6u; i++) {
1496
467M
            for (auto j = 0u; j < 2; j++) {
1497
311M
                auto index_a = half_block_size + (quarter_block_size * j) + i;
1498
311M
                auto index_b = half_block_size + quarter_block_size - 1 + (quarter_block_size * j) - i;
1499
311M
                hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0);
1500
311M
            }
1501
155M
        }
1502
53.6M
    }
1503
1504
    // 6. If n is greater than or equal to 3:
1505
188M
    if constexpr (log2_of_block_size >= 3) {
1506
        // a. Invoke B( n0-n3-1-i, n1+n3+i, 16, 1 ) for i = 0..(n3-1).
1507
297M
        for (auto i = 0u; i < eighth_block_size; i++) {
1508
199M
            auto index_a = block_size - eighth_block_size - 1 - i;
1509
199M
            auto index_b = half_block_size + eighth_block_size + i;
1510
199M
            butterfly_rotation_in_place(data, index_a, index_b, 16, true);
1511
199M
        }
1512
97.9M
    }
1513
1514
    // 7. Invoke H( i, n0-1-i, 0 ) for i = 0..(n1-1).
1515
1.17G
    for (auto i = 0u; i < half_block_size; i++)
1516
984M
        hadamard_rotation_in_place(data, i, block_size - 1 - i, false);
1517
1518
188M
    return {};
1519
188M
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_discrete_cosine_transform<(unsigned char)2>(AK::Span<int>)
Line
Count
Source
1422
90.5M
{
1423
90.5M
    static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range.");
1424
1425
    // 2.1. The variable n0 is set equal to 1<<n.
1426
90.5M
    constexpr u8 block_size = 1 << log2_of_block_size;
1427
1428
    // 8.7.1.3 Inverse DCT process
1429
1430
    // 2.2. The variable n1 is set equal to 1<<(n-1).
1431
90.5M
    constexpr u8 half_block_size = block_size >> 1;
1432
    // 2.3 The variable n2 is set equal to 1<<(n-2).
1433
90.5M
    constexpr u8 quarter_block_size = half_block_size >> 1;
1434
    // 2.4 The variable n3 is set equal to 1<<(n-3).
1435
90.5M
    constexpr u8 eighth_block_size = quarter_block_size >> 1;
1436
1437
    // 2.5 If n is equal to 2, invoke B( 0, 1, 16, 1 ), otherwise recursively invoke the inverse DCT defined in this
1438
    // section with the variable n set equal to n - 1.
1439
    if constexpr (log2_of_block_size == 2)
1440
90.5M
        butterfly_rotation_in_place(data, 0, 1, 16, true);
1441
    else
1442
        TRY(inverse_discrete_cosine_transform<log2_of_block_size - 1>(data));
1443
1444
    // 2.6 Invoke B( n1+i, n0-1-i, 32-brev( 5, n1+i), 0 ) for i = 0..(n2-1).
1445
181M
    for (auto i = 0u; i < quarter_block_size; i++) {
1446
90.4M
        auto index = half_block_size + i;
1447
90.4M
        butterfly_rotation_in_place(data, index, block_size - 1 - i, 32 - brev<5>(index), false);
1448
90.4M
    }
1449
1450
    // 2.7 If n is greater than or equal to 3:
1451
    if constexpr (log2_of_block_size >= 3) {
1452
        // a. Invoke H( n1+4*i+2*j, n1+1+4*i+2*j, j ) for i = 0..(n3-1), j = 0..1.
1453
        for (auto i = 0u; i < eighth_block_size; i++) {
1454
            for (auto j = 0u; j < 2; j++) {
1455
                auto index = half_block_size + (4 * i) + (2 * j);
1456
                hadamard_rotation_in_place(data, index, index + 1, j);
1457
            }
1458
        }
1459
    }
1460
1461
    // 4. If n is equal to 5:
1462
    if constexpr (log2_of_block_size == 5) {
1463
        // a. Invoke B( n0-n+3-n2*j-4*i, n1+n-4+n2*j+4*i, 28-16*i+56*j, 1 ) for i = 0..1, j = 0..1.
1464
        for (auto i = 0u; i < 2; i++) {
1465
            for (auto j = 0u; j < 2; j++) {
1466
                auto index_a = block_size - log2_of_block_size + 3 - (quarter_block_size * j) - (4 * i);
1467
                auto index_b = half_block_size + log2_of_block_size - 4 + (quarter_block_size * j) + (4 * i);
1468
                auto angle = 28 - (16 * i) + (56 * j);
1469
                butterfly_rotation_in_place(data, index_a, index_b, angle, true);
1470
            }
1471
        }
1472
1473
        // b. Invoke H( n1+n3*j+i, n1+n2-5+n3*j-i, j&1 ) for i = 0..1, j = 0..3.
1474
        for (auto i = 0u; i < 2; i++) {
1475
            for (auto j = 0u; j < 4; j++) {
1476
                auto index_a = half_block_size + (eighth_block_size * j) + i;
1477
                auto index_b = half_block_size + quarter_block_size - 5 + (eighth_block_size * j) - i;
1478
                hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0);
1479
            }
1480
        }
1481
    }
1482
1483
    // 5. If n is greater than or equal to 4:
1484
    if constexpr (log2_of_block_size >= 4) {
1485
        // a. Invoke B( n0-n+2-i-n2*j, n1+n-3+i+n2*j, 24+48*j, 1 ) for i = 0..(n==5), j = 0..1.
1486
        for (auto i = 0u; i <= (log2_of_block_size == 5); i++) {
1487
            for (auto j = 0u; j < 2; j++) {
1488
                auto index_a = block_size - log2_of_block_size + 2 - i - (quarter_block_size * j);
1489
                auto index_b = half_block_size + log2_of_block_size - 3 + i + (quarter_block_size * j);
1490
                butterfly_rotation_in_place(data, index_a, index_b, 24 + (48 * j), true);
1491
            }
1492
        }
1493
1494
        // b. Invoke H( n1+n2*j+i, n1+n2-1+n2*j-i, j&1 ) for i = 0..(2n-7), j = 0..1.
1495
        for (auto i = 0u; i < (2 * log2_of_block_size) - 6u; i++) {
1496
            for (auto j = 0u; j < 2; j++) {
1497
                auto index_a = half_block_size + (quarter_block_size * j) + i;
1498
                auto index_b = half_block_size + quarter_block_size - 1 + (quarter_block_size * j) - i;
1499
                hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0);
1500
            }
1501
        }
1502
    }
1503
1504
    // 6. If n is greater than or equal to 3:
1505
    if constexpr (log2_of_block_size >= 3) {
1506
        // a. Invoke B( n0-n3-1-i, n1+n3+i, 16, 1 ) for i = 0..(n3-1).
1507
        for (auto i = 0u; i < eighth_block_size; i++) {
1508
            auto index_a = block_size - eighth_block_size - 1 - i;
1509
            auto index_b = half_block_size + eighth_block_size + i;
1510
            butterfly_rotation_in_place(data, index_a, index_b, 16, true);
1511
        }
1512
    }
1513
1514
    // 7. Invoke H( i, n0-1-i, 0 ) for i = 0..(n1-1).
1515
272M
    for (auto i = 0u; i < half_block_size; i++)
1516
181M
        hadamard_rotation_in_place(data, i, block_size - 1 - i, false);
1517
1518
90.5M
    return {};
1519
90.5M
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_discrete_cosine_transform<(unsigned char)3>(AK::Span<int>)
Line
Count
Source
1422
44.2M
{
1423
44.2M
    static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range.");
1424
1425
    // 2.1. The variable n0 is set equal to 1<<n.
1426
44.2M
    constexpr u8 block_size = 1 << log2_of_block_size;
1427
1428
    // 8.7.1.3 Inverse DCT process
1429
1430
    // 2.2. The variable n1 is set equal to 1<<(n-1).
1431
44.2M
    constexpr u8 half_block_size = block_size >> 1;
1432
    // 2.3 The variable n2 is set equal to 1<<(n-2).
1433
44.2M
    constexpr u8 quarter_block_size = half_block_size >> 1;
1434
    // 2.4 The variable n3 is set equal to 1<<(n-3).
1435
44.2M
    constexpr u8 eighth_block_size = quarter_block_size >> 1;
1436
1437
    // 2.5 If n is equal to 2, invoke B( 0, 1, 16, 1 ), otherwise recursively invoke the inverse DCT defined in this
1438
    // section with the variable n set equal to n - 1.
1439
    if constexpr (log2_of_block_size == 2)
1440
        butterfly_rotation_in_place(data, 0, 1, 16, true);
1441
    else
1442
44.2M
        TRY(inverse_discrete_cosine_transform<log2_of_block_size - 1>(data));
1443
1444
    // 2.6 Invoke B( n1+i, n0-1-i, 32-brev( 5, n1+i), 0 ) for i = 0..(n2-1).
1445
132M
    for (auto i = 0u; i < quarter_block_size; i++) {
1446
88.2M
        auto index = half_block_size + i;
1447
88.2M
        butterfly_rotation_in_place(data, index, block_size - 1 - i, 32 - brev<5>(index), false);
1448
88.2M
    }
1449
1450
    // 2.7 If n is greater than or equal to 3:
1451
44.2M
    if constexpr (log2_of_block_size >= 3) {
1452
        // a. Invoke H( n1+4*i+2*j, n1+1+4*i+2*j, j ) for i = 0..(n3-1), j = 0..1.
1453
88.4M
        for (auto i = 0u; i < eighth_block_size; i++) {
1454
132M
            for (auto j = 0u; j < 2; j++) {
1455
88.3M
                auto index = half_block_size + (4 * i) + (2 * j);
1456
88.3M
                hadamard_rotation_in_place(data, index, index + 1, j);
1457
88.3M
            }
1458
44.1M
        }
1459
44.2M
    }
1460
1461
    // 4. If n is equal to 5:
1462
    if constexpr (log2_of_block_size == 5) {
1463
        // a. Invoke B( n0-n+3-n2*j-4*i, n1+n-4+n2*j+4*i, 28-16*i+56*j, 1 ) for i = 0..1, j = 0..1.
1464
        for (auto i = 0u; i < 2; i++) {
1465
            for (auto j = 0u; j < 2; j++) {
1466
                auto index_a = block_size - log2_of_block_size + 3 - (quarter_block_size * j) - (4 * i);
1467
                auto index_b = half_block_size + log2_of_block_size - 4 + (quarter_block_size * j) + (4 * i);
1468
                auto angle = 28 - (16 * i) + (56 * j);
1469
                butterfly_rotation_in_place(data, index_a, index_b, angle, true);
1470
            }
1471
        }
1472
1473
        // b. Invoke H( n1+n3*j+i, n1+n2-5+n3*j-i, j&1 ) for i = 0..1, j = 0..3.
1474
        for (auto i = 0u; i < 2; i++) {
1475
            for (auto j = 0u; j < 4; j++) {
1476
                auto index_a = half_block_size + (eighth_block_size * j) + i;
1477
                auto index_b = half_block_size + quarter_block_size - 5 + (eighth_block_size * j) - i;
1478
                hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0);
1479
            }
1480
        }
1481
    }
1482
1483
    // 5. If n is greater than or equal to 4:
1484
    if constexpr (log2_of_block_size >= 4) {
1485
        // a. Invoke B( n0-n+2-i-n2*j, n1+n-3+i+n2*j, 24+48*j, 1 ) for i = 0..(n==5), j = 0..1.
1486
        for (auto i = 0u; i <= (log2_of_block_size == 5); i++) {
1487
            for (auto j = 0u; j < 2; j++) {
1488
                auto index_a = block_size - log2_of_block_size + 2 - i - (quarter_block_size * j);
1489
                auto index_b = half_block_size + log2_of_block_size - 3 + i + (quarter_block_size * j);
1490
                butterfly_rotation_in_place(data, index_a, index_b, 24 + (48 * j), true);
1491
            }
1492
        }
1493
1494
        // b. Invoke H( n1+n2*j+i, n1+n2-1+n2*j-i, j&1 ) for i = 0..(2n-7), j = 0..1.
1495
        for (auto i = 0u; i < (2 * log2_of_block_size) - 6u; i++) {
1496
            for (auto j = 0u; j < 2; j++) {
1497
                auto index_a = half_block_size + (quarter_block_size * j) + i;
1498
                auto index_b = half_block_size + quarter_block_size - 1 + (quarter_block_size * j) - i;
1499
                hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0);
1500
            }
1501
        }
1502
    }
1503
1504
    // 6. If n is greater than or equal to 3:
1505
44.2M
    if constexpr (log2_of_block_size >= 3) {
1506
        // a. Invoke B( n0-n3-1-i, n1+n3+i, 16, 1 ) for i = 0..(n3-1).
1507
88.4M
        for (auto i = 0u; i < eighth_block_size; i++) {
1508
44.1M
            auto index_a = block_size - eighth_block_size - 1 - i;
1509
44.1M
            auto index_b = half_block_size + eighth_block_size + i;
1510
44.1M
            butterfly_rotation_in_place(data, index_a, index_b, 16, true);
1511
44.1M
        }
1512
44.2M
    }
1513
1514
    // 7. Invoke H( i, n0-1-i, 0 ) for i = 0..(n1-1).
1515
221M
    for (auto i = 0u; i < half_block_size; i++)
1516
176M
        hadamard_rotation_in_place(data, i, block_size - 1 - i, false);
1517
1518
44.2M
    return {};
1519
44.2M
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_discrete_cosine_transform<(unsigned char)4>(AK::Span<int>)
Line
Count
Source
1422
29.2M
{
1423
29.2M
    static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range.");
1424
1425
    // 2.1. The variable n0 is set equal to 1<<n.
1426
29.2M
    constexpr u8 block_size = 1 << log2_of_block_size;
1427
1428
    // 8.7.1.3 Inverse DCT process
1429
1430
    // 2.2. The variable n1 is set equal to 1<<(n-1).
1431
29.2M
    constexpr u8 half_block_size = block_size >> 1;
1432
    // 2.3 The variable n2 is set equal to 1<<(n-2).
1433
29.2M
    constexpr u8 quarter_block_size = half_block_size >> 1;
1434
    // 2.4 The variable n3 is set equal to 1<<(n-3).
1435
29.2M
    constexpr u8 eighth_block_size = quarter_block_size >> 1;
1436
1437
    // 2.5 If n is equal to 2, invoke B( 0, 1, 16, 1 ), otherwise recursively invoke the inverse DCT defined in this
1438
    // section with the variable n set equal to n - 1.
1439
    if constexpr (log2_of_block_size == 2)
1440
        butterfly_rotation_in_place(data, 0, 1, 16, true);
1441
    else
1442
29.2M
        TRY(inverse_discrete_cosine_transform<log2_of_block_size - 1>(data));
1443
1444
    // 2.6 Invoke B( n1+i, n0-1-i, 32-brev( 5, n1+i), 0 ) for i = 0..(n2-1).
1445
145M
    for (auto i = 0u; i < quarter_block_size; i++) {
1446
116M
        auto index = half_block_size + i;
1447
116M
        butterfly_rotation_in_place(data, index, block_size - 1 - i, 32 - brev<5>(index), false);
1448
116M
    }
1449
1450
    // 2.7 If n is greater than or equal to 3:
1451
29.2M
    if constexpr (log2_of_block_size >= 3) {
1452
        // a. Invoke H( n1+4*i+2*j, n1+1+4*i+2*j, j ) for i = 0..(n3-1), j = 0..1.
1453
87.6M
        for (auto i = 0u; i < eighth_block_size; i++) {
1454
175M
            for (auto j = 0u; j < 2; j++) {
1455
116M
                auto index = half_block_size + (4 * i) + (2 * j);
1456
116M
                hadamard_rotation_in_place(data, index, index + 1, j);
1457
116M
            }
1458
58.3M
        }
1459
29.2M
    }
1460
1461
    // 4. If n is equal to 5:
1462
    if constexpr (log2_of_block_size == 5) {
1463
        // a. Invoke B( n0-n+3-n2*j-4*i, n1+n-4+n2*j+4*i, 28-16*i+56*j, 1 ) for i = 0..1, j = 0..1.
1464
        for (auto i = 0u; i < 2; i++) {
1465
            for (auto j = 0u; j < 2; j++) {
1466
                auto index_a = block_size - log2_of_block_size + 3 - (quarter_block_size * j) - (4 * i);
1467
                auto index_b = half_block_size + log2_of_block_size - 4 + (quarter_block_size * j) + (4 * i);
1468
                auto angle = 28 - (16 * i) + (56 * j);
1469
                butterfly_rotation_in_place(data, index_a, index_b, angle, true);
1470
            }
1471
        }
1472
1473
        // b. Invoke H( n1+n3*j+i, n1+n2-5+n3*j-i, j&1 ) for i = 0..1, j = 0..3.
1474
        for (auto i = 0u; i < 2; i++) {
1475
            for (auto j = 0u; j < 4; j++) {
1476
                auto index_a = half_block_size + (eighth_block_size * j) + i;
1477
                auto index_b = half_block_size + quarter_block_size - 5 + (eighth_block_size * j) - i;
1478
                hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0);
1479
            }
1480
        }
1481
    }
1482
1483
    // 5. If n is greater than or equal to 4:
1484
29.2M
    if constexpr (log2_of_block_size >= 4) {
1485
        // a. Invoke B( n0-n+2-i-n2*j, n1+n-3+i+n2*j, 24+48*j, 1 ) for i = 0..(n==5), j = 0..1.
1486
58.4M
        for (auto i = 0u; i <= (log2_of_block_size == 5); i++) {
1487
87.5M
            for (auto j = 0u; j < 2; j++) {
1488
58.3M
                auto index_a = block_size - log2_of_block_size + 2 - i - (quarter_block_size * j);
1489
58.3M
                auto index_b = half_block_size + log2_of_block_size - 3 + i + (quarter_block_size * j);
1490
58.3M
                butterfly_rotation_in_place(data, index_a, index_b, 24 + (48 * j), true);
1491
58.3M
            }
1492
29.1M
        }
1493
1494
        // b. Invoke H( n1+n2*j+i, n1+n2-1+n2*j-i, j&1 ) for i = 0..(2n-7), j = 0..1.
1495
87.6M
        for (auto i = 0u; i < (2 * log2_of_block_size) - 6u; i++) {
1496
175M
            for (auto j = 0u; j < 2; j++) {
1497
116M
                auto index_a = half_block_size + (quarter_block_size * j) + i;
1498
116M
                auto index_b = half_block_size + quarter_block_size - 1 + (quarter_block_size * j) - i;
1499
116M
                hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0);
1500
116M
            }
1501
58.4M
        }
1502
29.2M
    }
1503
1504
    // 6. If n is greater than or equal to 3:
1505
29.2M
    if constexpr (log2_of_block_size >= 3) {
1506
        // a. Invoke B( n0-n3-1-i, n1+n3+i, 16, 1 ) for i = 0..(n3-1).
1507
87.6M
        for (auto i = 0u; i < eighth_block_size; i++) {
1508
58.3M
            auto index_a = block_size - eighth_block_size - 1 - i;
1509
58.3M
            auto index_b = half_block_size + eighth_block_size + i;
1510
58.3M
            butterfly_rotation_in_place(data, index_a, index_b, 16, true);
1511
58.3M
        }
1512
29.2M
    }
1513
1514
    // 7. Invoke H( i, n0-1-i, 0 ) for i = 0..(n1-1).
1515
263M
    for (auto i = 0u; i < half_block_size; i++)
1516
234M
        hadamard_rotation_in_place(data, i, block_size - 1 - i, false);
1517
1518
29.2M
    return {};
1519
29.2M
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_discrete_cosine_transform<(unsigned char)5>(AK::Span<int>)
Line
Count
Source
1422
24.4M
{
1423
24.4M
    static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range.");
1424
1425
    // 2.1. The variable n0 is set equal to 1<<n.
1426
24.4M
    constexpr u8 block_size = 1 << log2_of_block_size;
1427
1428
    // 8.7.1.3 Inverse DCT process
1429
1430
    // 2.2. The variable n1 is set equal to 1<<(n-1).
1431
24.4M
    constexpr u8 half_block_size = block_size >> 1;
1432
    // 2.3 The variable n2 is set equal to 1<<(n-2).
1433
24.4M
    constexpr u8 quarter_block_size = half_block_size >> 1;
1434
    // 2.4 The variable n3 is set equal to 1<<(n-3).
1435
24.4M
    constexpr u8 eighth_block_size = quarter_block_size >> 1;
1436
1437
    // 2.5 If n is equal to 2, invoke B( 0, 1, 16, 1 ), otherwise recursively invoke the inverse DCT defined in this
1438
    // section with the variable n set equal to n - 1.
1439
    if constexpr (log2_of_block_size == 2)
1440
        butterfly_rotation_in_place(data, 0, 1, 16, true);
1441
    else
1442
24.4M
        TRY(inverse_discrete_cosine_transform<log2_of_block_size - 1>(data));
1443
1444
    // 2.6 Invoke B( n1+i, n0-1-i, 32-brev( 5, n1+i), 0 ) for i = 0..(n2-1).
1445
217M
    for (auto i = 0u; i < quarter_block_size; i++) {
1446
193M
        auto index = half_block_size + i;
1447
193M
        butterfly_rotation_in_place(data, index, block_size - 1 - i, 32 - brev<5>(index), false);
1448
193M
    }
1449
1450
    // 2.7 If n is greater than or equal to 3:
1451
24.4M
    if constexpr (log2_of_block_size >= 3) {
1452
        // a. Invoke H( n1+4*i+2*j, n1+1+4*i+2*j, j ) for i = 0..(n3-1), j = 0..1.
1453
121M
        for (auto i = 0u; i < eighth_block_size; i++) {
1454
292M
            for (auto j = 0u; j < 2; j++) {
1455
194M
                auto index = half_block_size + (4 * i) + (2 * j);
1456
194M
                hadamard_rotation_in_place(data, index, index + 1, j);
1457
194M
            }
1458
97.4M
        }
1459
24.4M
    }
1460
1461
    // 4. If n is equal to 5:
1462
24.4M
    if constexpr (log2_of_block_size == 5) {
1463
        // a. Invoke B( n0-n+3-n2*j-4*i, n1+n-4+n2*j+4*i, 28-16*i+56*j, 1 ) for i = 0..1, j = 0..1.
1464
73.1M
        for (auto i = 0u; i < 2; i++) {
1465
145M
            for (auto j = 0u; j < 2; j++) {
1466
97.0M
                auto index_a = block_size - log2_of_block_size + 3 - (quarter_block_size * j) - (4 * i);
1467
97.0M
                auto index_b = half_block_size + log2_of_block_size - 4 + (quarter_block_size * j) + (4 * i);
1468
97.0M
                auto angle = 28 - (16 * i) + (56 * j);
1469
97.0M
                butterfly_rotation_in_place(data, index_a, index_b, angle, true);
1470
97.0M
            }
1471
48.6M
        }
1472
1473
        // b. Invoke H( n1+n3*j+i, n1+n2-5+n3*j-i, j&1 ) for i = 0..1, j = 0..3.
1474
73.2M
        for (auto i = 0u; i < 2; i++) {
1475
243M
            for (auto j = 0u; j < 4; j++) {
1476
195M
                auto index_a = half_block_size + (eighth_block_size * j) + i;
1477
195M
                auto index_b = half_block_size + quarter_block_size - 5 + (eighth_block_size * j) - i;
1478
195M
                hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0);
1479
195M
            }
1480
48.7M
        }
1481
24.4M
    }
1482
1483
    // 5. If n is greater than or equal to 4:
1484
24.4M
    if constexpr (log2_of_block_size >= 4) {
1485
        // a. Invoke B( n0-n+2-i-n2*j, n1+n-3+i+n2*j, 24+48*j, 1 ) for i = 0..(n==5), j = 0..1.
1486
73.1M
        for (auto i = 0u; i <= (log2_of_block_size == 5); i++) {
1487
145M
            for (auto j = 0u; j < 2; j++) {
1488
97.1M
                auto index_a = block_size - log2_of_block_size + 2 - i - (quarter_block_size * j);
1489
97.1M
                auto index_b = half_block_size + log2_of_block_size - 3 + i + (quarter_block_size * j);
1490
97.1M
                butterfly_rotation_in_place(data, index_a, index_b, 24 + (48 * j), true);
1491
97.1M
            }
1492
48.7M
        }
1493
1494
        // b. Invoke H( n1+n2*j+i, n1+n2-1+n2*j-i, j&1 ) for i = 0..(2n-7), j = 0..1.
1495
122M
        for (auto i = 0u; i < (2 * log2_of_block_size) - 6u; i++) {
1496
292M
            for (auto j = 0u; j < 2; j++) {
1497
195M
                auto index_a = half_block_size + (quarter_block_size * j) + i;
1498
195M
                auto index_b = half_block_size + quarter_block_size - 1 + (quarter_block_size * j) - i;
1499
195M
                hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0);
1500
195M
            }
1501
97.5M
        }
1502
24.4M
    }
1503
1504
    // 6. If n is greater than or equal to 3:
1505
24.4M
    if constexpr (log2_of_block_size >= 3) {
1506
        // a. Invoke B( n0-n3-1-i, n1+n3+i, 16, 1 ) for i = 0..(n3-1).
1507
121M
        for (auto i = 0u; i < eighth_block_size; i++) {
1508
97.2M
            auto index_a = block_size - eighth_block_size - 1 - i;
1509
97.2M
            auto index_b = half_block_size + eighth_block_size + i;
1510
97.2M
            butterfly_rotation_in_place(data, index_a, index_b, 16, true);
1511
97.2M
        }
1512
24.4M
    }
1513
1514
    // 7. Invoke H( i, n0-1-i, 0 ) for i = 0..(n1-1).
1515
415M
    for (auto i = 0u; i < half_block_size; i++)
1516
391M
        hadamard_rotation_in_place(data, i, block_size - 1 - i, false);
1517
1518
24.4M
    return {};
1519
24.4M
}
1520
1521
template<u8 log2_of_block_size>
1522
inline void Decoder::inverse_asymmetric_discrete_sine_transform_input_array_permutation(Span<Intermediate> data)
1523
1.90M
{
1524
    // The variable n0 is set equal to 1<<n.
1525
1.90M
    constexpr auto block_size = 1u << log2_of_block_size;
1526
    // The variable n1 is set equal to 1<<(n-1).
1527
    // We can iterate by 2 at a time instead of taking half block size.
1528
1529
    // A temporary array named copyT is set equal to T.
1530
1.90M
    Array<Intermediate, block_size> data_copy;
1531
1.90M
    AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size);
1532
1533
    // The values at even locations T[ 2 * i ] are set equal to copyT[ n0 - 1 - 2 * i ] for i = 0..(n1-1).
1534
    // The values at odd locations T[ 2 * i + 1 ] are set equal to copyT[ 2 * i ] for i = 0..(n1-1).
1535
12.0M
    for (auto i = 0u; i < block_size; i += 2) {
1536
10.1M
        data[i] = data_copy[block_size - 1 - i];
1537
10.1M
        data[i + 1] = data_copy[i];
1538
10.1M
    }
1539
1.90M
}
void Media::Video::VP9::Decoder::inverse_asymmetric_discrete_sine_transform_input_array_permutation<(unsigned char)3>(AK::Span<int>)
Line
Count
Source
1523
1.27M
{
1524
    // The variable n0 is set equal to 1<<n.
1525
1.27M
    constexpr auto block_size = 1u << log2_of_block_size;
1526
    // The variable n1 is set equal to 1<<(n-1).
1527
    // We can iterate by 2 at a time instead of taking half block size.
1528
1529
    // A temporary array named copyT is set equal to T.
1530
1.27M
    Array<Intermediate, block_size> data_copy;
1531
1.27M
    AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size);
1532
1533
    // The values at even locations T[ 2 * i ] are set equal to copyT[ n0 - 1 - 2 * i ] for i = 0..(n1-1).
1534
    // The values at odd locations T[ 2 * i + 1 ] are set equal to copyT[ 2 * i ] for i = 0..(n1-1).
1535
6.39M
    for (auto i = 0u; i < block_size; i += 2) {
1536
5.11M
        data[i] = data_copy[block_size - 1 - i];
1537
5.11M
        data[i + 1] = data_copy[i];
1538
5.11M
    }
1539
1.27M
}
void Media::Video::VP9::Decoder::inverse_asymmetric_discrete_sine_transform_input_array_permutation<(unsigned char)4>(AK::Span<int>)
Line
Count
Source
1523
630k
{
1524
    // The variable n0 is set equal to 1<<n.
1525
630k
    constexpr auto block_size = 1u << log2_of_block_size;
1526
    // The variable n1 is set equal to 1<<(n-1).
1527
    // We can iterate by 2 at a time instead of taking half block size.
1528
1529
    // A temporary array named copyT is set equal to T.
1530
630k
    Array<Intermediate, block_size> data_copy;
1531
630k
    AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size);
1532
1533
    // The values at even locations T[ 2 * i ] are set equal to copyT[ n0 - 1 - 2 * i ] for i = 0..(n1-1).
1534
    // The values at odd locations T[ 2 * i + 1 ] are set equal to copyT[ 2 * i ] for i = 0..(n1-1).
1535
5.67M
    for (auto i = 0u; i < block_size; i += 2) {
1536
5.04M
        data[i] = data_copy[block_size - 1 - i];
1537
5.04M
        data[i + 1] = data_copy[i];
1538
5.04M
    }
1539
630k
}
1540
1541
template<u8 log2_of_block_size>
1542
inline void Decoder::inverse_asymmetric_discrete_sine_transform_output_array_permutation(Span<Intermediate> data)
1543
1.91M
{
1544
1.91M
    auto block_size = 1u << log2_of_block_size;
1545
1546
    // A temporary array named copyT is set equal to T.
1547
1.91M
    Array<Intermediate, maximum_transform_size> data_copy;
1548
1.91M
    AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size);
1549
1550
    // The permutation depends on n as follows:
1551
1.91M
    if (log2_of_block_size == 4) {
1552
        // − If n is equal to 4,
1553
        // T[ 8*a + 4*b + 2*c + d ] is set equal to copyT[ 8*(d^c) + 4*(c^b) + 2*(b^a) + a ] for a = 0..1
1554
        // and b = 0..1 and c = 0..1 and d = 0..1.
1555
1.89M
        for (auto a = 0u; a < 2; a++)
1556
3.78M
            for (auto b = 0u; b < 2; b++)
1557
7.56M
                for (auto c = 0u; c < 2; c++)
1558
15.1M
                    for (auto d = 0u; d < 2; d++)
1559
10.0M
                        data[(8 * a) + (4 * b) + (2 * c) + d] = data_copy[8 * (d ^ c) + 4 * (c ^ b) + 2 * (b ^ a) + a];
1560
1.28M
    } else {
1561
1.28M
        VERIFY(log2_of_block_size == 3);
1562
        // − Otherwise (n is equal to 3),
1563
        // T[ 4*a + 2*b + c ] is set equal to copyT[ 4*(c^b) + 2*(b^a) + a ] for a = 0..1 and
1564
        // b = 0..1 and c = 0..1.
1565
3.84M
        for (auto a = 0u; a < 2; a++)
1566
7.67M
            for (auto b = 0u; b < 2; b++)
1567
15.3M
                for (auto c = 0u; c < 2; c++)
1568
10.2M
                    data[4 * a + 2 * b + c] = data_copy[4 * (c ^ b) + 2 * (b ^ a) + a];
1569
1.28M
    }
1570
1.91M
}
void Media::Video::VP9::Decoder::inverse_asymmetric_discrete_sine_transform_output_array_permutation<(unsigned char)3>(AK::Span<int>)
Line
Count
Source
1543
1.28M
{
1544
1.28M
    auto block_size = 1u << log2_of_block_size;
1545
1546
    // A temporary array named copyT is set equal to T.
1547
1.28M
    Array<Intermediate, maximum_transform_size> data_copy;
1548
1.28M
    AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size);
1549
1550
    // The permutation depends on n as follows:
1551
1.28M
    if (log2_of_block_size == 4) {
1552
        // − If n is equal to 4,
1553
        // T[ 8*a + 4*b + 2*c + d ] is set equal to copyT[ 8*(d^c) + 4*(c^b) + 2*(b^a) + a ] for a = 0..1
1554
        // and b = 0..1 and c = 0..1 and d = 0..1.
1555
0
        for (auto a = 0u; a < 2; a++)
1556
0
            for (auto b = 0u; b < 2; b++)
1557
0
                for (auto c = 0u; c < 2; c++)
1558
0
                    for (auto d = 0u; d < 2; d++)
1559
0
                        data[(8 * a) + (4 * b) + (2 * c) + d] = data_copy[8 * (d ^ c) + 4 * (c ^ b) + 2 * (b ^ a) + a];
1560
1.28M
    } else {
1561
1.28M
        VERIFY(log2_of_block_size == 3);
1562
        // − Otherwise (n is equal to 3),
1563
        // T[ 4*a + 2*b + c ] is set equal to copyT[ 4*(c^b) + 2*(b^a) + a ] for a = 0..1 and
1564
        // b = 0..1 and c = 0..1.
1565
3.84M
        for (auto a = 0u; a < 2; a++)
1566
7.67M
            for (auto b = 0u; b < 2; b++)
1567
15.3M
                for (auto c = 0u; c < 2; c++)
1568
10.2M
                    data[4 * a + 2 * b + c] = data_copy[4 * (c ^ b) + 2 * (b ^ a) + a];
1569
1.28M
    }
1570
1.28M
}
void Media::Video::VP9::Decoder::inverse_asymmetric_discrete_sine_transform_output_array_permutation<(unsigned char)4>(AK::Span<int>)
Line
Count
Source
1543
630k
{
1544
630k
    auto block_size = 1u << log2_of_block_size;
1545
1546
    // A temporary array named copyT is set equal to T.
1547
630k
    Array<Intermediate, maximum_transform_size> data_copy;
1548
630k
    AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size);
1549
1550
    // The permutation depends on n as follows:
1551
630k
    if (log2_of_block_size == 4) {
1552
        // − If n is equal to 4,
1553
        // T[ 8*a + 4*b + 2*c + d ] is set equal to copyT[ 8*(d^c) + 4*(c^b) + 2*(b^a) + a ] for a = 0..1
1554
        // and b = 0..1 and c = 0..1 and d = 0..1.
1555
1.89M
        for (auto a = 0u; a < 2; a++)
1556
3.78M
            for (auto b = 0u; b < 2; b++)
1557
7.56M
                for (auto c = 0u; c < 2; c++)
1558
15.1M
                    for (auto d = 0u; d < 2; d++)
1559
10.0M
                        data[(8 * a) + (4 * b) + (2 * c) + d] = data_copy[8 * (d ^ c) + 4 * (c ^ b) + 2 * (b ^ a) + a];
1560
18.4E
    } else {
1561
18.4E
        VERIFY(log2_of_block_size == 3);
1562
        // − Otherwise (n is equal to 3),
1563
        // T[ 4*a + 2*b + c ] is set equal to copyT[ 4*(c^b) + 2*(b^a) + a ] for a = 0..1 and
1564
        // b = 0..1 and c = 0..1.
1565
18.4E
        for (auto a = 0u; a < 2; a++)
1566
0
            for (auto b = 0u; b < 2; b++)
1567
0
                for (auto c = 0u; c < 2; c++)
1568
0
                    data[4 * a + 2 * b + c] = data_copy[4 * (c ^ b) + 2 * (b ^ a) + a];
1569
18.4E
    }
1570
630k
}
1571
1572
inline void Decoder::inverse_asymmetric_discrete_sine_transform_4(Span<Intermediate> data)
1573
2.06M
{
1574
2.06M
    VERIFY(data.size() == 4);
1575
2.06M
    i64 const sinpi_1_9 = 5283;
1576
2.06M
    i64 const sinpi_2_9 = 9929;
1577
2.06M
    i64 const sinpi_3_9 = 13377;
1578
2.06M
    i64 const sinpi_4_9 = 15212;
1579
1580
    // Steps are derived from pseudocode in (8.7.1.6):
1581
    // s0 = SINPI_1_9 * T[ 0 ]
1582
2.06M
    i64 s0 = sinpi_1_9 * data[0];
1583
    // s1 = SINPI_2_9 * T[ 0 ]
1584
2.06M
    i64 s1 = sinpi_2_9 * data[0];
1585
    // s2 = SINPI_3_9 * T[ 1 ]
1586
2.06M
    i64 s2 = sinpi_3_9 * data[1];
1587
    // s3 = SINPI_4_9 * T[ 2 ]
1588
2.06M
    i64 s3 = sinpi_4_9 * data[2];
1589
    // s4 = SINPI_1_9 * T[ 2 ]
1590
2.06M
    i64 s4 = sinpi_1_9 * data[2];
1591
    // s5 = SINPI_2_9 * T[ 3 ]
1592
2.06M
    i64 s5 = sinpi_2_9 * data[3];
1593
    // s6 = SINPI_4_9 * T[ 3 ]
1594
2.06M
    i64 s6 = sinpi_4_9 * data[3];
1595
    // v = T[ 0 ] - T[ 2 ] + T[ 3 ]
1596
    // s7 = SINPI_3_9 * v
1597
2.06M
    i64 s7 = sinpi_3_9 * (data[0] - data[2] + data[3]);
1598
1599
    // x0 = s0 + s3 + s5
1600
2.06M
    auto x0 = s0 + s3 + s5;
1601
    // x1 = s1 - s4 - s6
1602
2.06M
    auto x1 = s1 - s4 - s6;
1603
    // x2 = s7
1604
2.06M
    auto x2 = s7;
1605
    // x3 = s2
1606
2.06M
    auto x3 = s2;
1607
1608
    // s0 = x0 + x3
1609
2.06M
    s0 = x0 + x3;
1610
    // s1 = x1 + x3
1611
2.06M
    s1 = x1 + x3;
1612
    // s2 = x2
1613
2.06M
    s2 = x2;
1614
    // s3 = x0 + x1 - x3
1615
2.06M
    s3 = x0 + x1 - x3;
1616
1617
    // T[ 0 ] = Round2( s0, 14 )
1618
2.06M
    data[0] = rounded_right_shift(s0, 14);
1619
    // T[ 1 ] = Round2( s1, 14 )
1620
2.06M
    data[1] = rounded_right_shift(s1, 14);
1621
    // T[ 2 ] = Round2( s2, 14 )
1622
2.06M
    data[2] = rounded_right_shift(s2, 14);
1623
    // T[ 3 ] = Round2( s3, 14 )
1624
2.06M
    data[3] = rounded_right_shift(s3, 14);
1625
1626
    // (8.7.1.1) The inverse asymmetric discrete sine transforms also make use of an intermediate array named S.
1627
    // The values in this array require higher precision to avoid overflow. Using signed integers with 24 +
1628
    // BitDepth bits of precision is enough to avoid overflow.
1629
    // Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal
1630
    // to allow these bounds to be violated. Therefore, we can avoid the performance cost here.
1631
2.06M
}
1632
1633
// The function SB( a, b, angle, 0 ) performs a butterfly rotation.
1634
// Spec defines the source as array T, and the destination array as S.
1635
template<typename S, typename D>
1636
inline void Decoder::butterfly_rotation(Span<S> source, Span<D> destination, size_t index_a, size_t index_b, u8 angle, bool flip)
1637
17.7M
{
1638
    // The function SB( a, b, angle, 0 ) performs a butterfly rotation according to the following ordered steps:
1639
17.7M
    auto cos = cos64(angle);
1640
17.7M
    auto sin = sin64(angle);
1641
    // Expand to the destination buffer's precision.
1642
17.7M
    D a = source[index_a];
1643
17.7M
    D b = source[index_b];
1644
    // 1. S[ a ] is set equal to T[ a ] * cos64( angle ) - T[ b ] * sin64( angle ).
1645
17.7M
    destination[index_a] = a * cos - b * sin;
1646
    // 2. S[ b ] is set equal to T[ a ] * sin64( angle ) + T[ b ] * cos64( angle ).
1647
17.7M
    destination[index_b] = a * sin + b * cos;
1648
1649
    // The function SB( a, b, angle, 1 ) performs a butterfly rotation and flip according to the following ordered steps:
1650
    // 1. The function SB( a, b, angle, 0 ) is invoked.
1651
    // 2. The contents of S[ a ] and S[ b ] are exchanged.
1652
17.7M
    if (flip)
1653
17.7M
        swap(destination[index_a], destination[index_b]);
1654
17.7M
}
1655
1656
// The function SH( a, b ) performs a Hadamard rotation and rounding.
1657
// Spec defines the source array as S, and the destination array as T.
1658
template<typename S, typename D>
1659
inline void Decoder::hadamard_rotation(Span<S> source, Span<D> destination, size_t index_a, size_t index_b)
1660
17.7M
{
1661
    // Keep the source buffer's precision until rounding.
1662
17.7M
    S a = source[index_a];
1663
17.7M
    S b = source[index_b];
1664
    // 1. T[ a ] is set equal to Round2( S[ a ] + S[ b ], 14 ).
1665
17.7M
    destination[index_a] = rounded_right_shift(a + b, 14);
1666
    // 2. T[ b ] is set equal to Round2( S[ a ] - S[ b ], 14 ).
1667
17.7M
    destination[index_b] = rounded_right_shift(a - b, 14);
1668
17.7M
}
1669
1670
inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform_8(Span<Intermediate> data)
1671
1.27M
{
1672
1.27M
    VERIFY(data.size() == 8);
1673
    // This process does an in-place transform of the array T using:
1674
1675
    // A higher precision array S for intermediate results.
1676
    // (8.7.1.1) NOTE - The values in array S require higher precision to avoid overflow. Using signed integers with
1677
    // 24 + BitDepth bits of precision is enough to avoid overflow.
1678
1.27M
    Array<i64, 8> high_precision_temp;
1679
1680
    // The following ordered steps apply:
1681
1682
    // 1. Invoke the ADST input array permutation process specified in section 8.7.1.4 with the input variable n set
1683
    //    equal to 3.
1684
1.27M
    inverse_asymmetric_discrete_sine_transform_input_array_permutation<3>(data);
1685
1686
    // 2. Invoke SB( 2*i, 1+2*i, 30-8*i, 1 ) for i = 0..3.
1687
6.39M
    for (auto i = 0u; i < 4; i++)
1688
5.11M
        butterfly_rotation(data, high_precision_temp.span(), 2 * i, 1 + (2 * i), 30 - (8 * i), true);
1689
1690
    // 3. Invoke SH( i, 4+i ) for i = 0..3.
1691
6.39M
    for (auto i = 0u; i < 4; i++)
1692
5.11M
        hadamard_rotation(high_precision_temp.span(), data, i, 4 + i);
1693
1694
    // 4. Invoke SB( 4+3*i, 5+i, 24-16*i, 1 ) for i = 0..1.
1695
3.83M
    for (auto i = 0u; i < 2; i++)
1696
2.56M
        butterfly_rotation(data, high_precision_temp.span(), 4 + (3 * i), 5 + i, 24 - (16 * i), true);
1697
    // 5. Invoke SH( 4+i, 6+i ) for i = 0..1.
1698
3.83M
    for (auto i = 0u; i < 2; i++)
1699
2.56M
        hadamard_rotation(high_precision_temp.span(), data, 4 + i, 6 + i);
1700
1701
    // 6. Invoke H( i, 2+i, 0 ) for i = 0..1.
1702
3.83M
    for (auto i = 0u; i < 2; i++)
1703
2.56M
        hadamard_rotation_in_place(data, i, 2 + i, false);
1704
1705
    // 7. Invoke B( 2+4*i, 3+4*i, 16, 1 ) for i = 0..1.
1706
3.83M
    for (auto i = 0u; i < 2; i++)
1707
2.56M
        butterfly_rotation_in_place(data, 2 + (4 * i), 3 + (4 * i), 16, true);
1708
1709
    // 8. Invoke the ADST output array permutation process specified in section 8.7.1.5 with the input variable n
1710
    //    set equal to 3.
1711
1.27M
    inverse_asymmetric_discrete_sine_transform_output_array_permutation<3>(data);
1712
1713
    // 9. Set T[ 1+2*i ] equal to -T[ 1+2*i ] for i = 0..3.
1714
6.39M
    for (auto i = 0u; i < 4; i++) {
1715
5.12M
        auto index = 1 + (2 * i);
1716
5.12M
        data[index] = -data[index];
1717
5.12M
    }
1718
1.27M
    return {};
1719
1.27M
}
1720
1721
inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform_16(Span<Intermediate> data)
1722
630k
{
1723
630k
    VERIFY(data.size() == 16);
1724
    // This process does an in-place transform of the array T using:
1725
1726
    // A higher precision array S for intermediate results.
1727
    // (8.7.1.1) The inverse asymmetric discrete sine transforms also make use of an intermediate array named S.
1728
    // The values in this array require higher precision to avoid overflow. Using signed integers with 24 +
1729
    // BitDepth bits of precision is enough to avoid overflow.
1730
630k
    Array<i64, 16> high_precision_temp;
1731
1732
    // The following ordered steps apply:
1733
1734
    // 1. Invoke the ADST input array permutation process specified in section 8.7.1.4 with the input variable n set
1735
    // equal to 4.
1736
630k
    inverse_asymmetric_discrete_sine_transform_input_array_permutation<4>(data);
1737
1738
    // 2. Invoke SB( 2*i, 1+2*i, 31-4*i, 1 ) for i = 0..7.
1739
5.66M
    for (auto i = 0u; i < 8; i++)
1740
5.03M
        butterfly_rotation(data, high_precision_temp.span(), 2 * i, 1 + (2 * i), 31 - (4 * i), true);
1741
    // 3. Invoke SH( i, 8+i ) for i = 0..7.
1742
5.67M
    for (auto i = 0u; i < 8; i++)
1743
5.04M
        hadamard_rotation(high_precision_temp.span(), data, i, 8 + i);
1744
1745
    // 4. Invoke SB( 8+2*i, 9+2*i, 28-16*i, 1 ) for i = 0..3.
1746
3.15M
    for (auto i = 0u; i < 4; i++)
1747
2.52M
        butterfly_rotation(data, high_precision_temp.span(), 8 + (2 * i), 9 + (2 * i), 128 + 28 - (16 * i), true);
1748
    // 5. Invoke SH( 8+i, 12+i ) for i = 0..3.
1749
3.15M
    for (auto i = 0u; i < 4; i++)
1750
2.52M
        hadamard_rotation(high_precision_temp.span(), data, 8 + i, 12 + i);
1751
1752
    // 6. Invoke H( i, 4+i, 0 ) for i = 0..3.
1753
3.15M
    for (auto i = 0u; i < 4; i++)
1754
2.52M
        hadamard_rotation_in_place(data, i, 4 + i, false);
1755
1756
    // 7. Invoke SB( 4+8*i+3*j, 5+8*i+j, 24-16*j, 1 ) for i = 0..1, for j = 0..1.
1757
1.89M
    for (auto i = 0u; i < 2; i++)
1758
3.78M
        for (auto j = 0u; j < 2; j++)
1759
2.52M
            butterfly_rotation(data, high_precision_temp.span(), 4 + (8 * i) + (3 * j), 5 + (8 * i) + j, 24 - (16 * j), true);
1760
    // 8. Invoke SH( 4+8*j+i, 6+8*j+i ) for i = 0..1, j = 0..1.
1761
1.89M
    for (auto i = 0u; i < 2; i++)
1762
3.78M
        for (auto j = 0u; j < 2; j++)
1763
2.52M
            hadamard_rotation(high_precision_temp.span(), data, 4 + (8 * j) + i, 6 + (8 * j) + i);
1764
1765
    // 9. Invoke H( 8*j+i, 2+8*j+i, 0 ) for i = 0..1, for j = 0..1.
1766
1.89M
    for (auto i = 0u; i < 2; i++)
1767
3.78M
        for (auto j = 0u; j < 2; j++)
1768
2.52M
            hadamard_rotation_in_place(data, (8 * j) + i, 2 + (8 * j) + i, false);
1769
    // 10. Invoke B( 2+4*j+8*i, 3+4*j+8*i, 48+64*(i^j), 0 ) for i = 0..1, for j = 0..1.
1770
1.89M
    for (auto i = 0u; i < 2; i++)
1771
3.78M
        for (auto j = 0u; j < 2; j++)
1772
2.52M
            butterfly_rotation_in_place(data, 2 + (4 * j) + (8 * i), 3 + (4 * j) + (8 * i), 48 + (64 * (i ^ j)), false);
1773
1774
    // 11. Invoke the ADST output array permutation process specified in section 8.7.1.5 with the input variable n
1775
    // set equal to 4.
1776
630k
    inverse_asymmetric_discrete_sine_transform_output_array_permutation<4>(data);
1777
1778
    // 12. Set T[ 1+12*j+2*i ] equal to -T[ 1+12*j+2*i ] for i = 0..1, for j = 0..1.
1779
1.89M
    for (auto i = 0u; i < 2; i++) {
1780
3.78M
        for (auto j = 0u; j < 2; j++) {
1781
2.52M
            auto index = 1 + (12 * j) + (2 * i);
1782
2.52M
            data[index] = -data[index];
1783
2.52M
        }
1784
1.26M
    }
1785
630k
    return {};
1786
630k
}
1787
1788
template<u8 log2_of_block_size>
1789
inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform(Span<Intermediate> data)
1790
3.97M
{
1791
    // 8.7.1.9 Inverse ADST Process
1792
1793
    // This process performs an in-place inverse ADST process on the array T of size 2^n for 2 ≤ n ≤ 4.
1794
    if constexpr (log2_of_block_size < 2 || log2_of_block_size > 4)
1795
0
        return DecoderError::corrupted("Block size was out of range"sv);
1796
1797
    // The process to invoke depends on n as follows:
1798
2.06M
    if constexpr (log2_of_block_size == 2) {
1799
        // − If n is equal to 2, invoke the Inverse ADST4 process specified in section 8.7.1.6.
1800
2.06M
        inverse_asymmetric_discrete_sine_transform_4(data);
1801
2.06M
        return {};
1802
2.06M
    }
1803
1.27M
    if constexpr (log2_of_block_size == 3) {
1804
        // − Otherwise if n is equal to 3, invoke the Inverse ADST8 process specified in section 8.7.1.7.
1805
1.27M
        return inverse_asymmetric_discrete_sine_transform_8(data);
1806
1.27M
    }
1807
    // − Otherwise (n is equal to 4), invoke the Inverse ADST16 process specified in section 8.7.1.8.
1808
0
    return inverse_asymmetric_discrete_sine_transform_16(data);
1809
3.97M
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_asymmetric_discrete_sine_transform<(unsigned char)2>(AK::Span<int>)
Line
Count
Source
1790
2.06M
{
1791
    // 8.7.1.9 Inverse ADST Process
1792
1793
    // This process performs an in-place inverse ADST process on the array T of size 2^n for 2 ≤ n ≤ 4.
1794
    if constexpr (log2_of_block_size < 2 || log2_of_block_size > 4)
1795
        return DecoderError::corrupted("Block size was out of range"sv);
1796
1797
    // The process to invoke depends on n as follows:
1798
2.06M
    if constexpr (log2_of_block_size == 2) {
1799
        // − If n is equal to 2, invoke the Inverse ADST4 process specified in section 8.7.1.6.
1800
2.06M
        inverse_asymmetric_discrete_sine_transform_4(data);
1801
2.06M
        return {};
1802
2.06M
    }
1803
    if constexpr (log2_of_block_size == 3) {
1804
        // − Otherwise if n is equal to 3, invoke the Inverse ADST8 process specified in section 8.7.1.7.
1805
        return inverse_asymmetric_discrete_sine_transform_8(data);
1806
    }
1807
    // − Otherwise (n is equal to 4), invoke the Inverse ADST16 process specified in section 8.7.1.8.
1808
2.06M
    return inverse_asymmetric_discrete_sine_transform_16(data);
1809
2.06M
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_asymmetric_discrete_sine_transform<(unsigned char)3>(AK::Span<int>)
Line
Count
Source
1790
1.27M
{
1791
    // 8.7.1.9 Inverse ADST Process
1792
1793
    // This process performs an in-place inverse ADST process on the array T of size 2^n for 2 ≤ n ≤ 4.
1794
    if constexpr (log2_of_block_size < 2 || log2_of_block_size > 4)
1795
        return DecoderError::corrupted("Block size was out of range"sv);
1796
1797
    // The process to invoke depends on n as follows:
1798
    if constexpr (log2_of_block_size == 2) {
1799
        // − If n is equal to 2, invoke the Inverse ADST4 process specified in section 8.7.1.6.
1800
        inverse_asymmetric_discrete_sine_transform_4(data);
1801
        return {};
1802
    }
1803
1.27M
    if constexpr (log2_of_block_size == 3) {
1804
        // − Otherwise if n is equal to 3, invoke the Inverse ADST8 process specified in section 8.7.1.7.
1805
1.27M
        return inverse_asymmetric_discrete_sine_transform_8(data);
1806
1.27M
    }
1807
    // − Otherwise (n is equal to 4), invoke the Inverse ADST16 process specified in section 8.7.1.8.
1808
0
    return inverse_asymmetric_discrete_sine_transform_16(data);
1809
1.27M
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_asymmetric_discrete_sine_transform<(unsigned char)4>(AK::Span<int>)
Line
Count
Source
1790
630k
{
1791
    // 8.7.1.9 Inverse ADST Process
1792
1793
    // This process performs an in-place inverse ADST process on the array T of size 2^n for 2 ≤ n ≤ 4.
1794
    if constexpr (log2_of_block_size < 2 || log2_of_block_size > 4)
1795
        return DecoderError::corrupted("Block size was out of range"sv);
1796
1797
    // The process to invoke depends on n as follows:
1798
    if constexpr (log2_of_block_size == 2) {
1799
        // − If n is equal to 2, invoke the Inverse ADST4 process specified in section 8.7.1.6.
1800
        inverse_asymmetric_discrete_sine_transform_4(data);
1801
        return {};
1802
    }
1803
    if constexpr (log2_of_block_size == 3) {
1804
        // − Otherwise if n is equal to 3, invoke the Inverse ADST8 process specified in section 8.7.1.7.
1805
        return inverse_asymmetric_discrete_sine_transform_8(data);
1806
    }
1807
    // − Otherwise (n is equal to 4), invoke the Inverse ADST16 process specified in section 8.7.1.8.
1808
630k
    return inverse_asymmetric_discrete_sine_transform_16(data);
1809
630k
}
Unexecuted instantiation: AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_asymmetric_discrete_sine_transform<(unsigned char)5>(AK::Span<int>)
1810
1811
template<u8 log2_of_block_size>
1812
ALWAYS_INLINE DecoderErrorOr<void> Decoder::inverse_transform_2d(BlockContext const& block_context, Span<Intermediate> dequantized, TransformSet transform_set)
1813
8.55M
{
1814
8.55M
    static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5);
1815
1816
    // This process performs a 2D inverse transform for an array of size 2^n by 2^n stored in the 2D array Dequant.
1817
    // The input to this process is a variable n (log2_of_block_size) that specifies the base 2 logarithm of the width of the transform.
1818
1819
    // 1. Set the variable n0 (block_size) equal to 1 << n.
1820
8.55M
    constexpr auto block_size = 1u << log2_of_block_size;
1821
1822
8.55M
    Array<Intermediate, block_size * block_size> row_array;
1823
8.55M
    Span<Intermediate> row = row_array.span().trim(block_size);
1824
1825
    // 2. The row transforms with i = 0..(n0-1) are applied as follows:
1826
59.5M
    for (auto i = 0u; i < block_size; i++) {
1827
        // 1. Set T[ j ] equal to Dequant[ i ][ j ] for j = 0..(n0-1).
1828
662M
        for (auto j = 0u; j < block_size; j++)
1829
611M
            row[j] = dequantized[i * block_size + j];
1830
1831
        // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal
1832
        //    to 2.
1833
50.9M
        if (block_context.frame_context.lossless) {
1834
3.62M
            TRY(inverse_walsh_hadamard_transform(row, log2_of_block_size, 2));
1835
47.3M
        } else {
1836
47.3M
            switch (transform_set.second_transform) {
1837
45.0M
            case TransformType::DCT:
1838
                // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to ADST_DCT, apply an inverse DCT as
1839
                // follows:
1840
                // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n.
1841
45.0M
                TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(row));
1842
                // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n.
1843
45.0M
                TRY(inverse_discrete_cosine_transform<log2_of_block_size>(row));
1844
45.0M
                break;
1845
2.30M
            case TransformType::ADST:
1846
                // 4. Otherwise (TxType is equal to DCT_ADST or TxType is equal to ADST_ADST), invoke the inverse ADST
1847
                //    process as specified in section 8.7.1.9 with input variable n.
1848
2.30M
                TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(row));
1849
2.30M
                break;
1850
0
            default:
1851
0
                return DecoderError::corrupted("Unknown tx_type"sv);
1852
47.3M
            }
1853
47.3M
        }
1854
1855
        // 5. Set Dequant[ i ][ j ] equal to T[ j ] for j = 0..(n0-1).
1856
662M
        for (auto j = 0u; j < block_size; j++)
1857
611M
            dequantized[i * block_size + j] = row[j];
1858
51.0M
    }
1859
1860
8.61M
    Array<Intermediate, block_size * block_size> column_array;
1861
8.61M
    auto column = column_array.span().trim(block_size);
1862
1863
    // 3. The column transforms with j = 0..(n0-1) are applied as follows:
1864
59.6M
    for (auto j = 0u; j < block_size; j++) {
1865
        // 1. Set T[ i ] equal to Dequant[ i ][ j ] for i = 0..(n0-1).
1866
661M
        for (auto i = 0u; i < block_size; i++)
1867
610M
            column[i] = dequantized[i * block_size + j];
1868
1869
        // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal
1870
        //    to 0.
1871
50.9M
        if (block_context.frame_context.lossless) {
1872
3.62M
            TRY(inverse_walsh_hadamard_transform(column, log2_of_block_size, 0));
1873
47.3M
        } else {
1874
47.3M
            switch (transform_set.first_transform) {
1875
45.6M
            case TransformType::DCT:
1876
                // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to DCT_ADST, apply an inverse DCT as
1877
                // follows:
1878
                // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n.
1879
45.6M
                TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(column));
1880
                // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n.
1881
45.6M
                TRY(inverse_discrete_cosine_transform<log2_of_block_size>(column));
1882
45.6M
                break;
1883
1.67M
            case TransformType::ADST:
1884
                // 4. Otherwise (TxType is equal to ADST_DCT or TxType is equal to ADST_ADST), invoke the inverse ADST
1885
                //    process as specified in section 8.7.1.9 with input variable n.
1886
1.67M
                TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(column));
1887
1.67M
                break;
1888
0
            default:
1889
0
                VERIFY_NOT_REACHED();
1890
47.3M
            }
1891
47.3M
        }
1892
1893
        // 5. If Lossless is equal to 1, set Dequant[ i ][ j ] equal to T[ i ] for i = 0..(n0-1).
1894
662M
        for (auto i = 0u; i < block_size; i++)
1895
611M
            dequantized[i * block_size + j] = column[i];
1896
1897
        // 6. Otherwise (Lossless is equal to 0), set Dequant[ i ][ j ] equal to Round2( T[ i ], Min( 6, n + 2 ) )
1898
        //    for i = 0..(n0-1).
1899
51.0M
        if (!block_context.frame_context.lossless) {
1900
643M
            for (auto i = 0u; i < block_size; i++) {
1901
596M
                auto index = i * block_size + j;
1902
596M
                dequantized[index] = rounded_right_shift(dequantized[index], min(6, log2_of_block_size + 2));
1903
596M
            }
1904
47.3M
        }
1905
51.0M
    }
1906
1907
8.70M
    return {};
1908
8.61M
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_transform_2d<(unsigned char)2>(Media::Video::VP9::BlockContext const&, AK::Span<int>, Media::Video::VP9::TransformSet)
Line
Count
Source
1813
6.98M
{
1814
6.98M
    static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5);
1815
1816
    // This process performs a 2D inverse transform for an array of size 2^n by 2^n stored in the 2D array Dequant.
1817
    // The input to this process is a variable n (log2_of_block_size) that specifies the base 2 logarithm of the width of the transform.
1818
1819
    // 1. Set the variable n0 (block_size) equal to 1 << n.
1820
6.98M
    constexpr auto block_size = 1u << log2_of_block_size;
1821
1822
6.98M
    Array<Intermediate, block_size * block_size> row_array;
1823
6.98M
    Span<Intermediate> row = row_array.span().trim(block_size);
1824
1825
    // 2. The row transforms with i = 0..(n0-1) are applied as follows:
1826
34.9M
    for (auto i = 0u; i < block_size; i++) {
1827
        // 1. Set T[ j ] equal to Dequant[ i ][ j ] for j = 0..(n0-1).
1828
139M
        for (auto j = 0u; j < block_size; j++)
1829
111M
            row[j] = dequantized[i * block_size + j];
1830
1831
        // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal
1832
        //    to 2.
1833
27.8M
        if (block_context.frame_context.lossless) {
1834
3.62M
            TRY(inverse_walsh_hadamard_transform(row, log2_of_block_size, 2));
1835
24.2M
        } else {
1836
24.2M
            switch (transform_set.second_transform) {
1837
23.0M
            case TransformType::DCT:
1838
                // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to ADST_DCT, apply an inverse DCT as
1839
                // follows:
1840
                // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n.
1841
23.0M
                TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(row));
1842
                // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n.
1843
23.0M
                TRY(inverse_discrete_cosine_transform<log2_of_block_size>(row));
1844
23.0M
                break;
1845
1.19M
            case TransformType::ADST:
1846
                // 4. Otherwise (TxType is equal to DCT_ADST or TxType is equal to ADST_ADST), invoke the inverse ADST
1847
                //    process as specified in section 8.7.1.9 with input variable n.
1848
1.19M
                TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(row));
1849
1.19M
                break;
1850
0
            default:
1851
0
                return DecoderError::corrupted("Unknown tx_type"sv);
1852
24.2M
            }
1853
24.2M
        }
1854
1855
        // 5. Set Dequant[ i ][ j ] equal to T[ j ] for j = 0..(n0-1).
1856
139M
        for (auto j = 0u; j < block_size; j++)
1857
111M
            dequantized[i * block_size + j] = row[j];
1858
27.9M
    }
1859
1860
7.03M
    Array<Intermediate, block_size * block_size> column_array;
1861
7.03M
    auto column = column_array.span().trim(block_size);
1862
1863
    // 3. The column transforms with j = 0..(n0-1) are applied as follows:
1864
34.9M
    for (auto j = 0u; j < block_size; j++) {
1865
        // 1. Set T[ i ] equal to Dequant[ i ][ j ] for i = 0..(n0-1).
1866
139M
        for (auto i = 0u; i < block_size; i++)
1867
111M
            column[i] = dequantized[i * block_size + j];
1868
1869
        // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal
1870
        //    to 0.
1871
27.8M
        if (block_context.frame_context.lossless) {
1872
3.62M
            TRY(inverse_walsh_hadamard_transform(column, log2_of_block_size, 0));
1873
24.2M
        } else {
1874
24.2M
            switch (transform_set.first_transform) {
1875
23.3M
            case TransformType::DCT:
1876
                // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to DCT_ADST, apply an inverse DCT as
1877
                // follows:
1878
                // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n.
1879
23.3M
                TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(column));
1880
                // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n.
1881
23.3M
                TRY(inverse_discrete_cosine_transform<log2_of_block_size>(column));
1882
23.3M
                break;
1883
872k
            case TransformType::ADST:
1884
                // 4. Otherwise (TxType is equal to ADST_DCT or TxType is equal to ADST_ADST), invoke the inverse ADST
1885
                //    process as specified in section 8.7.1.9 with input variable n.
1886
872k
                TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(column));
1887
872k
                break;
1888
0
            default:
1889
0
                VERIFY_NOT_REACHED();
1890
24.2M
            }
1891
24.2M
        }
1892
1893
        // 5. If Lossless is equal to 1, set Dequant[ i ][ j ] equal to T[ i ] for i = 0..(n0-1).
1894
139M
        for (auto i = 0u; i < block_size; i++)
1895
111M
            dequantized[i * block_size + j] = column[i];
1896
1897
        // 6. Otherwise (Lossless is equal to 0), set Dequant[ i ][ j ] equal to Round2( T[ i ], Min( 6, n + 2 ) )
1898
        //    for i = 0..(n0-1).
1899
27.9M
        if (!block_context.frame_context.lossless) {
1900
121M
            for (auto i = 0u; i < block_size; i++) {
1901
97.0M
                auto index = i * block_size + j;
1902
97.0M
                dequantized[index] = rounded_right_shift(dequantized[index], min(6, log2_of_block_size + 2));
1903
97.0M
            }
1904
24.2M
        }
1905
27.9M
    }
1906
1907
7.10M
    return {};
1908
7.03M
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_transform_2d<(unsigned char)3>(Media::Video::VP9::BlockContext const&, AK::Span<int>, Media::Video::VP9::TransformSet)
Line
Count
Source
1813
1.01M
{
1814
1.01M
    static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5);
1815
1816
    // This process performs a 2D inverse transform for an array of size 2^n by 2^n stored in the 2D array Dequant.
1817
    // The input to this process is a variable n (log2_of_block_size) that specifies the base 2 logarithm of the width of the transform.
1818
1819
    // 1. Set the variable n0 (block_size) equal to 1 << n.
1820
1.01M
    constexpr auto block_size = 1u << log2_of_block_size;
1821
1822
1.01M
    Array<Intermediate, block_size * block_size> row_array;
1823
1.01M
    Span<Intermediate> row = row_array.span().trim(block_size);
1824
1825
    // 2. The row transforms with i = 0..(n0-1) are applied as follows:
1826
9.15M
    for (auto i = 0u; i < block_size; i++) {
1827
        // 1. Set T[ j ] equal to Dequant[ i ][ j ] for j = 0..(n0-1).
1828
73.2M
        for (auto j = 0u; j < block_size; j++)
1829
65.1M
            row[j] = dequantized[i * block_size + j];
1830
1831
        // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal
1832
        //    to 2.
1833
8.13M
        if (block_context.frame_context.lossless) {
1834
0
            TRY(inverse_walsh_hadamard_transform(row, log2_of_block_size, 2));
1835
8.13M
        } else {
1836
8.13M
            switch (transform_set.second_transform) {
1837
7.39M
            case TransformType::DCT:
1838
                // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to ADST_DCT, apply an inverse DCT as
1839
                // follows:
1840
                // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n.
1841
7.39M
                TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(row));
1842
                // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n.
1843
7.39M
                TRY(inverse_discrete_cosine_transform<log2_of_block_size>(row));
1844
7.39M
                break;
1845
742k
            case TransformType::ADST:
1846
                // 4. Otherwise (TxType is equal to DCT_ADST or TxType is equal to ADST_ADST), invoke the inverse ADST
1847
                //    process as specified in section 8.7.1.9 with input variable n.
1848
742k
                TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(row));
1849
742k
                break;
1850
0
            default:
1851
0
                return DecoderError::corrupted("Unknown tx_type"sv);
1852
8.13M
            }
1853
8.13M
        }
1854
1855
        // 5. Set Dequant[ i ][ j ] equal to T[ j ] for j = 0..(n0-1).
1856
73.2M
        for (auto j = 0u; j < block_size; j++)
1857
65.1M
            dequantized[i * block_size + j] = row[j];
1858
8.13M
    }
1859
1860
1.01M
    Array<Intermediate, block_size * block_size> column_array;
1861
1.01M
    auto column = column_array.span().trim(block_size);
1862
1863
    // 3. The column transforms with j = 0..(n0-1) are applied as follows:
1864
9.15M
    for (auto j = 0u; j < block_size; j++) {
1865
        // 1. Set T[ i ] equal to Dequant[ i ][ j ] for i = 0..(n0-1).
1866
73.2M
        for (auto i = 0u; i < block_size; i++)
1867
65.1M
            column[i] = dequantized[i * block_size + j];
1868
1869
        // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal
1870
        //    to 0.
1871
8.13M
        if (block_context.frame_context.lossless) {
1872
0
            TRY(inverse_walsh_hadamard_transform(column, log2_of_block_size, 0));
1873
8.13M
        } else {
1874
8.13M
            switch (transform_set.first_transform) {
1875
7.60M
            case TransformType::DCT:
1876
                // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to DCT_ADST, apply an inverse DCT as
1877
                // follows:
1878
                // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n.
1879
7.60M
                TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(column));
1880
                // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n.
1881
7.60M
                TRY(inverse_discrete_cosine_transform<log2_of_block_size>(column));
1882
7.60M
                break;
1883
537k
            case TransformType::ADST:
1884
                // 4. Otherwise (TxType is equal to ADST_DCT or TxType is equal to ADST_ADST), invoke the inverse ADST
1885
                //    process as specified in section 8.7.1.9 with input variable n.
1886
537k
                TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(column));
1887
537k
                break;
1888
0
            default:
1889
0
                VERIFY_NOT_REACHED();
1890
8.13M
            }
1891
8.13M
        }
1892
1893
        // 5. If Lossless is equal to 1, set Dequant[ i ][ j ] equal to T[ i ] for i = 0..(n0-1).
1894
73.2M
        for (auto i = 0u; i < block_size; i++)
1895
65.1M
            dequantized[i * block_size + j] = column[i];
1896
1897
        // 6. Otherwise (Lossless is equal to 0), set Dequant[ i ][ j ] equal to Round2( T[ i ], Min( 6, n + 2 ) )
1898
        //    for i = 0..(n0-1).
1899
8.13M
        if (!block_context.frame_context.lossless) {
1900
73.2M
            for (auto i = 0u; i < block_size; i++) {
1901
65.1M
                auto index = i * block_size + j;
1902
65.1M
                dequantized[index] = rounded_right_shift(dequantized[index], min(6, log2_of_block_size + 2));
1903
65.1M
            }
1904
8.13M
        }
1905
8.13M
    }
1906
1907
1.01M
    return {};
1908
1.01M
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_transform_2d<(unsigned char)4>(Media::Video::VP9::BlockContext const&, AK::Span<int>, Media::Video::VP9::TransformSet)
Line
Count
Source
1813
170k
{
1814
170k
    static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5);
1815
1816
    // This process performs a 2D inverse transform for an array of size 2^n by 2^n stored in the 2D array Dequant.
1817
    // The input to this process is a variable n (log2_of_block_size) that specifies the base 2 logarithm of the width of the transform.
1818
1819
    // 1. Set the variable n0 (block_size) equal to 1 << n.
1820
170k
    constexpr auto block_size = 1u << log2_of_block_size;
1821
1822
170k
    Array<Intermediate, block_size * block_size> row_array;
1823
170k
    Span<Intermediate> row = row_array.span().trim(block_size);
1824
1825
    // 2. The row transforms with i = 0..(n0-1) are applied as follows:
1826
2.89M
    for (auto i = 0u; i < block_size; i++) {
1827
        // 1. Set T[ j ] equal to Dequant[ i ][ j ] for j = 0..(n0-1).
1828
46.3M
        for (auto j = 0u; j < block_size; j++)
1829
43.6M
            row[j] = dequantized[i * block_size + j];
1830
1831
        // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal
1832
        //    to 2.
1833
2.72M
        if (block_context.frame_context.lossless) {
1834
0
            TRY(inverse_walsh_hadamard_transform(row, log2_of_block_size, 2));
1835
2.72M
        } else {
1836
2.72M
            switch (transform_set.second_transform) {
1837
2.35M
            case TransformType::DCT:
1838
                // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to ADST_DCT, apply an inverse DCT as
1839
                // follows:
1840
                // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n.
1841
2.35M
                TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(row));
1842
                // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n.
1843
2.35M
                TRY(inverse_discrete_cosine_transform<log2_of_block_size>(row));
1844
2.35M
                break;
1845
368k
            case TransformType::ADST:
1846
                // 4. Otherwise (TxType is equal to DCT_ADST or TxType is equal to ADST_ADST), invoke the inverse ADST
1847
                //    process as specified in section 8.7.1.9 with input variable n.
1848
368k
                TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(row));
1849
368k
                break;
1850
0
            default:
1851
0
                return DecoderError::corrupted("Unknown tx_type"sv);
1852
2.72M
            }
1853
2.72M
        }
1854
1855
        // 5. Set Dequant[ i ][ j ] equal to T[ j ] for j = 0..(n0-1).
1856
46.3M
        for (auto j = 0u; j < block_size; j++)
1857
43.6M
            dequantized[i * block_size + j] = row[j];
1858
2.72M
    }
1859
1860
170k
    Array<Intermediate, block_size * block_size> column_array;
1861
170k
    auto column = column_array.span().trim(block_size);
1862
1863
    // 3. The column transforms with j = 0..(n0-1) are applied as follows:
1864
2.89M
    for (auto j = 0u; j < block_size; j++) {
1865
        // 1. Set T[ i ] equal to Dequant[ i ][ j ] for i = 0..(n0-1).
1866
46.3M
        for (auto i = 0u; i < block_size; i++)
1867
43.6M
            column[i] = dequantized[i * block_size + j];
1868
1869
        // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal
1870
        //    to 0.
1871
2.72M
        if (block_context.frame_context.lossless) {
1872
0
            TRY(inverse_walsh_hadamard_transform(column, log2_of_block_size, 0));
1873
2.72M
        } else {
1874
2.72M
            switch (transform_set.first_transform) {
1875
2.46M
            case TransformType::DCT:
1876
                // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to DCT_ADST, apply an inverse DCT as
1877
                // follows:
1878
                // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n.
1879
2.46M
                TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(column));
1880
                // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n.
1881
2.46M
                TRY(inverse_discrete_cosine_transform<log2_of_block_size>(column));
1882
2.46M
                break;
1883
262k
            case TransformType::ADST:
1884
                // 4. Otherwise (TxType is equal to ADST_DCT or TxType is equal to ADST_ADST), invoke the inverse ADST
1885
                //    process as specified in section 8.7.1.9 with input variable n.
1886
262k
                TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(column));
1887
262k
                break;
1888
0
            default:
1889
0
                VERIFY_NOT_REACHED();
1890
2.72M
            }
1891
2.72M
        }
1892
1893
        // 5. If Lossless is equal to 1, set Dequant[ i ][ j ] equal to T[ i ] for i = 0..(n0-1).
1894
46.3M
        for (auto i = 0u; i < block_size; i++)
1895
43.6M
            dequantized[i * block_size + j] = column[i];
1896
1897
        // 6. Otherwise (Lossless is equal to 0), set Dequant[ i ][ j ] equal to Round2( T[ i ], Min( 6, n + 2 ) )
1898
        //    for i = 0..(n0-1).
1899
2.72M
        if (!block_context.frame_context.lossless) {
1900
46.3M
            for (auto i = 0u; i < block_size; i++) {
1901
43.6M
                auto index = i * block_size + j;
1902
43.6M
                dequantized[index] = rounded_right_shift(dequantized[index], min(6, log2_of_block_size + 2));
1903
43.6M
            }
1904
2.72M
        }
1905
2.72M
    }
1906
1907
170k
    return {};
1908
170k
}
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_transform_2d<(unsigned char)5>(Media::Video::VP9::BlockContext const&, AK::Span<int>, Media::Video::VP9::TransformSet)
Line
Count
Source
1813
382k
{
1814
382k
    static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5);
1815
1816
    // This process performs a 2D inverse transform for an array of size 2^n by 2^n stored in the 2D array Dequant.
1817
    // The input to this process is a variable n (log2_of_block_size) that specifies the base 2 logarithm of the width of the transform.
1818
1819
    // 1. Set the variable n0 (block_size) equal to 1 << n.
1820
382k
    constexpr auto block_size = 1u << log2_of_block_size;
1821
1822
382k
    Array<Intermediate, block_size * block_size> row_array;
1823
382k
    Span<Intermediate> row = row_array.span().trim(block_size);
1824
1825
    // 2. The row transforms with i = 0..(n0-1) are applied as follows:
1826
12.6M
    for (auto i = 0u; i < block_size; i++) {
1827
        // 1. Set T[ j ] equal to Dequant[ i ][ j ] for j = 0..(n0-1).
1828
403M
        for (auto j = 0u; j < block_size; j++)
1829
390M
            row[j] = dequantized[i * block_size + j];
1830
1831
        // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal
1832
        //    to 2.
1833
12.2M
        if (block_context.frame_context.lossless) {
1834
0
            TRY(inverse_walsh_hadamard_transform(row, log2_of_block_size, 2));
1835
12.2M
        } else {
1836
12.2M
            switch (transform_set.second_transform) {
1837
12.2M
            case TransformType::DCT:
1838
                // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to ADST_DCT, apply an inverse DCT as
1839
                // follows:
1840
                // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n.
1841
12.2M
                TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(row));
1842
                // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n.
1843
12.2M
                TRY(inverse_discrete_cosine_transform<log2_of_block_size>(row));
1844
12.2M
                break;
1845
0
            case TransformType::ADST:
1846
                // 4. Otherwise (TxType is equal to DCT_ADST or TxType is equal to ADST_ADST), invoke the inverse ADST
1847
                //    process as specified in section 8.7.1.9 with input variable n.
1848
0
                TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(row));
1849
0
                break;
1850
0
            default:
1851
0
                return DecoderError::corrupted("Unknown tx_type"sv);
1852
12.2M
            }
1853
12.2M
        }
1854
1855
        // 5. Set Dequant[ i ][ j ] equal to T[ j ] for j = 0..(n0-1).
1856
403M
        for (auto j = 0u; j < block_size; j++)
1857
390M
            dequantized[i * block_size + j] = row[j];
1858
12.2M
    }
1859
1860
389k
    Array<Intermediate, block_size * block_size> column_array;
1861
389k
    auto column = column_array.span().trim(block_size);
1862
1863
    // 3. The column transforms with j = 0..(n0-1) are applied as follows:
1864
12.6M
    for (auto j = 0u; j < block_size; j++) {
1865
        // 1. Set T[ i ] equal to Dequant[ i ][ j ] for i = 0..(n0-1).
1866
402M
        for (auto i = 0u; i < block_size; i++)
1867
390M
            column[i] = dequantized[i * block_size + j];
1868
1869
        // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal
1870
        //    to 0.
1871
12.1M
        if (block_context.frame_context.lossless) {
1872
0
            TRY(inverse_walsh_hadamard_transform(column, log2_of_block_size, 0));
1873
12.1M
        } else {
1874
12.1M
            switch (transform_set.first_transform) {
1875
12.2M
            case TransformType::DCT:
1876
                // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to DCT_ADST, apply an inverse DCT as
1877
                // follows:
1878
                // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n.
1879
12.2M
                TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(column));
1880
                // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n.
1881
12.2M
                TRY(inverse_discrete_cosine_transform<log2_of_block_size>(column));
1882
12.2M
                break;
1883
0
            case TransformType::ADST:
1884
                // 4. Otherwise (TxType is equal to ADST_DCT or TxType is equal to ADST_ADST), invoke the inverse ADST
1885
                //    process as specified in section 8.7.1.9 with input variable n.
1886
0
                TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(column));
1887
0
                break;
1888
0
            default:
1889
0
                VERIFY_NOT_REACHED();
1890
12.1M
            }
1891
12.1M
        }
1892
1893
        // 5. If Lossless is equal to 1, set Dequant[ i ][ j ] equal to T[ i ] for i = 0..(n0-1).
1894
402M
        for (auto i = 0u; i < block_size; i++)
1895
390M
            dequantized[i * block_size + j] = column[i];
1896
1897
        // 6. Otherwise (Lossless is equal to 0), set Dequant[ i ][ j ] equal to Round2( T[ i ], Min( 6, n + 2 ) )
1898
        //    for i = 0..(n0-1).
1899
12.2M
        if (!block_context.frame_context.lossless) {
1900
402M
            for (auto i = 0u; i < block_size; i++) {
1901
390M
                auto index = i * block_size + j;
1902
390M
                dequantized[index] = rounded_right_shift(dequantized[index], min(6, log2_of_block_size + 2));
1903
390M
            }
1904
12.2M
        }
1905
12.2M
    }
1906
1907
409k
    return {};
1908
389k
}
1909
1910
DecoderErrorOr<void> Decoder::update_reference_frames(FrameContext const& frame_context)
1911
1.80k
{
1912
    // This process is invoked as the final step in decoding a frame.
1913
    // The inputs to this process are the samples in the current frame CurrFrame[ plane ][ x ][ y ].
1914
    // The output from this process is an updated set of reference frames and previous motion vectors.
1915
    // The following ordered steps apply:
1916
1917
    // 1. For each value of i from 0 to NUM_REF_FRAMES - 1, the following applies if bit i of refresh_frame_flags
1918
    // is equal to 1 (i.e. if (refresh_frame_flags>>i)&1 is equal to 1):
1919
16.2k
    for (u8 i = 0; i < NUM_REF_FRAMES; i++) {
1920
14.4k
        if (frame_context.should_update_reference_frame_at_index(i)) {
1921
7.45k
            auto& reference_frame = m_parser->m_reference_frames[i];
1922
1923
            // − RefFrameWidth[ i ] is set equal to FrameWidth.
1924
            // − RefFrameHeight[ i ] is set equal to FrameHeight.
1925
7.45k
            reference_frame.size = frame_context.size();
1926
            // − RefSubsamplingX[ i ] is set equal to subsampling_x.
1927
7.45k
            reference_frame.subsampling_x = frame_context.color_config.subsampling_x;
1928
            // − RefSubsamplingY[ i ] is set equal to subsampling_y.
1929
7.45k
            reference_frame.subsampling_y = frame_context.color_config.subsampling_y;
1930
            // − RefBitDepth[ i ] is set equal to BitDepth.
1931
7.45k
            reference_frame.bit_depth = frame_context.color_config.bit_depth;
1932
1933
            // − FrameStore[ i ][ 0 ][ y ][ x ] is set equal to CurrFrame[ 0 ][ y ][ x ] for x = 0..FrameWidth-1, for y =
1934
            // 0..FrameHeight-1.
1935
            // − FrameStore[ i ][ plane ][ y ][ x ] is set equal to CurrFrame[ plane ][ y ][ x ] for plane = 1..2, for x =
1936
            // 0..((FrameWidth+subsampling_x) >> subsampling_x)-1, for y = 0..((FrameHeight+subsampling_y) >>
1937
            // subsampling_y)-1.
1938
1939
            // FIXME: Frame width is not equal to the buffer's stride. If we store the stride of the buffer with the reference
1940
            //        frame, we can just copy the framebuffer data instead. Alternatively, we should crop the output framebuffer.
1941
29.8k
            for (auto plane = 0u; plane < 3; plane++) {
1942
22.3k
                auto width = frame_context.size().width();
1943
22.3k
                auto height = frame_context.size().height();
1944
22.3k
                auto stride = frame_context.decoded_size(plane > 0).width();
1945
22.3k
                if (plane > 0) {
1946
14.9k
                    width = Subsampling::subsampled_size(frame_context.color_config.subsampling_x, width);
1947
14.9k
                    height = Subsampling::subsampled_size(frame_context.color_config.subsampling_y, height);
1948
14.9k
                }
1949
1950
22.3k
                auto const& original_buffer = get_output_buffer(plane);
1951
22.3k
                auto& frame_store_buffer = reference_frame.frame_planes[plane];
1952
22.3k
                auto frame_store_width = width + MV_BORDER * 2;
1953
22.3k
                auto frame_store_height = height + MV_BORDER * 2;
1954
22.3k
                frame_store_buffer.resize_and_keep_capacity(frame_store_width * frame_store_height);
1955
1956
22.3k
                VERIFY(original_buffer.size() >= width * height);
1957
28.6M
                for (auto destination_y = 0u; destination_y < frame_store_height; destination_y++) {
1958
                    // Offset the source row by the motion vector border and then clamp it to the range of 0...height.
1959
                    // This will create an extended border on the top and bottom of the reference frame to avoid having to bounds check
1960
                    // inter-prediction.
1961
28.6M
                    auto source_y = min(destination_y >= MV_BORDER ? destination_y - MV_BORDER : 0, height - 1);
1962
28.6M
                    auto const* source = &original_buffer[source_y * stride];
1963
28.6M
                    auto* destination = &frame_store_buffer[destination_y * frame_store_width + MV_BORDER];
1964
28.6M
                    AK::TypedTransfer<RemoveReference<decltype(*destination)>>::copy(destination, source, width);
1965
28.6M
                }
1966
1967
28.6M
                for (auto destination_y = 0u; destination_y < frame_store_height; destination_y++) {
1968
                    // Stretch the leftmost samples out into the border.
1969
28.6M
                    auto sample = frame_store_buffer[destination_y * frame_store_width + MV_BORDER];
1970
1971
3.69G
                    for (auto destination_x = 0u; destination_x < MV_BORDER; destination_x++) {
1972
3.66G
                        frame_store_buffer[destination_y * frame_store_width + destination_x] = sample;
1973
3.66G
                    }
1974
1975
                    // Stretch the rightmost samples out into the border.
1976
28.6M
                    sample = frame_store_buffer[destination_y * frame_store_width + MV_BORDER + width - 1];
1977
1978
3.69G
                    for (auto destination_x = MV_BORDER + width; destination_x < frame_store_width; destination_x++) {
1979
3.66G
                        frame_store_buffer[destination_y * frame_store_width + destination_x] = sample;
1980
3.66G
                    }
1981
28.6M
                }
1982
22.3k
            }
1983
7.45k
        }
1984
14.4k
    }
1985
1986
    // 2. If show_existing_frame is equal to 0, the following applies:
1987
1.80k
    if (!frame_context.shows_existing_frame()) {
1988
1.80k
        DECODER_TRY_ALLOC(m_parser->m_previous_block_contexts.try_resize_to_match_other_vector2d(frame_context.block_contexts()));
1989
        // − PrevRefFrames[ row ][ col ][ list ] is set equal to RefFrames[ row ][ col ][ list ] for row = 0..MiRows-1,
1990
        // for col = 0..MiCols-1, for list = 0..1.
1991
        // − PrevMvs[ row ][ col ][ list ][ comp ] is set equal to Mvs[ row ][ col ][ list ][ comp ] for row = 0..MiRows-1,
1992
        // for col = 0..MiCols-1, for list = 0..1, for comp = 0..1.
1993
        // And from decode_frame():
1994
        // - If all of the following conditions are true, PrevSegmentIds[ row ][ col ] is set equal to
1995
        // SegmentIds[ row ][ col ] for row = 0..MiRows-1, for col = 0..MiCols-1:
1996
        //   − show_existing_frame is equal to 0,
1997
        //   − segmentation_enabled is equal to 1,
1998
        //   − segmentation_update_map is equal to 1.
1999
1.80k
        bool keep_segment_ids = !frame_context.shows_existing_frame() && frame_context.segmentation_enabled && frame_context.use_full_segment_id_tree;
2000
2.75M
        frame_context.block_contexts().copy_to(m_parser->m_previous_block_contexts, [keep_segment_ids](FrameBlockContext context) {
2001
2.75M
            auto persistent_context = PersistentBlockContext(context);
2002
2.75M
            if (!keep_segment_ids)
2003
1.91M
                persistent_context.segment_id = 0;
2004
2.75M
            return persistent_context;
2005
2.75M
        });
2006
1.80k
    }
2007
2008
1.80k
    return {};
2009
1.80k
}
2010
2011
}