Coverage Report

Created: 2026-05-30 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/svt-av1/Source/Lib/Codec/entropy_coding.c
Line
Count
Source
1
/*
2
* Copyright(c) 2019 Intel Corporation
3
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
4
*
5
* This source code is subject to the terms of the BSD 2 Clause License and
6
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
7
* was not distributed with this source code in the LICENSE file, you can
8
* obtain it at https://www.aomedia.org/license/software-license. If the Alliance for Open
9
* Media Patent License 1.0 was not distributed with this source code in the
10
* PATENTS file, you can obtain it at https://www.aomedia.org/license/patent-license.
11
*/
12
13
#include <stdlib.h>
14
#include <string.h>
15
#include <math.h>
16
17
#include "EbSvtAv1.h"
18
#include "entropy_coding.h"
19
#include "utility.h"
20
#include "transforms.h"
21
#include "ec_process.h"
22
#include "common_utils.h"
23
#include "adaptive_mv_pred.h"
24
#include "rd_cost.h"
25
#include "svt_log.h"
26
#include "full_loop.h"
27
#include "aom_dsp_rtcd.h"
28
#include "inter_prediction.h"
29
#include "mode_decision.h"
30
#include "restoration.h"
31
32
5.14k
static void mem_put_varsize(uint8_t* const dst, const int sz, const int val) {
33
5.14k
    switch (sz) {
34
5.14k
    case 1:
35
5.14k
        dst[0] = (uint8_t)(val & 0xff);
36
5.14k
        break;
37
0
    case 2:
38
0
        mem_put_le16(dst, val);
39
0
        break;
40
0
    case 3:
41
0
        mem_put_le24(dst, val);
42
0
        break;
43
0
    case 4:
44
0
        mem_put_le32(dst, val);
45
0
        break;
46
0
    default:
47
0
        assert(0 && "Invalid size");
48
0
        break;
49
5.14k
    }
50
5.14k
}
51
52
int svt_aom_get_comp_index_context_enc(PictureParentControlSet* pcs, int cur_frame_index, int bck_frame_index,
53
0
                                       int fwd_frame_index, const MacroBlockD* xd) {
54
0
    const int fwd = abs(svt_aom_get_relative_dist_enc(&pcs->scs->seq_header, fwd_frame_index, cur_frame_index));
55
0
    const int bck = abs(svt_aom_get_relative_dist_enc(&pcs->scs->seq_header, cur_frame_index, bck_frame_index));
56
57
0
    const MbModeInfo* const above_mi  = xd->above_mbmi;
58
0
    const MbModeInfo* const left_mi   = xd->left_mbmi;
59
0
    const int               offset    = fwd == bck;
60
0
    int                     above_ctx = 0, left_ctx = 0;
61
62
0
    if (above_mi) {
63
0
        if (has_second_ref(&above_mi->block_mi)) {
64
0
            above_ctx = above_mi->block_mi.compound_idx;
65
0
        } else if (above_mi->block_mi.ref_frame[0] == ALTREF_FRAME) {
66
0
            above_ctx = 1;
67
0
        }
68
0
    }
69
70
0
    if (left_mi) {
71
0
        if (has_second_ref(&left_mi->block_mi)) {
72
0
            left_ctx = left_mi->block_mi.compound_idx;
73
0
        } else if (left_mi->block_mi.ref_frame[0] == ALTREF_FRAME) {
74
0
            left_ctx = 1;
75
0
        }
76
0
    }
77
0
    return above_ctx + left_ctx + 3 * offset;
78
0
}
79
80
0
int svt_aom_get_comp_group_idx_context_enc(const MacroBlockD* xd) {
81
0
    const MbModeInfo* const above_mi  = xd->above_mbmi;
82
0
    const MbModeInfo* const left_mi   = xd->left_mbmi;
83
0
    int                     above_ctx = 0, left_ctx = 0;
84
0
    if (above_mi) {
85
0
        if (has_second_ref(&above_mi->block_mi)) {
86
0
            above_ctx = above_mi->block_mi.comp_group_idx;
87
0
        } else if (above_mi->block_mi.ref_frame[0] == ALTREF_FRAME) {
88
0
            above_ctx = 3;
89
0
        }
90
0
    }
91
0
    if (left_mi) {
92
0
        if (has_second_ref(&left_mi->block_mi)) {
93
0
            left_ctx = left_mi->block_mi.comp_group_idx;
94
0
        } else if (left_mi->block_mi.ref_frame[0] == ALTREF_FRAME) {
95
0
            left_ctx = 3;
96
0
        }
97
0
    }
98
0
    return AOMMIN(5, above_ctx + left_ctx);
99
0
}
100
101
static INLINE int32_t does_level_match(int32_t width, int32_t height, double fps, int32_t lvl_width, int32_t lvl_height,
102
1.06k
                                       double lvl_fps, int32_t lvl_dim_mult) {
103
1.06k
    const int64_t lvl_luma_pels           = (int64_t)lvl_width * lvl_height;
104
1.06k
    const double  lvl_display_sample_rate = lvl_luma_pels * lvl_fps;
105
1.06k
    const int64_t luma_pels               = (int64_t)width * height;
106
1.06k
    const double  display_sample_rate     = luma_pels * fps;
107
1.06k
    return luma_pels <= lvl_luma_pels && display_sample_rate <= lvl_display_sample_rate &&
108
1.06k
        width <= lvl_width * lvl_dim_mult && height <= lvl_height * lvl_dim_mult;
109
1.06k
}
110
111
1.06k
static void set_bitstream_level_tier(SequenceControlSet* scs) {
112
    // This is a placeholder function that only addresses dimensions
113
    // and max display sample rates.
114
    // Need to add checks for max bit rate, max decoded luma sample rate, header
115
    // rate, etc. that are not covered by this function.
116
117
1.06k
    BitstreamLevel bl = {9, 3};
118
1.06k
    if (scs->static_config.level) {
119
0
        bl.major = scs->static_config.level / 10;
120
0
        bl.minor = scs->static_config.level % 10;
121
1.06k
    } else if (does_level_match(scs->seq_header.max_frame_width,
122
1.06k
                                scs->seq_header.max_frame_height,
123
1.06k
                                scs->frame_rate,
124
1.06k
                                512,
125
1.06k
                                288,
126
1.06k
                                30.0,
127
1.06k
                                4)) {
128
1.06k
        bl.major = 2;
129
1.06k
        bl.minor = 0;
130
1.06k
    } else if (does_level_match(scs->seq_header.max_frame_width,
131
0
                                scs->seq_header.max_frame_height,
132
0
                                scs->frame_rate,
133
0
                                704,
134
0
                                396,
135
0
                                30.0,
136
0
                                4)) {
137
0
        bl.major = 2;
138
0
        bl.minor = 1;
139
0
    } else if (does_level_match(scs->seq_header.max_frame_width,
140
0
                                scs->seq_header.max_frame_height,
141
0
                                scs->frame_rate,
142
0
                                1088,
143
0
                                612,
144
0
                                30.0,
145
0
                                4)) {
146
0
        bl.major = 3;
147
0
        bl.minor = 0;
148
0
    } else if (does_level_match(scs->seq_header.max_frame_width,
149
0
                                scs->seq_header.max_frame_height,
150
0
                                scs->frame_rate,
151
0
                                1376,
152
0
                                774,
153
0
                                30.0,
154
0
                                4)) {
155
0
        bl.major = 3;
156
0
        bl.minor = 1;
157
0
    } else if (does_level_match(scs->seq_header.max_frame_width,
158
0
                                scs->seq_header.max_frame_height,
159
0
                                scs->frame_rate,
160
0
                                2048,
161
0
                                1152,
162
0
                                30.0,
163
0
                                3)) {
164
0
        bl.major = 4;
165
0
        bl.minor = 0;
166
0
    } else if (does_level_match(scs->seq_header.max_frame_width,
167
0
                                scs->seq_header.max_frame_height,
168
0
                                scs->frame_rate,
169
0
                                2048,
170
0
                                1152,
171
0
                                60.0,
172
0
                                3)) {
173
0
        bl.major = 4;
174
0
        bl.minor = 1;
175
0
    } else if (does_level_match(scs->seq_header.max_frame_width,
176
0
                                scs->seq_header.max_frame_height,
177
0
                                scs->frame_rate,
178
0
                                4096,
179
0
                                2176,
180
0
                                30.0,
181
0
                                2)) {
182
0
        bl.major = 5;
183
0
        bl.minor = 0;
184
0
    } else if (does_level_match(scs->seq_header.max_frame_width,
185
0
                                scs->seq_header.max_frame_height,
186
0
                                scs->frame_rate,
187
0
                                4096,
188
0
                                2176,
189
0
                                60.0,
190
0
                                2)) {
191
0
        bl.major = 5;
192
0
        bl.minor = 1;
193
0
    } else if (does_level_match(scs->seq_header.max_frame_width,
194
0
                                scs->seq_header.max_frame_height,
195
0
                                scs->frame_rate,
196
0
                                4096,
197
0
                                2176,
198
0
                                120.0,
199
0
                                2)) {
200
0
        bl.major = 5;
201
0
        bl.minor = 2;
202
0
    } else if (does_level_match(scs->seq_header.max_frame_width,
203
0
                                scs->seq_header.max_frame_height,
204
0
                                scs->frame_rate,
205
0
                                8192,
206
0
                                4352,
207
0
                                30.0,
208
0
                                2)) {
209
0
        bl.major = 6;
210
0
        bl.minor = 0;
211
0
    } else if (does_level_match(scs->seq_header.max_frame_width,
212
0
                                scs->seq_header.max_frame_height,
213
0
                                scs->frame_rate,
214
0
                                8192,
215
0
                                4352,
216
0
                                60.0,
217
0
                                2)) {
218
0
        bl.major = 6;
219
0
        bl.minor = 1;
220
0
    } else if (does_level_match(scs->seq_header.max_frame_width,
221
0
                                scs->seq_header.max_frame_height,
222
0
                                scs->frame_rate,
223
0
                                8192,
224
0
                                4352,
225
0
                                120.0,
226
0
                                2)) {
227
0
        bl.major = 6;
228
0
        bl.minor = 2;
229
0
    }
230
35.1k
    for (int32_t i = 0; i < MAX_NUM_OPERATING_POINTS; ++i) {
231
34.1k
        scs->level[i]                               = bl;
232
34.1k
        scs->seq_header.operating_point[i].seq_tier = 0; // setting main tier by default
233
34.1k
    }
234
1.06k
}
235
236
16.0k
static INLINE void write_golomb(AomWriter* w, int32_t level) {
237
16.0k
    const int32_t  x      = level + 1;
238
16.0k
    const uint32_t length = svt_log2f(x) + 1;
239
16.0k
    assert(length > 0);
240
241
16.0k
    aom_write_literal(w, 0, length - 1);
242
16.0k
    aom_write_literal(w, x, length);
243
16.0k
}
244
245
/************************************************************************************************/
246
// blockd.h
247
248
void svt_aom_get_txb_ctx(PictureControlSet* pcs, const int32_t plane,
249
                         NeighborArrayUnit* dc_sign_level_coeff_neighbor_array, uint32_t blk_org_x, uint32_t blk_org_y,
250
                         const BlockSize plane_bsize, const TxSize tx_size, int16_t* const txb_skip_ctx,
251
27.1k
                         int16_t* const dc_sign_ctx) {
252
    /* Hoist NA ring pointers and iterate them directly. Shape-B PU NA. */
253
27.1k
    const uint8_t* const top_ptr  = svt_aom_na_top_ptr_pu(dc_sign_level_coeff_neighbor_array, blk_org_x);
254
27.1k
    const uint8_t* const left_ptr = svt_aom_na_left_ptr_pu(dc_sign_level_coeff_neighbor_array, blk_org_y);
255
256
27.1k
    static const int8_t signs[3]    = {0, -1, 1};
257
27.1k
    const int32_t       plane_shift = !!plane;
258
27.1k
    int32_t             txb_w_unit  = MIN(eb_tx_size_wide_unit[tx_size],
259
27.1k
                             (int32_t)((pcs->ppcs->aligned_width >> plane_shift) - blk_org_x) >> 2);
260
27.1k
    int32_t             txb_h_unit  = MIN(eb_tx_size_high_unit[tx_size],
261
27.1k
                             (int32_t)((pcs->ppcs->aligned_height >> plane_shift) - blk_org_y) >> 2);
262
263
27.1k
    int16_t dc_sign = 0;
264
27.1k
    int32_t top     = 0; /* OR-accumulation across neighbors */
265
27.1k
    int32_t left    = 0;
266
267
    /* Combined top sweep: dc_sign + OR-accumulated top. */
268
27.1k
    if (top_ptr[0] != INVALID_NEIGHBOR_DATA) {
269
16.3k
        for (int32_t k = 0; k < txb_w_unit; ++k) {
270
10.5k
            uint8_t v    = top_ptr[k];
271
10.5k
            uint8_t sign = v >> COEFF_CONTEXT_BITS;
272
10.5k
            assert(sign <= 2);
273
10.5k
            dc_sign += signs[sign];
274
10.5k
            top |= v;
275
10.5k
        }
276
5.79k
    }
277
    /* Combined left sweep: dc_sign + OR-accumulated left. */
278
27.1k
    if (left_ptr[0] != INVALID_NEIGHBOR_DATA) {
279
26.8k
        for (int32_t k = 0; k < txb_h_unit; ++k) {
280
20.1k
            uint8_t v    = left_ptr[k];
281
20.1k
            uint8_t sign = v >> COEFF_CONTEXT_BITS;
282
20.1k
            assert(sign <= 2);
283
20.1k
            dc_sign += signs[sign];
284
20.1k
            left |= v;
285
20.1k
        }
286
6.73k
    }
287
288
27.1k
    if (dc_sign > 0) {
289
0
        *dc_sign_ctx = 2;
290
27.1k
    } else if (dc_sign < 0) {
291
7.72k
        *dc_sign_ctx = 1;
292
19.4k
    } else {
293
19.4k
        *dc_sign_ctx = 0;
294
19.4k
    }
295
296
27.1k
    int32_t tx_bsize = txsize_to_bsize[tx_size];
297
27.1k
    if (plane == 0) {
298
13.8k
        if (plane_bsize == tx_bsize) {
299
4.26k
            *txb_skip_ctx = 0;
300
9.56k
        } else {
301
9.56k
            static const uint8_t skip_contexts[5][5] = {
302
9.56k
                {1, 2, 2, 2, 3}, {1, 4, 4, 4, 5}, {1, 4, 4, 4, 5}, {1, 4, 4, 4, 5}, {1, 4, 4, 4, 6}};
303
9.56k
            top &= COEFF_CONTEXT_MASK;
304
9.56k
            left &= COEFF_CONTEXT_MASK;
305
9.56k
            int32_t max = AOMMIN(top | left, 4);
306
9.56k
            int32_t min = AOMMIN(AOMMIN(top, left), 4);
307
308
9.56k
            *txb_skip_ctx = skip_contexts[min][max];
309
9.56k
        }
310
13.8k
    } else {
311
13.3k
        int32_t ctx_base   = ((left != 0) + (top != 0));
312
13.3k
        int32_t ctx_offset = (eb_num_pels_log2_lookup[plane_bsize] > eb_num_pels_log2_lookup[tx_bsize]) ? 10 : 7;
313
13.3k
        *txb_skip_ctx      = (int16_t)(ctx_base + ctx_offset);
314
13.3k
    }
315
27.1k
}
316
317
static void av1_write_tx_type(PictureParentControlSet* pcs, FRAME_CONTEXT* frame_context, MbModeInfo* mbmi,
318
6.36k
                              AomWriter* ec_writer, uint32_t intraDir, TxType tx_type, TxSize tx_size) {
319
6.36k
    FrameHeader*  frm_hdr  = &pcs->frm_hdr;
320
6.36k
    const int32_t is_inter = mbmi->block_mi.use_intrabc || is_inter_mode(mbmi->block_mi.mode);
321
6.36k
    if (get_ext_tx_types(tx_size, is_inter, frm_hdr->reduced_tx_set) > 1 &&
322
3.19k
        (frm_hdr->quantization_params.base_q_idx > 0)) {
323
800
        const TxSize square_tx_size = txsize_sqr_map[tx_size];
324
800
        assert(square_tx_size <= EXT_TX_SIZES);
325
326
800
        const TxSetType tx_set_type = get_ext_tx_set_type(tx_size, is_inter, frm_hdr->reduced_tx_set);
327
800
        const int32_t   eset        = get_ext_tx_set(tx_size, is_inter, frm_hdr->reduced_tx_set);
328
        // eset == 0 should correspond to a set with only DCT_DCT and there
329
        // is no need to send the tx_type
330
800
        assert(eset > 0);
331
800
        assert(av1_ext_tx_used[tx_set_type][tx_type]);
332
800
        if (is_inter) {
333
0
            aom_write_symbol(ec_writer,
334
0
                             av1_ext_tx_ind[tx_set_type][tx_type],
335
0
                             frame_context->inter_ext_tx_cdf[eset][square_tx_size],
336
0
                             av1_num_ext_tx_set[tx_set_type]);
337
800
        } else {
338
800
            PredictionMode intra_dir;
339
800
            if (mbmi->block_mi.filter_intra_mode != FILTER_INTRA_MODES) {
340
0
                intra_dir = fimode_to_intradir[mbmi->block_mi.filter_intra_mode];
341
800
            } else {
342
800
                intra_dir = intraDir;
343
800
            }
344
345
800
            assert(intra_dir < 13);
346
800
            assert(square_tx_size < 4);
347
800
            aom_write_symbol(ec_writer,
348
800
                             av1_ext_tx_ind[tx_set_type][tx_type],
349
800
                             frame_context->intra_ext_tx_cdf[eset][square_tx_size][intra_dir],
350
800
                             av1_num_ext_tx_set[tx_set_type]);
351
800
        }
352
800
    }
353
6.36k
}
354
355
static int32_t av1_write_coeffs_txb_1d(PictureParentControlSet* ppcs, FRAME_CONTEXT* frame_context, MbModeInfo* mbmi,
356
                                       AomWriter* ec_writer, EcBlkStruct* blk_ptr, TxSize tx_size, uint32_t txb_index,
357
                                       uint32_t intraLumaDir, int32_t* coeff_buffer_ptr, COMPONENT_TYPE component_type,
358
                                       int16_t txb_skip_ctx, int16_t dc_sign_ctx, int16_t eob,
359
27.1k
                                       EntropyCodingContext* ec_ctx) {
360
27.1k
    int32_t      c;
361
27.1k
    const TxSize txs_ctx = get_txsize_entropy_ctx(tx_size);
362
27.1k
    TxType       tx_type = component_type == COMPONENT_LUMA ? blk_ptr->tx_type[txb_index] : blk_ptr->tx_type_uv;
363
364
27.1k
    assert(txs_ctx < TX_SIZES);
365
366
27.1k
    aom_write_symbol(ec_writer, eob == 0, frame_context->txb_skip_cdf[txs_ctx][txb_skip_ctx], 2);
367
368
27.1k
    assert(IMPLIES((component_type == 0 && eob == 0), tx_type == DCT_DCT));
369
27.1k
    assert(IMPLIES((is_inter_mode(mbmi->block_mi.mode) && component_type == 0 && eob == 0 && txb_index == 0),
370
27.1k
                   blk_ptr->tx_type_uv == DCT_DCT));
371
27.1k
    if (eob == 0) {
372
8.31k
        return 0;
373
8.31k
    }
374
18.8k
    if (component_type == COMPONENT_LUMA) {
375
6.36k
        av1_write_tx_type(ppcs, frame_context, mbmi, ec_writer, intraLumaDir, tx_type, tx_size);
376
6.36k
    }
377
18.8k
    int         eob_extra;
378
18.8k
    const int   eob_pt         = get_eob_pos_token(eob, &eob_extra);
379
18.8k
    const int   eob_multi_size = txsize_log2_minus4[tx_size];
380
18.8k
    const int   eob_multi_ctx  = (tx_type_to_class[tx_type] == TX_CLASS_2D) ? 0 : 1;
381
18.8k
    AomCdfProb* eob_flag_cdfs;
382
18.8k
    switch (eob_multi_size) {
383
7.97k
    case 0:
384
7.97k
        eob_flag_cdfs = frame_context->eob_flag_cdf16[component_type][eob_multi_ctx];
385
7.97k
        break;
386
0
    case 1:
387
0
        eob_flag_cdfs = frame_context->eob_flag_cdf32[component_type][eob_multi_ctx];
388
0
        break;
389
1.07k
    case 2:
390
1.07k
        eob_flag_cdfs = frame_context->eob_flag_cdf64[component_type][eob_multi_ctx];
391
1.07k
        break;
392
0
    case 3:
393
0
        eob_flag_cdfs = frame_context->eob_flag_cdf128[component_type][eob_multi_ctx];
394
0
        break;
395
1.38k
    case 4:
396
1.38k
        eob_flag_cdfs = frame_context->eob_flag_cdf256[component_type][eob_multi_ctx];
397
1.38k
        break;
398
0
    case 5:
399
0
        eob_flag_cdfs = frame_context->eob_flag_cdf512[component_type][eob_multi_ctx];
400
0
        break;
401
8.39k
    case 6:
402
8.39k
    default:
403
8.39k
        eob_flag_cdfs = frame_context->eob_flag_cdf1024[component_type][eob_multi_ctx];
404
8.39k
        break;
405
18.8k
    }
406
18.8k
    aom_write_symbol(ec_writer, eob_pt - 1, eob_flag_cdfs, eob_multi_size + 5);
407
18.8k
    if (eob_pt > 2) {
408
0
        int cnt = eob_pt - 3;
409
0
        int bit = (eob_extra >> cnt) & 1;
410
0
        aom_write_symbol(ec_writer, bit, frame_context->eob_extra_cdf[txs_ctx][component_type][cnt], 2);
411
0
        aom_write_literal(ec_writer, eob_extra, cnt);
412
0
    }
413
414
18.8k
#if OPT_EC_DC_ONLY
415
    // Fast path for eob==1: single DC coefficient.
416
    // Contexts are known: coeff_ctx=0 (get_lower_levels_ctx_eob returns 0 for scan_idx=0),
417
    // br_ctx=0 (DC position with all-zero neighbors).
418
    // Skips txb_init_levels and get_nz_map_contexts entirely.
419
18.8k
    if (eob == 1) {
420
18.8k
        const int32_t v         = coeff_buffer_ptr[0];
421
18.8k
        int32_t       level     = ABS(v);
422
18.8k
        AomCdfProb*   dc_br_cdf = frame_context->coeff_br_cdf[AOMMIN(txs_ctx, TX_32X32)][component_type][0];
423
424
18.8k
        aom_write_symbol(
425
18.8k
            ec_writer, AOMMIN(level, 3) - 1, frame_context->coeff_base_eob_cdf[txs_ctx][component_type][0], 3);
426
18.8k
        if (level > NUM_BASE_LEVELS) {
427
17.0k
            int32_t base_range = level - 1 - NUM_BASE_LEVELS;
428
82.8k
            for (int32_t idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
429
66.7k
                const int32_t k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
430
66.7k
                aom_write_symbol(ec_writer, k, dc_br_cdf, BR_CDF_SIZE);
431
66.7k
                if (k < BR_CDF_SIZE - 1) {
432
935
                    break;
433
935
                }
434
66.7k
            }
435
17.0k
        }
436
        // Sign (DC always uses dc_sign_cdf)
437
18.8k
        aom_write_symbol(ec_writer, (v < 0) ? 1 : 0, frame_context->dc_sign_cdf[component_type][dc_sign_ctx], 2);
438
18.8k
        if (level > COEFF_BASE_RANGE + NUM_BASE_LEVELS) {
439
16.0k
            write_golomb(ec_writer, level - COEFF_BASE_RANGE - 1 - NUM_BASE_LEVELS);
440
16.0k
        }
441
442
18.8k
        int32_t cul_level = AOMMIN(level, COEFF_CONTEXT_MASK);
443
18.8k
        set_dc_sign(&cul_level, coeff_buffer_ptr[0]);
444
18.8k
        return cul_level;
445
18.8k
    }
446
0
#endif
447
448
0
    const int bwl    = get_txb_bwl(tx_size);
449
0
    const int width  = get_txb_wide(tx_size);
450
0
    const int height = get_txb_high(tx_size);
451
452
0
    uint8_t* const levels = set_levels(ec_ctx->levels_buf, width, height);
453
0
    svt_av1_txb_init_levels(coeff_buffer_ptr, width, height, levels);
454
455
0
    const ScanOrder* const scan_order = get_scan_order(tx_size, tx_type);
456
0
    const int16_t* const   scan       = scan_order->scan;
457
458
0
    svt_av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_type_to_class[tx_type], ec_ctx->coeff_contexts);
459
460
0
#if OPT_EC_MERGE_COEFF_LOOPS
461
    // Merged approach: backward pass caches level/sign per coefficient,
462
    // accumulates cul_level, then a forward pass emits signs from cache.
463
    // Avoids re-reading coeff_buffer_ptr[scan[c]] in the forward pass.
464
0
    const TxClass tx_class   = tx_type_to_class[tx_type];
465
0
    const int32_t br_txs_ctx = AOMMIN(txs_ctx, TX_32X32);
466
467
    // Pre-compute CDF base pointers (loop-invariant outer dimensions)
468
0
    AomCdfProb(*base_cdf)[CDF_SIZE(4)]         = frame_context->coeff_base_cdf[txs_ctx][component_type];
469
0
    AomCdfProb(*br_cdf)[CDF_SIZE(BR_CDF_SIZE)] = frame_context->coeff_br_cdf[br_txs_ctx][component_type];
470
471
    // Cache: store level and sign for each scan position 0..eob-1
472
    // VLA sized to eob (guaranteed >= 2 here) instead of MAX_TX_SQUARE (4096)
473
    // to reduce stack usage from ~12KB to a few bytes for typical small blocks.
474
    // MSVC does not support C99 VLAs, so fall back to MAX_TX_SQUARE there.
475
#ifdef _MSC_VER
476
    int16_t cached_level[MAX_TX_SQUARE];
477
    uint8_t cached_sign[MAX_TX_SQUARE];
478
#else
479
0
    int16_t cached_level[eob];
480
0
    uint8_t cached_sign[eob];
481
0
#endif
482
0
    int32_t cul_level = 0;
483
484
    // Backward pass: base levels + base_range + cache
485
0
    {
486
0
        AomCdfProb(*base_eob_cdf)[CDF_SIZE(3)] = frame_context->coeff_base_eob_cdf[txs_ctx][component_type];
487
488
        // Peeled first iteration: c == eob - 1
489
0
        const int16_t pos       = scan[eob - 1];
490
0
        const int32_t v         = coeff_buffer_ptr[pos];
491
0
        const int16_t coeff_ctx = ec_ctx->coeff_contexts[pos];
492
0
        int32_t       level     = ABS(v);
493
494
0
        cached_level[eob - 1] = (int16_t)level;
495
0
        cached_sign[eob - 1]  = (v < 0) ? 1 : 0;
496
0
        cul_level += level;
497
498
0
        aom_write_symbol(ec_writer, AOMMIN(level, 3) - 1, base_eob_cdf[coeff_ctx], 3);
499
0
        if (level > NUM_BASE_LEVELS) {
500
0
            int32_t base_range = level - 1 - NUM_BASE_LEVELS;
501
0
            int16_t br_ctx     = get_br_ctx(levels, pos, bwl, tx_class);
502
0
            for (int32_t idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
503
0
                const int32_t k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
504
0
                aom_write_symbol(ec_writer, k, br_cdf[br_ctx], BR_CDF_SIZE);
505
0
                if (k < BR_CDF_SIZE - 1) {
506
0
                    break;
507
0
                }
508
0
            }
509
0
        }
510
0
    }
511
0
    for (c = eob - 2; c >= 0; --c) {
512
0
        const int16_t pos       = scan[c];
513
0
        const int32_t v         = coeff_buffer_ptr[pos];
514
0
        const int16_t coeff_ctx = ec_ctx->coeff_contexts[pos];
515
0
        int32_t       level     = ABS(v);
516
517
0
        cached_level[c] = (int16_t)level;
518
0
        cached_sign[c]  = (v < 0) ? 1 : 0;
519
0
        cul_level += level;
520
521
0
        aom_write_symbol(ec_writer, AOMMIN(level, 3), base_cdf[coeff_ctx], 4);
522
0
        if (level > NUM_BASE_LEVELS) {
523
0
            int32_t base_range = level - 1 - NUM_BASE_LEVELS;
524
0
            int16_t br_ctx     = get_br_ctx(levels, pos, bwl, tx_class);
525
0
            for (int32_t idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
526
0
                const int32_t k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
527
0
                aom_write_symbol(ec_writer, k, br_cdf[br_ctx], BR_CDF_SIZE);
528
0
                if (k < BR_CDF_SIZE - 1) {
529
0
                    break;
530
0
                }
531
0
            }
532
0
        }
533
0
    }
534
535
    // Forward pass: signs + golomb from cached data (no coeff_buffer_ptr re-read)
536
0
    for (c = 0; c < eob; ++c) {
537
0
        const int32_t level = cached_level[c];
538
0
        if (level) {
539
0
            if (c == 0) {
540
0
                aom_write_symbol(ec_writer, cached_sign[c], frame_context->dc_sign_cdf[component_type][dc_sign_ctx], 2);
541
0
            } else {
542
0
                aom_write_bit(ec_writer, cached_sign[c]);
543
0
            }
544
0
            if (level > COEFF_BASE_RANGE + NUM_BASE_LEVELS) {
545
0
                write_golomb(ec_writer, level - COEFF_BASE_RANGE - 1 - NUM_BASE_LEVELS);
546
0
            }
547
0
        }
548
0
    }
549
550
0
    cul_level = AOMMIN(COEFF_CONTEXT_MASK, cul_level);
551
0
    set_dc_sign(&cul_level, coeff_buffer_ptr[0]);
552
0
    return cul_level;
553
#else
554
    // Pre-compute CDF base pointers (loop-invariant outer dimensions)
555
    AomCdfProb(*base_cdf)[CDF_SIZE(4)]         = frame_context->coeff_base_cdf[txs_ctx][component_type];
556
    AomCdfProb(*base_eob_cdf)[CDF_SIZE(3)]     = frame_context->coeff_base_eob_cdf[txs_ctx][component_type];
557
    AomCdfProb(*br_cdf)[CDF_SIZE(BR_CDF_SIZE)] = frame_context->coeff_br_cdf[AOMMIN(txs_ctx, TX_32X32)][component_type];
558
    for (c = eob - 1; c >= 0; --c) {
559
        const int16_t pos       = scan[c];
560
        const int32_t v         = coeff_buffer_ptr[pos];
561
        const int16_t coeff_ctx = ec_ctx->coeff_contexts[pos];
562
        int32_t       level     = ABS(v);
563
564
        if (c == eob - 1) {
565
            aom_write_symbol(ec_writer, AOMMIN(level, 3) - 1, base_eob_cdf[coeff_ctx], 3);
566
        } else {
567
            aom_write_symbol(ec_writer, AOMMIN(level, 3), base_cdf[coeff_ctx], 4);
568
        }
569
        if (level > NUM_BASE_LEVELS) {
570
            // level is above 1.
571
            int32_t base_range = level - 1 - NUM_BASE_LEVELS;
572
            int16_t br_ctx     = get_br_ctx(levels, pos, bwl, tx_type_to_class[tx_type]);
573
            for (int32_t idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
574
                const int32_t k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
575
                aom_write_symbol(ec_writer, k, br_cdf[br_ctx], BR_CDF_SIZE);
576
                if (k < BR_CDF_SIZE - 1) {
577
                    break;
578
                }
579
            }
580
        }
581
    }
582
    // Loop to code all signs in the transform block,
583
    // starting with the sign of DC (if applicable)
584
585
    int32_t cul_level = 0;
586
    for (c = 0; c < eob; ++c) {
587
        const int16_t pos   = scan[c];
588
        const int32_t v     = coeff_buffer_ptr[pos];
589
        int32_t       level = ABS(v);
590
        cul_level += level;
591
592
        const int32_t sign = (v < 0) ? 1 : 0;
593
        if (level) {
594
            if (c == 0) {
595
                aom_write_symbol(ec_writer, sign, frame_context->dc_sign_cdf[component_type][dc_sign_ctx], 2);
596
            } else {
597
                aom_write_bit(ec_writer, sign);
598
            }
599
            if (level > COEFF_BASE_RANGE + NUM_BASE_LEVELS) {
600
                write_golomb(ec_writer, level - COEFF_BASE_RANGE - 1 - NUM_BASE_LEVELS);
601
            }
602
        }
603
    }
604
605
    cul_level = AOMMIN(COEFF_CONTEXT_MASK, cul_level);
606
    // DC value
607
    set_dc_sign(&cul_level, coeff_buffer_ptr[0]);
608
    return cul_level;
609
#endif
610
18.8k
}
611
612
static EbErrorType av1_encode_tx_coef_y(PictureControlSet* pcs, EntropyCodingContext* ec_ctx,
613
                                        FRAME_CONTEXT* frame_context, AomWriter* ec_writer, MbModeInfo* mbmi,
614
                                        EcBlkStruct* blk_ptr, uint32_t blk_org_x, uint32_t blk_org_y,
615
                                        uint32_t intraLumaDir, BlockSize plane_bsize, EbPictureBufferDesc* coeff_ptr,
616
2.39k
                                        NeighborArrayUnit* luma_dc_sign_level_coeff_na) {
617
2.39k
    EbErrorType     return_error = EB_ErrorNone;
618
2.39k
    const bool      is_inter     = is_inter_mode(mbmi->block_mi.mode) || mbmi->block_mi.use_intrabc;
619
2.39k
    const BlockSize bsize        = mbmi->bsize;
620
2.39k
    const uint8_t   tx_depth     = mbmi->block_mi.tx_depth;
621
2.39k
    const uint16_t  txb_count    = tx_blocks_per_depth[bsize][tx_depth];
622
2.39k
    const TxSize    tx_size      = tx_depth_to_tx_size[tx_depth][bsize];
623
2.39k
    const int       tx_width     = tx_size_wide[tx_size];
624
2.39k
    const int       tx_height    = tx_size_high[tx_size];
625
626
11.9k
    for (uint16_t txb_itr = 0; txb_itr < txb_count; txb_itr++) {
627
        // Hoist tx_org lookup: same Position is used by both svt_aom_get_txb_ctx and the NA write.
628
9.56k
        const Position org  = tx_org[bsize][is_inter][tx_depth][txb_itr];
629
9.56k
        const uint32_t tx_x = blk_org_x + org.x;
630
9.56k
        const uint32_t tx_y = blk_org_y + org.y;
631
632
9.56k
        int32_t* coeff_buffer = (int32_t*)coeff_ptr->y_buffer + ec_ctx->coded_area_sb;
633
634
9.56k
        int16_t txb_skip_ctx = 0;
635
9.56k
        int16_t dc_sign_ctx  = 0;
636
9.56k
        svt_aom_get_txb_ctx(pcs,
637
9.56k
                            COMPONENT_LUMA,
638
9.56k
                            luma_dc_sign_level_coeff_na,
639
9.56k
                            tx_x,
640
9.56k
                            tx_y,
641
9.56k
                            plane_bsize,
642
9.56k
                            tx_size,
643
9.56k
                            &txb_skip_ctx,
644
9.56k
                            &dc_sign_ctx);
645
646
9.56k
        int32_t cul_level_y = av1_write_coeffs_txb_1d(pcs->ppcs,
647
9.56k
                                                      frame_context,
648
9.56k
                                                      mbmi,
649
9.56k
                                                      ec_writer,
650
9.56k
                                                      blk_ptr,
651
9.56k
                                                      tx_size,
652
9.56k
                                                      txb_itr,
653
9.56k
                                                      intraLumaDir,
654
9.56k
                                                      coeff_buffer,
655
9.56k
                                                      COMPONENT_LUMA,
656
9.56k
                                                      txb_skip_ctx,
657
9.56k
                                                      dc_sign_ctx,
658
9.56k
                                                      blk_ptr->eob.y[txb_itr],
659
9.56k
                                                      ec_ctx);
660
661
        // Update the luma Dc Sign Level Coeff Neighbor Array
662
9.56k
        uint8_t dc_sign_level_coeff = (uint8_t)cul_level_y;
663
9.56k
        svt_aom_neighbor_array_unit_mode_write_pu(luma_dc_sign_level_coeff_na,
664
9.56k
                                                  &dc_sign_level_coeff,
665
9.56k
                                                  tx_x,
666
9.56k
                                                  tx_y,
667
9.56k
                                                  tx_width,
668
9.56k
                                                  tx_height,
669
9.56k
                                                  NEIGHBOR_ARRAY_UNIT_TOP_AND_LEFT_ONLY_MASK);
670
671
9.56k
        ec_ctx->coded_area_sb += tx_width * tx_height;
672
9.56k
    }
673
674
2.39k
    return return_error;
675
2.39k
}
676
677
static void av1_encode_tx_coef_uv(PictureControlSet* pcs, EntropyCodingContext* ec_ctx, FRAME_CONTEXT* frame_context,
678
                                  AomWriter* ec_writer, EcBlkStruct* blk_ptr, uint32_t blk_org_x, uint32_t blk_org_y,
679
                                  uint32_t intraLumaDir, EbPictureBufferDesc* coeff_ptr,
680
                                  NeighborArrayUnit* cr_dc_sign_level_coeff_na,
681
2.39k
                                  NeighborArrayUnit* cb_dc_sign_level_coeff_na) {
682
2.39k
    MbModeInfo* const mbmi   = ec_ctx->mbmi;
683
2.39k
    const BlockSize   bsize  = mbmi->bsize;
684
2.39k
    const bool        has_uv = is_chroma_reference(blk_org_y >> 2, blk_org_x >> 2, bsize, 1, 1);
685
686
2.39k
    if (!has_uv) {
687
0
        return;
688
0
    }
689
2.39k
    const int32_t   is_inter       = is_inter_mode(mbmi->block_mi.mode) || mbmi->block_mi.use_intrabc;
690
2.39k
    const BlockSize bsize_uv       = get_plane_block_size(bsize, 1, 1);
691
2.39k
    const uint8_t   tx_depth       = mbmi->block_mi.tx_depth;
692
2.39k
    const TxSize    chroma_tx_size = av1_get_max_uv_txsize(bsize, 1, 1);
693
2.39k
    const int       tx_width_uv    = tx_size_wide[chroma_tx_size];
694
2.39k
    const int       tx_height_uv   = tx_size_high[chroma_tx_size];
695
2.39k
    const unsigned  txb_count      = 1;
696
697
4.78k
    for (unsigned tx_index = 0; tx_index < txb_count; ++tx_index) {
698
        // Hoist tx_org lookup + ROUND_UV: reused by 4 sites below.
699
2.39k
        const Position org  = tx_org[bsize][is_inter][tx_depth][tx_index];
700
2.39k
        const uint32_t uv_x = ROUND_UV(blk_org_x + org.x) >> 1;
701
2.39k
        const uint32_t uv_y = ROUND_UV(blk_org_y + org.y) >> 1;
702
703
        // cb
704
2.39k
        int32_t* coeff_buffer = (int32_t*)coeff_ptr->u_buffer + ec_ctx->coded_area_sb_uv;
705
2.39k
        int16_t  txb_skip_ctx = 0;
706
2.39k
        int16_t  dc_sign_ctx  = 0;
707
708
2.39k
        svt_aom_get_txb_ctx(pcs,
709
2.39k
                            COMPONENT_CHROMA,
710
2.39k
                            cb_dc_sign_level_coeff_na,
711
2.39k
                            uv_x,
712
2.39k
                            uv_y,
713
2.39k
                            bsize_uv,
714
2.39k
                            chroma_tx_size,
715
2.39k
                            &txb_skip_ctx,
716
2.39k
                            &dc_sign_ctx);
717
718
2.39k
        int32_t cul_level_cb = av1_write_coeffs_txb_1d(pcs->ppcs,
719
2.39k
                                                       frame_context,
720
2.39k
                                                       mbmi,
721
2.39k
                                                       ec_writer,
722
2.39k
                                                       blk_ptr,
723
2.39k
                                                       chroma_tx_size,
724
2.39k
                                                       tx_index,
725
2.39k
                                                       intraLumaDir,
726
2.39k
                                                       coeff_buffer,
727
2.39k
                                                       COMPONENT_CHROMA,
728
2.39k
                                                       txb_skip_ctx,
729
2.39k
                                                       dc_sign_ctx,
730
2.39k
                                                       blk_ptr->eob.u[tx_index],
731
2.39k
                                                       ec_ctx);
732
733
        // cr
734
2.39k
        coeff_buffer = (int32_t*)coeff_ptr->v_buffer + ec_ctx->coded_area_sb_uv;
735
2.39k
        txb_skip_ctx = 0;
736
2.39k
        dc_sign_ctx  = 0;
737
738
2.39k
        svt_aom_get_txb_ctx(pcs,
739
2.39k
                            COMPONENT_CHROMA,
740
2.39k
                            cr_dc_sign_level_coeff_na,
741
2.39k
                            uv_x,
742
2.39k
                            uv_y,
743
2.39k
                            bsize_uv,
744
2.39k
                            chroma_tx_size,
745
2.39k
                            &txb_skip_ctx,
746
2.39k
                            &dc_sign_ctx);
747
748
2.39k
        int32_t cul_level_cr = av1_write_coeffs_txb_1d(pcs->ppcs,
749
2.39k
                                                       frame_context,
750
2.39k
                                                       mbmi,
751
2.39k
                                                       ec_writer,
752
2.39k
                                                       blk_ptr,
753
2.39k
                                                       chroma_tx_size,
754
2.39k
                                                       tx_index,
755
2.39k
                                                       intraLumaDir,
756
2.39k
                                                       coeff_buffer,
757
2.39k
                                                       COMPONENT_CHROMA,
758
2.39k
                                                       txb_skip_ctx,
759
2.39k
                                                       dc_sign_ctx,
760
2.39k
                                                       blk_ptr->eob.v[tx_index],
761
2.39k
                                                       ec_ctx);
762
        // Update the cb Dc Sign Level Coeff Neighbor Array
763
2.39k
        uint8_t dc_sign_level_coeff = (uint8_t)cul_level_cb;
764
2.39k
        svt_aom_neighbor_array_unit_mode_write_pu(cb_dc_sign_level_coeff_na,
765
2.39k
                                                  &dc_sign_level_coeff,
766
2.39k
                                                  uv_x,
767
2.39k
                                                  uv_y,
768
2.39k
                                                  tx_width_uv,
769
2.39k
                                                  tx_height_uv,
770
2.39k
                                                  NEIGHBOR_ARRAY_UNIT_TOP_AND_LEFT_ONLY_MASK);
771
        // Update the cr DC Sign Level Coeff Neighbor Array
772
2.39k
        dc_sign_level_coeff = (uint8_t)cul_level_cr;
773
2.39k
        svt_aom_neighbor_array_unit_mode_write_pu(cr_dc_sign_level_coeff_na,
774
2.39k
                                                  &dc_sign_level_coeff,
775
2.39k
                                                  uv_x,
776
2.39k
                                                  uv_y,
777
2.39k
                                                  tx_width_uv,
778
2.39k
                                                  tx_height_uv,
779
2.39k
                                                  NEIGHBOR_ARRAY_UNIT_TOP_AND_LEFT_ONLY_MASK);
780
781
2.39k
        ec_ctx->coded_area_sb_uv += tx_width_uv * tx_height_uv;
782
2.39k
    }
783
2.39k
}
784
785
/************************************
786
******* Av1EncodeTuCoeff
787
**************************************/
788
static EbErrorType av1_encode_coeff_1d(PictureControlSet* pcs, EntropyCodingContext* ec_ctx,
789
                                       FRAME_CONTEXT* frame_context, AomWriter* ec_writer, EcBlkStruct* blk_ptr,
790
                                       uint32_t blk_org_x, uint32_t blk_org_y, uint32_t intraLumaDir,
791
                                       BlockSize luma_bsize, EbPictureBufferDesc* coeff_ptr,
792
                                       NeighborArrayUnit* luma_dc_sign_level_coeff_na,
793
                                       NeighborArrayUnit* cr_dc_sign_level_coeff_na,
794
6.65k
                                       NeighborArrayUnit* cb_dc_sign_level_coeff_na) {
795
6.65k
    EbErrorType       return_error = EB_ErrorNone;
796
6.65k
    MbModeInfo* const mbmi         = ec_ctx->mbmi;
797
6.65k
    const int32_t     is_inter     = is_inter_mode(mbmi->block_mi.mode) || mbmi->block_mi.use_intrabc;
798
6.65k
    if (mbmi->block_mi.tx_depth) {
799
2.39k
        av1_encode_tx_coef_y(pcs,
800
2.39k
                             ec_ctx,
801
2.39k
                             frame_context,
802
2.39k
                             ec_writer,
803
2.39k
                             mbmi,
804
2.39k
                             blk_ptr,
805
2.39k
                             blk_org_x,
806
2.39k
                             blk_org_y,
807
2.39k
                             intraLumaDir,
808
2.39k
                             luma_bsize,
809
2.39k
                             coeff_ptr,
810
2.39k
                             luma_dc_sign_level_coeff_na);
811
812
2.39k
        av1_encode_tx_coef_uv(pcs,
813
2.39k
                              ec_ctx,
814
2.39k
                              frame_context,
815
2.39k
                              ec_writer,
816
2.39k
                              blk_ptr,
817
2.39k
                              blk_org_x,
818
2.39k
                              blk_org_y,
819
2.39k
                              intraLumaDir,
820
2.39k
                              coeff_ptr,
821
2.39k
                              cr_dc_sign_level_coeff_na,
822
2.39k
                              cb_dc_sign_level_coeff_na);
823
4.26k
    } else {
824
        // Transform partitioning free path (except the 128x128 case).
825
        // tx_depth is 0 in this branch.
826
4.26k
        int32_t cul_level_y, cul_level_cb = 0, cul_level_cr = 0;
827
828
4.26k
        const bool     has_uv       = is_chroma_reference(blk_org_y >> 2, blk_org_x >> 2, luma_bsize, 1, 1);
829
4.26k
        const uint8_t  tx_depth     = 0;
830
4.26k
        const uint16_t txb_count    = tx_blocks_per_depth[luma_bsize][tx_depth];
831
4.26k
        const TxSize   tx_size      = tx_depth_to_tx_size[tx_depth][luma_bsize];
832
4.26k
        const int      tx_width     = tx_size_wide[tx_size];
833
4.26k
        const int      tx_height    = tx_size_high[tx_size];
834
4.26k
        const TxSize   tx_size_uv   = av1_get_max_uv_txsize(luma_bsize, 1, 1);
835
4.26k
        const int      tx_width_uv  = tx_size_wide[tx_size_uv];
836
4.26k
        const int      tx_height_uv = tx_size_high[tx_size_uv];
837
        // bsize_uv is only consumed under `has_uv`, but hoisting unconditionally is cheaper than branching twice.
838
4.26k
        const BlockSize bsize_uv = has_uv ? get_plane_block_size(luma_bsize, 1, 1) : 0;
839
8.52k
        for (uint8_t txb_itr = 0; txb_itr < txb_count; txb_itr++) {
840
            // Hoist tx_org + ROUND_UV: reused by up to 7 sites per iteration.
841
4.26k
            const Position org  = tx_org[luma_bsize][is_inter][tx_depth][txb_itr];
842
4.26k
            const uint32_t tx_x = blk_org_x + org.x;
843
4.26k
            const uint32_t tx_y = blk_org_y + org.y;
844
4.26k
            const uint32_t uv_x = ROUND_UV(tx_x) >> 1;
845
4.26k
            const uint32_t uv_y = ROUND_UV(tx_y) >> 1;
846
847
4.26k
            int32_t* coeff_buffer = (int32_t*)coeff_ptr->y_buffer + ec_ctx->coded_area_sb;
848
849
4.26k
            {
850
4.26k
                int16_t txb_skip_ctx = 0;
851
4.26k
                int16_t dc_sign_ctx  = 0;
852
853
4.26k
                svt_aom_get_txb_ctx(pcs,
854
4.26k
                                    COMPONENT_LUMA,
855
4.26k
                                    luma_dc_sign_level_coeff_na,
856
4.26k
                                    tx_x,
857
4.26k
                                    tx_y,
858
4.26k
                                    luma_bsize,
859
4.26k
                                    tx_size,
860
4.26k
                                    &txb_skip_ctx,
861
4.26k
                                    &dc_sign_ctx);
862
863
4.26k
                cul_level_y = av1_write_coeffs_txb_1d(pcs->ppcs,
864
4.26k
                                                      frame_context,
865
4.26k
                                                      mbmi,
866
4.26k
                                                      ec_writer,
867
4.26k
                                                      blk_ptr,
868
4.26k
                                                      tx_size,
869
4.26k
                                                      txb_itr,
870
4.26k
                                                      intraLumaDir,
871
4.26k
                                                      coeff_buffer,
872
4.26k
                                                      COMPONENT_LUMA,
873
4.26k
                                                      txb_skip_ctx,
874
4.26k
                                                      dc_sign_ctx,
875
4.26k
                                                      blk_ptr->eob.y[txb_itr],
876
4.26k
                                                      ec_ctx);
877
4.26k
            }
878
879
4.26k
            if (has_uv) {
880
                // cb
881
4.26k
                coeff_buffer = (int32_t*)coeff_ptr->u_buffer + ec_ctx->coded_area_sb_uv;
882
4.26k
                {
883
4.26k
                    int16_t txb_skip_ctx = 0;
884
4.26k
                    int16_t dc_sign_ctx  = 0;
885
886
4.26k
                    svt_aom_get_txb_ctx(pcs,
887
4.26k
                                        COMPONENT_CHROMA,
888
4.26k
                                        cb_dc_sign_level_coeff_na,
889
4.26k
                                        uv_x,
890
4.26k
                                        uv_y,
891
4.26k
                                        bsize_uv,
892
4.26k
                                        tx_size_uv,
893
4.26k
                                        &txb_skip_ctx,
894
4.26k
                                        &dc_sign_ctx);
895
896
4.26k
                    cul_level_cb = av1_write_coeffs_txb_1d(pcs->ppcs,
897
4.26k
                                                           frame_context,
898
4.26k
                                                           mbmi,
899
4.26k
                                                           ec_writer,
900
4.26k
                                                           blk_ptr,
901
4.26k
                                                           tx_size_uv,
902
4.26k
                                                           txb_itr,
903
4.26k
                                                           intraLumaDir,
904
4.26k
                                                           coeff_buffer,
905
4.26k
                                                           COMPONENT_CHROMA,
906
4.26k
                                                           txb_skip_ctx,
907
4.26k
                                                           dc_sign_ctx,
908
4.26k
                                                           blk_ptr->eob.u[txb_itr],
909
4.26k
                                                           ec_ctx);
910
4.26k
                }
911
912
                // cr
913
4.26k
                coeff_buffer = (int32_t*)coeff_ptr->v_buffer + ec_ctx->coded_area_sb_uv;
914
4.26k
                {
915
4.26k
                    int16_t txb_skip_ctx = 0;
916
4.26k
                    int16_t dc_sign_ctx  = 0;
917
918
4.26k
                    svt_aom_get_txb_ctx(pcs,
919
4.26k
                                        COMPONENT_CHROMA,
920
4.26k
                                        cr_dc_sign_level_coeff_na,
921
4.26k
                                        uv_x,
922
4.26k
                                        uv_y,
923
4.26k
                                        bsize_uv,
924
4.26k
                                        tx_size_uv,
925
4.26k
                                        &txb_skip_ctx,
926
4.26k
                                        &dc_sign_ctx);
927
928
4.26k
                    cul_level_cr = av1_write_coeffs_txb_1d(pcs->ppcs,
929
4.26k
                                                           frame_context,
930
4.26k
                                                           mbmi,
931
4.26k
                                                           ec_writer,
932
4.26k
                                                           blk_ptr,
933
4.26k
                                                           tx_size_uv,
934
4.26k
                                                           txb_itr,
935
4.26k
                                                           intraLumaDir,
936
4.26k
                                                           coeff_buffer,
937
4.26k
                                                           COMPONENT_CHROMA,
938
4.26k
                                                           txb_skip_ctx,
939
4.26k
                                                           dc_sign_ctx,
940
4.26k
                                                           blk_ptr->eob.v[txb_itr],
941
4.26k
                                                           ec_ctx);
942
4.26k
                }
943
4.26k
            }
944
945
            // Update the luma Dc Sign Level Coeff Neighbor Array
946
4.26k
            uint8_t dc_sign_level_coeff = (uint8_t)cul_level_y;
947
4.26k
            svt_aom_neighbor_array_unit_mode_write_pu(luma_dc_sign_level_coeff_na,
948
4.26k
                                                      &dc_sign_level_coeff,
949
4.26k
                                                      tx_x,
950
4.26k
                                                      tx_y,
951
4.26k
                                                      tx_width,
952
4.26k
                                                      tx_height,
953
4.26k
                                                      NEIGHBOR_ARRAY_UNIT_TOP_AND_LEFT_ONLY_MASK);
954
955
            // Update the cb Dc Sign Level Coeff Neighbor Array
956
4.26k
            if (has_uv) {
957
4.26k
                dc_sign_level_coeff = (uint8_t)cul_level_cb;
958
4.26k
                svt_aom_neighbor_array_unit_mode_write_pu(cb_dc_sign_level_coeff_na,
959
4.26k
                                                          &dc_sign_level_coeff,
960
4.26k
                                                          uv_x,
961
4.26k
                                                          uv_y,
962
4.26k
                                                          tx_width_uv,
963
4.26k
                                                          tx_height_uv,
964
4.26k
                                                          NEIGHBOR_ARRAY_UNIT_TOP_AND_LEFT_ONLY_MASK);
965
                // Update the cr DC Sign Level Coeff Neighbor Array
966
4.26k
                dc_sign_level_coeff = (uint8_t)cul_level_cr;
967
4.26k
                svt_aom_neighbor_array_unit_mode_write_pu(cr_dc_sign_level_coeff_na,
968
4.26k
                                                          &dc_sign_level_coeff,
969
4.26k
                                                          uv_x,
970
4.26k
                                                          uv_y,
971
4.26k
                                                          tx_width_uv,
972
4.26k
                                                          tx_height_uv,
973
4.26k
                                                          NEIGHBOR_ARRAY_UNIT_TOP_AND_LEFT_ONLY_MASK);
974
4.26k
                ec_ctx->coded_area_sb_uv += tx_width_uv * tx_height_uv;
975
4.26k
            }
976
4.26k
            ec_ctx->coded_area_sb += tx_width * tx_height;
977
4.26k
        }
978
4.26k
    }
979
6.65k
    return return_error;
980
6.65k
}
981
982
/*********************************************************************
983
* encode_partition_av1
984
*   Encodes the partition
985
*********************************************************************/
986
// Return the number of elements in the partition CDF when
987
// partitioning the (square) block with luma block size of bsize.
988
190k
int32_t svt_aom_partition_cdf_length(BlockSize bsize) {
989
190k
    if (bsize <= BLOCK_8X8) {
990
141k
        return PARTITION_TYPES;
991
141k
    } else if (bsize == BLOCK_128X128) {
992
0
        return EXT_PARTITION_TYPES - 2;
993
48.5k
    } else {
994
48.5k
        return EXT_PARTITION_TYPES;
995
48.5k
    }
996
190k
}
997
998
static void encode_partition_av1(PictureControlSet* pcs, FRAME_CONTEXT* frame_context, AomWriter* ec_writer,
999
                                 BlockSize bsize, PartitionType p, uint32_t blk_org_x, uint32_t blk_org_y,
1000
200k
                                 NeighborArrayUnit* partition_context_na) {
1001
200k
    const int32_t is_partition_point = bsize >= BLOCK_8X8;
1002
1003
200k
    if (!is_partition_point) {
1004
0
        return;
1005
0
    }
1006
1007
200k
    const int32_t hbs      = (mi_size_wide[bsize] << 2) >> 1;
1008
200k
    const int32_t has_rows = (blk_org_y + hbs) < pcs->ppcs->aligned_height;
1009
200k
    const int32_t has_cols = (blk_org_x + hbs) < pcs->ppcs->aligned_width;
1010
1011
200k
    const uint8_t above_byte = *svt_aom_na_top_ptr_pu(partition_context_na, blk_org_x);
1012
200k
    const uint8_t left_byte  = *svt_aom_na_left_ptr_pu(partition_context_na, blk_org_y);
1013
1014
200k
    uint32_t context_index = 0;
1015
1016
200k
    PartitionContextType above_ctx = (above_byte == INVALID_NEIGHBOR_DATA) ? 0 : (PartitionContextType)above_byte;
1017
200k
    PartitionContextType left_ctx  = (left_byte == INVALID_NEIGHBOR_DATA) ? 0 : (PartitionContextType)left_byte;
1018
1019
200k
    const int32_t bsl   = mi_size_wide_log2[bsize] - mi_size_wide_log2[BLOCK_8X8];
1020
200k
    int32_t       above = (above_ctx >> bsl) & 1, left = (left_ctx >> bsl) & 1;
1021
1022
200k
    assert(mi_size_wide_log2[bsize] == mi_size_high_log2[bsize]);
1023
200k
    assert(bsl >= 0);
1024
200k
    assert(p < CDF_SIZE(EXT_PARTITION_TYPES));
1025
1026
200k
    context_index = (left * 2 + above) + bsl * PARTITION_PLOFFSET;
1027
1028
200k
    if (!has_rows && !has_cols) {
1029
456
        assert(p == PARTITION_SPLIT);
1030
456
        return;
1031
456
    }
1032
1033
199k
    if (has_rows && has_cols) {
1034
190k
        aom_write_symbol(
1035
190k
            ec_writer, p, frame_context->partition_cdf[context_index], svt_aom_partition_cdf_length(bsize));
1036
190k
    } else if (!has_rows && has_cols) {
1037
4.62k
        AomCdfProb cdf[CDF_SIZE(2)];
1038
4.62k
        partition_gather_vert_alike(cdf, frame_context->partition_cdf[context_index], bsize);
1039
4.62k
        aom_write_symbol(ec_writer, p == PARTITION_SPLIT, cdf, 2);
1040
4.80k
    } else {
1041
4.80k
        AomCdfProb cdf[CDF_SIZE(2)];
1042
4.80k
        partition_gather_horz_alike(cdf, frame_context->partition_cdf[context_index], bsize);
1043
4.80k
        aom_write_symbol(ec_writer, p == PARTITION_SPLIT, cdf, 2);
1044
4.80k
    }
1045
1046
199k
    return;
1047
200k
}
1048
1049
146k
uint8_t av1_get_skip_context(const MacroBlockD* xd) {
1050
146k
    const MbModeInfo* const above_mi   = xd->above_mbmi;
1051
146k
    const MbModeInfo* const left_mi    = xd->left_mbmi;
1052
146k
    const uint8_t           above_skip = above_mi ? above_mi->block_mi.skip : 0;
1053
146k
    const uint8_t           left_skip  = left_mi ? left_mi->block_mi.skip : 0;
1054
146k
    return above_skip + left_skip;
1055
146k
}
1056
1057
/*********************************************************************
1058
 * encode_skip_coeff_av1
1059
 *   Encodes the skip coefficient flag
1060
 *********************************************************************/
1061
static void encode_skip_coeff_av1(EcBlkStruct* blk_ptr, FRAME_CONTEXT* frame_context, AomWriter* ec_writer,
1062
146k
                                  bool skip_coeff_flag) {
1063
    // TODO: need to code in syntax for segmentation map + skip
1064
146k
    uint8_t ctx = av1_get_skip_context(blk_ptr->av1xd);
1065
146k
    aom_write_symbol(ec_writer, skip_coeff_flag ? 1 : 0, frame_context->skip_cdfs[ctx], 2);
1066
146k
}
1067
1068
/* Get the contexts (left and top) for writing the intra luma mode for key frames. Intended to
1069
 * be used for key frame only. */
1070
291k
void svt_aom_get_kf_y_mode_ctx(const MacroBlockD* xd, uint8_t* above_ctx, uint8_t* left_ctx) {
1071
291k
    PredictionMode intra_luma_left_mode = DC_PRED;
1072
291k
    PredictionMode intra_luma_top_mode  = DC_PRED;
1073
291k
    if (xd->left_available) {
1074
        // When called for key frame, neighbouring mode should be intra
1075
245k
        assert(!is_inter_block(&xd->mi[-1]->block_mi) || is_intrabc_block(&xd->mi[-1]->block_mi));
1076
245k
        intra_luma_left_mode = xd->mi[-1]->block_mi.mode;
1077
245k
    }
1078
291k
    if (xd->up_available) {
1079
        // When called for key frame, neighbouring mode should be intra
1080
243k
        assert(!is_inter_block(&xd->mi[-xd->mi_stride]->block_mi) ||
1081
243k
               is_intrabc_block(&xd->mi[-xd->mi_stride]->block_mi));
1082
243k
        intra_luma_top_mode = xd->mi[-xd->mi_stride]->block_mi.mode;
1083
243k
    }
1084
1085
291k
    *above_ctx = intra_mode_context[intra_luma_top_mode];
1086
291k
    *left_ctx  = intra_mode_context[intra_luma_left_mode];
1087
291k
}
1088
1089
/*********************************************************************
1090
*   Encodes the Intra Luma Mode for a key frame
1091
*********************************************************************/
1092
static void encode_intra_luma_mode_kf_av1(FRAME_CONTEXT* frame_context, AomWriter* ec_writer, MbModeInfo* mbmi,
1093
146k
                                          EcBlkStruct* blk_ptr, BlockSize bsize, uint32_t luma_mode) {
1094
146k
    uint8_t top_context, left_context;
1095
146k
    svt_aom_get_kf_y_mode_ctx(blk_ptr->av1xd, &top_context, &left_context);
1096
146k
    aom_write_symbol(ec_writer, luma_mode, frame_context->kf_y_cdf[top_context][left_context], INTRA_MODES);
1097
1098
146k
    if (bsize >= BLOCK_8X8 && av1_is_directional_mode(mbmi->block_mi.mode)) {
1099
0
        aom_write_symbol(ec_writer,
1100
0
                         mbmi->block_mi.angle_delta[PLANE_TYPE_Y] + MAX_ANGLE_DELTA,
1101
0
                         frame_context->angle_delta_cdf[luma_mode - V_PRED],
1102
0
                         2 * MAX_ANGLE_DELTA + 1);
1103
0
    }
1104
1105
146k
    return;
1106
146k
}
1107
1108
/*********************************************************************
1109
* encode_intra_luma_mode_nonkey_av1
1110
*   Encodes the Intra Luma Mode for non Key frames
1111
*********************************************************************/
1112
static void encode_intra_luma_mode_nonkey_av1(FRAME_CONTEXT* frame_context, AomWriter* ec_writer, MbModeInfo* mbmi,
1113
0
                                              BlockSize bsize, uint32_t luma_mode) {
1114
0
    aom_write_symbol(ec_writer, luma_mode, frame_context->y_mode_cdf[eb_size_group_lookup[bsize]], INTRA_MODES);
1115
1116
0
    if (bsize >= BLOCK_8X8 && av1_is_directional_mode(mbmi->block_mi.mode)) {
1117
0
        aom_write_symbol(ec_writer,
1118
0
                         mbmi->block_mi.angle_delta[PLANE_TYPE_Y] + MAX_ANGLE_DELTA,
1119
0
                         frame_context->angle_delta_cdf[luma_mode - V_PRED],
1120
0
                         2 * MAX_ANGLE_DELTA + 1);
1121
0
    }
1122
1123
0
    return;
1124
0
}
1125
1126
0
static void write_cfl_alphas(FRAME_CONTEXT* const ec_ctx, int32_t idx, int32_t joint_sign, AomWriter* w) {
1127
0
    aom_write_symbol(w, joint_sign, ec_ctx->cfl_sign_cdf, CFL_JOINT_SIGNS);
1128
    // Magnitudes are only signaled for nonzero codes.
1129
0
    if (CFL_SIGN_U(joint_sign) != CFL_SIGN_ZERO) {
1130
0
        AomCdfProb* cdf_u = ec_ctx->cfl_alpha_cdf[CFL_CONTEXT_U(joint_sign)];
1131
0
        aom_write_symbol(w, CFL_IDX_U(idx), cdf_u, CFL_ALPHABET_SIZE);
1132
0
    }
1133
0
    if (CFL_SIGN_V(joint_sign) != CFL_SIGN_ZERO) {
1134
0
        AomCdfProb* cdf_v = ec_ctx->cfl_alpha_cdf[CFL_CONTEXT_V(joint_sign)];
1135
0
        aom_write_symbol(w, CFL_IDX_V(idx), cdf_v, CFL_ALPHABET_SIZE);
1136
0
    }
1137
0
}
1138
1139
/*********************************************************************
1140
* encode_intra_chroma_mode_av1
1141
*   Encodes the Intra Chroma Mode
1142
*********************************************************************/
1143
static void encode_intra_chroma_mode_av1(FRAME_CONTEXT* frame_context, AomWriter* ec_writer, MbModeInfo* mbmi,
1144
                                         BlockSize bsize, uint32_t luma_mode, uint32_t chroma_mode,
1145
146k
                                         uint8_t cflAllowed) {
1146
146k
    aom_write_symbol(
1147
146k
        ec_writer, chroma_mode, frame_context->uv_mode_cdf[cflAllowed][luma_mode], UV_INTRA_MODES - !cflAllowed);
1148
1149
146k
    if (chroma_mode == UV_CFL_PRED) {
1150
0
        write_cfl_alphas(frame_context, mbmi->block_mi.cfl_alpha_idx, mbmi->block_mi.cfl_alpha_signs, ec_writer);
1151
0
    }
1152
1153
146k
    if (bsize >= BLOCK_8X8 && av1_is_directional_mode(get_uv_mode(mbmi->block_mi.uv_mode))) {
1154
0
        aom_write_symbol(ec_writer,
1155
0
                         mbmi->block_mi.angle_delta[PLANE_TYPE_UV] + MAX_ANGLE_DELTA,
1156
0
                         frame_context->angle_delta_cdf[chroma_mode - V_PRED],
1157
0
                         2 * MAX_ANGLE_DELTA + 1);
1158
0
    }
1159
1160
146k
    return;
1161
146k
}
1162
1163
145k
uint8_t av1_get_skip_mode_context(const MacroBlockD* xd) {
1164
145k
    const MbModeInfo* const above_mi        = xd->above_mbmi;
1165
145k
    const MbModeInfo* const left_mi         = xd->left_mbmi;
1166
145k
    const int               above_skip_mode = above_mi ? above_mi->block_mi.skip_mode : 0;
1167
145k
    const int               left_skip_mode  = left_mi ? left_mi->block_mi.skip_mode : 0;
1168
145k
    return above_skip_mode + left_skip_mode;
1169
145k
}
1170
1171
/*********************************************************************
1172
 * encode_skip_mode_av1
1173
 *   Encodes the skip Mode flag
1174
 *********************************************************************/
1175
static void encode_skip_mode_av1(const EcBlkStruct* blk_ptr, FRAME_CONTEXT* frame_context, AomWriter* ec_writer,
1176
0
                                 bool skip_mode_flag) {
1177
    // TODO: not coded in syntax for skip mode/ref-frame/global-mv in segmentation map
1178
0
    const uint8_t context_index = av1_get_skip_mode_context(blk_ptr->av1xd);
1179
1180
0
    aom_write_symbol(ec_writer, skip_mode_flag ? 1 : 0, frame_context->skip_mode_cdfs[context_index], 2);
1181
0
}
1182
1183
/*******************************************************************************
1184
* The mode info data structure has a one element border above and to the
1185
* left of the entries corresponding to real macroblocks.
1186
* The prediction flags in these dummy entries are initialized to 0.
1187
* 0 - inter/inter, inter/--, --/inter, --/--
1188
* 1 - intra/inter, inter/intra
1189
* 2 - intra/--, --/intra
1190
* 3 - intra/intra
1191
 ******************************************************************************/
1192
145k
uint8_t svt_av1_get_intra_inter_context(const MacroBlockD* xd) {
1193
145k
    const MbModeInfo* const above_mbmi = xd->above_mbmi;
1194
145k
    const MbModeInfo* const left_mbmi  = xd->left_mbmi;
1195
145k
    const int               has_above  = xd->up_available;
1196
145k
    const int               has_left   = xd->left_available;
1197
1198
145k
    if (has_above && has_left) { // both edges available
1199
104k
        const int above_intra = !is_inter_block(&above_mbmi->block_mi);
1200
104k
        const int left_intra  = !is_inter_block(&left_mbmi->block_mi);
1201
18.4E
        return left_intra && above_intra ? 3 : left_intra || above_intra;
1202
104k
    } else if (has_above || has_left) { // one edge available
1203
36.1k
        return 2 * !is_inter_block(has_above ? &above_mbmi->block_mi : &left_mbmi->block_mi);
1204
36.1k
    } else {
1205
5.04k
        return 0;
1206
5.04k
    }
1207
145k
}
1208
1209
/*********************************************************************
1210
 * encode_pred_mode_av1
1211
 *   Encodes the Prediction Mode
1212
 *********************************************************************/
1213
static void write_is_inter(const EcBlkStruct* blk_ptr, FRAME_CONTEXT* frame_context, AomWriter* ec_writer,
1214
0
                           int32_t is_inter) {
1215
0
    const uint8_t ctx = svt_av1_get_intra_inter_context(blk_ptr->av1xd);
1216
0
    aom_write_symbol(ec_writer, is_inter, frame_context->intra_inter_cdf[ctx], 2);
1217
0
}
1218
1219
//****************************************************************************************************//
1220
1221
/*********************************************************************
1222
* svt_aom_motion_mode_allowed
1223
*   checks the motion modes that are allowed for the current block
1224
*********************************************************************/
1225
MotionMode svt_aom_motion_mode_allowed(const PictureControlSet* pcs, uint16_t num_proj_ref,
1226
                                       uint32_t overlappable_neighbors, const BlockSize bsize, MvReferenceFrame rf0,
1227
0
                                       MvReferenceFrame rf1, PredictionMode mode) {
1228
0
    FrameHeader* frm_hdr = &pcs->ppcs->frm_hdr;
1229
0
    if (!frm_hdr->is_motion_mode_switchable) {
1230
0
        return SIMPLE_TRANSLATION;
1231
0
    }
1232
1233
0
    if (frm_hdr->force_integer_mv == 0) {
1234
0
        const TransformationType gm_type = pcs->ppcs->global_motion[rf0].wmtype;
1235
0
        if (is_global_mv_block(mode, bsize, gm_type)) {
1236
0
            return SIMPLE_TRANSLATION;
1237
0
        }
1238
0
    }
1239
0
    if (is_motion_variation_allowed_bsize(bsize) && is_inter_singleref_mode(mode) && rf1 != INTRA_FRAME &&
1240
0
        !(rf1 > INTRA_FRAME)) // is_motion_variation_allowed_compound
1241
0
    {
1242
0
        if (overlappable_neighbors == 0) {
1243
0
            return SIMPLE_TRANSLATION;
1244
0
        }
1245
1246
0
        if (frm_hdr->allow_warped_motion &&
1247
            /* TODO(JS): when scale is added, put: !av1_is_scaled(&(xd->block_refs[0]->sf)) && */
1248
0
            num_proj_ref >= 1) {
1249
0
            if (frm_hdr->force_integer_mv) {
1250
0
                return OBMC_CAUSAL;
1251
0
            }
1252
0
            return WARPED_CAUSAL;
1253
0
        }
1254
0
        return OBMC_CAUSAL;
1255
0
    } else {
1256
0
        return SIMPLE_TRANSLATION;
1257
0
    }
1258
0
}
1259
1260
/*********************************************************************
1261
* write_motion_mode
1262
*   Encodes the Motion Mode (obmc or warped)
1263
*********************************************************************/
1264
static void write_motion_mode(FRAME_CONTEXT* frame_context, AomWriter* ec_writer, BlockSize bsize, MbModeInfo* mbmi,
1265
                              MotionMode motion_mode, MvReferenceFrame rf0, MvReferenceFrame rf1, EcBlkStruct* blk_ptr,
1266
0
                              PictureControlSet* pcs) {
1267
0
    MotionMode last_motion_mode_allowed = svt_aom_motion_mode_allowed(
1268
0
        pcs, mbmi->block_mi.num_proj_ref, blk_ptr->overlappable_neighbors, bsize, rf0, rf1, mbmi->block_mi.mode);
1269
0
    switch (last_motion_mode_allowed) {
1270
0
    case SIMPLE_TRANSLATION:
1271
0
        break;
1272
0
    case OBMC_CAUSAL:
1273
0
        aom_write_symbol(ec_writer, motion_mode == OBMC_CAUSAL, frame_context->obmc_cdf[bsize], 2);
1274
0
        break;
1275
0
    default:
1276
0
        aom_write_symbol(ec_writer, motion_mode, frame_context->motion_mode_cdf[bsize], MOTION_MODES);
1277
0
    }
1278
1279
0
    return;
1280
0
}
1281
1282
//****************************************************************************************************//
1283
1284
5.67k
EbErrorType svt_aom_encode_slice_finish(EntropyCoder* ec) {
1285
5.67k
    EbErrorType return_error = EB_ErrorNone;
1286
1287
5.67k
    aom_stop_encode(&ec->ec_writer);
1288
1289
5.67k
    return return_error;
1290
5.67k
}
1291
1292
5.67k
EbErrorType svt_aom_reset_entropy_coder(EncodeContext* enc_ctx, EntropyCoder* ec, uint32_t qp, SliceType slice_type) {
1293
5.67k
    EbErrorType return_error = EB_ErrorNone;
1294
1295
5.67k
    (void)enc_ctx;
1296
5.67k
    (void)slice_type;
1297
5.67k
    svt_av1_default_coef_probs(ec->fc, qp);
1298
5.67k
    svt_aom_init_mode_probs(ec->fc);
1299
1300
5.67k
    return return_error;
1301
5.67k
}
1302
1303
5.67k
static void entropy_tile_info_dctor(EbPtr p) {
1304
5.67k
    EntropyTileInfo* obj = (EntropyTileInfo*)p;
1305
5.67k
    EB_DELETE(obj->ec);
1306
5.67k
}
1307
1308
5.67k
EbErrorType svt_aom_entropy_tile_info_ctor(EntropyTileInfo* eti, uint32_t buf_size) {
1309
5.67k
    EbErrorType return_error = EB_ErrorNone;
1310
5.67k
    eti->dctor               = entropy_tile_info_dctor;
1311
5.67k
    EB_NEW(eti->ec, svt_aom_entropy_coder_ctor, buf_size);
1312
5.67k
    eti->entropy_coding_tile_done = false;
1313
5.67k
    return return_error;
1314
5.67k
}
1315
1316
2.66k
static void bitstream_dctor(EbPtr p) {
1317
2.66k
    Bitstream* obj = (Bitstream*)p;
1318
2.66k
    EB_DELETE(obj->output_bitstream_ptr);
1319
2.66k
}
1320
1321
2.66k
EbErrorType svt_aom_bitstream_ctor(Bitstream* bitstream_ptr, uint32_t buffer_size) {
1322
2.66k
    bitstream_ptr->dctor = bitstream_dctor;
1323
2.66k
    EB_NEW(bitstream_ptr->output_bitstream_ptr, svt_aom_output_bitstream_unit_ctor, buffer_size);
1324
2.66k
    return EB_ErrorNone;
1325
2.66k
}
1326
1327
533
void svt_aom_bitstream_reset(Bitstream* bitstream_ptr) {
1328
533
    svt_aom_output_bitstream_reset(bitstream_ptr->output_bitstream_ptr);
1329
533
}
1330
1331
1.06k
int svt_aom_bitstream_get_bytes_count(const Bitstream* bitstream_ptr) {
1332
1.06k
    const OutputBitstreamUnit* unit = bitstream_ptr->output_bitstream_ptr;
1333
1.06k
    return (int)(unit->buffer_av1 - unit->buffer_begin_av1);
1334
1.06k
}
1335
1336
533
void svt_aom_bitstream_copy(const Bitstream* bitstream_ptr, void* dest, int size) {
1337
533
    const OutputBitstreamUnit* unit = bitstream_ptr->output_bitstream_ptr;
1338
533
    svt_memcpy(dest, unit->buffer_begin_av1, size);
1339
533
}
1340
1341
5.67k
static void entropy_coder_dctor(EbPtr p) {
1342
5.67k
    EntropyCoder*        obj                  = (EntropyCoder*)p;
1343
5.67k
    OutputBitstreamUnit* output_bitstream_ptr = (OutputBitstreamUnit*)obj->ec_output_bitstream_ptr;
1344
5.67k
    EB_DELETE(output_bitstream_ptr);
1345
    // EC buffer is owned by OutputBitstreamUnit and freed above; just NULL out.
1346
5.67k
    obj->ec_writer.ec.buf = NULL;
1347
5.67k
    obj->ec_writer.ec.ptr = NULL;
1348
5.67k
    EB_FREE(obj->fc);
1349
5.67k
}
1350
1351
5.67k
EbErrorType svt_aom_entropy_coder_ctor(EntropyCoder* ec, uint32_t buffer_size) {
1352
5.67k
    OutputBitstreamUnit* output_bitstream_ptr;
1353
1354
5.67k
    ec->dctor = entropy_coder_dctor;
1355
1356
5.67k
    EB_MALLOC_OBJECT(ec->fc);
1357
1358
5.67k
    EB_NEW(output_bitstream_ptr, svt_aom_output_bitstream_unit_ctor, buffer_size);
1359
5.67k
    ec->ec_output_bitstream_ptr = output_bitstream_ptr;
1360
1361
    // EC does not allocate its own buffer; it borrows from OutputBitstreamUnit
1362
    // via aom_start_encode() each frame.
1363
5.67k
    svt_od_ec_enc_init(&ec->ec_writer.ec);
1364
1365
5.67k
    return EB_ErrorNone;
1366
5.67k
}
1367
1368
//*******************************************************************************************//
1369
//*******************************************************************************************//
1370
//*******************************************************************************************//
1371
//*******************************************************************************************//
1372
// aom_integer.c
1373
static const size_t   k_maximum_leb_128_size  = 8;
1374
static const uint64_t k_maximum_leb_128_value = 0xFFFFFFFFFFFFFF; // 2 ^ 56 - 1
1375
1376
2.66k
size_t svt_aom_uleb_size_in_bytes(uint64_t value) {
1377
2.66k
    size_t size = 0;
1378
3.50k
    do {
1379
3.50k
        ++size;
1380
3.50k
    } while ((value >>= 7) != 0);
1381
2.66k
    return size;
1382
2.66k
}
1383
1384
1.59k
int32_t svt_aom_uleb_encode(uint64_t value, size_t available, uint8_t* coded_value, size_t* coded_size) {
1385
1.59k
    const size_t leb_size = svt_aom_uleb_size_in_bytes(value);
1386
1.59k
    if (value > k_maximum_leb_128_value || leb_size > k_maximum_leb_128_size || leb_size > available || !coded_value ||
1387
1.59k
        !coded_size) {
1388
0
        return -1;
1389
0
    }
1390
1391
3.61k
    for (size_t i = 0; i < leb_size; ++i) {
1392
2.02k
        uint8_t byte = value & 0x7f;
1393
2.02k
        value >>= 7;
1394
1395
2.02k
        if (value != 0) {
1396
421
            byte |= 0x80; // Signal that more bytes follow.
1397
421
        }
1398
1399
2.02k
        *(coded_value + i) = byte;
1400
2.02k
    }
1401
1402
1.59k
    *coded_size = leb_size;
1403
1.59k
    return 0;
1404
1.59k
}
1405
1406
1.06k
int32_t svt_aom_wb_is_byte_aligned(const AomWriteBitBuffer* wb) {
1407
1.06k
    return (wb->bit_offset % CHAR_BIT == 0);
1408
1.06k
}
1409
1410
4.78k
uint32_t svt_aom_wb_bytes_written(const AomWriteBitBuffer* wb) {
1411
4.78k
    return wb->bit_offset / CHAR_BIT + (wb->bit_offset % CHAR_BIT > 0);
1412
4.78k
}
1413
1414
126k
INLINE static void svt_aom_wb_write_bit_inlined(AomWriteBitBuffer* wb, int32_t bit) {
1415
126k
    const int32_t off = (int32_t)wb->bit_offset;
1416
126k
    const int32_t p   = off / CHAR_BIT;
1417
126k
    const int32_t q   = CHAR_BIT - 1 - off % CHAR_BIT;
1418
126k
    if (q == CHAR_BIT - 1) {
1419
        // zero next char and write bit
1420
17.5k
        wb->bit_buffer[p] = (uint8_t)(bit << q);
1421
109k
    } else {
1422
109k
        wb->bit_buffer[p] &= ~(1 << q);
1423
109k
        wb->bit_buffer[p] |= bit << q;
1424
109k
    }
1425
126k
    wb->bit_offset = off + 1;
1426
126k
}
1427
1428
24.6k
INLINE static void svt_aom_wb_write_literal_inlined(AomWriteBitBuffer* wb, int32_t data, int32_t bits) {
1429
24.6k
    int32_t bit;
1430
118k
    for (bit = bits - 1; bit >= 0; bit--) {
1431
93.8k
        svt_aom_wb_write_bit(wb, (data >> bit) & 1);
1432
93.8k
    }
1433
24.6k
}
1434
1435
126k
void NOINLINE svt_aom_wb_write_bit(AomWriteBitBuffer* wb, int32_t bit) {
1436
126k
    svt_aom_wb_write_bit_inlined(wb, bit);
1437
126k
}
1438
1439
24.6k
void NOINLINE svt_aom_wb_write_literal(AomWriteBitBuffer* wb, int32_t data, int32_t bits) {
1440
24.6k
    svt_aom_wb_write_literal_inlined(wb, data, bits);
1441
24.6k
}
1442
1443
0
void NOINLINE svt_aom_wb_write_inv_signed_literal(AomWriteBitBuffer* wb, int32_t data, int32_t bits) {
1444
0
    svt_aom_wb_write_literal_inlined(wb, data, bits + 1);
1445
0
}
1446
1447
//*******************************************************************************************//
1448
1449
static void write_inter_mode(FRAME_CONTEXT* frame_context, AomWriter* ec_writer, PredictionMode mode,
1450
0
                             const int16_t mode_ctx, uint32_t blk_org_x, uint32_t blk_org_y) {
1451
0
    (void)blk_org_x;
1452
0
    (void)blk_org_y;
1453
0
    int16_t newmv_ctx = mode_ctx & NEWMV_CTX_MASK;
1454
0
    assert(newmv_ctx < NEWMV_MODE_CONTEXTS);
1455
0
    aom_write_symbol(ec_writer, mode != NEWMV, frame_context->newmv_cdf[newmv_ctx], 2);
1456
1457
0
    if (mode != NEWMV) {
1458
0
        const int16_t zeromv_ctx = (mode_ctx >> GLOBALMV_OFFSET) & GLOBALMV_CTX_MASK;
1459
0
        aom_write_symbol(ec_writer, mode != GLOBALMV, frame_context->zeromv_cdf[zeromv_ctx], 2);
1460
1461
0
        if (mode != GLOBALMV) {
1462
0
            int16_t refmv_ctx = (mode_ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;
1463
0
            assert(refmv_ctx < REFMV_MODE_CONTEXTS);
1464
0
            aom_write_symbol(ec_writer, mode != NEARESTMV, frame_context->refmv_cdf[refmv_ctx], 2);
1465
0
        }
1466
0
    }
1467
0
}
1468
1469
//extern INLINE int8_t av1_ref_frame_type(const MvReferenceFrame *const rf);
1470
static void write_drl_idx(FRAME_CONTEXT* frame_context, AomWriter* ec_writer, MbModeInfo* mbmi,
1471
1472
0
                          EcBlkStruct* blk_ptr) {
1473
0
    const int32_t new_mv = mbmi->block_mi.mode == NEWMV || mbmi->block_mi.mode == NEW_NEWMV;
1474
0
    if (new_mv) {
1475
0
        int32_t idx;
1476
0
        for (idx = 0; idx < 2; ++idx) {
1477
0
            if (blk_ptr->drl_ctx[idx] != -1) {
1478
0
                uint8_t drl_ctx = (uint8_t)blk_ptr->drl_ctx[idx];
1479
1480
0
                aom_write_symbol(ec_writer, blk_ptr->drl_index != idx, frame_context->drl_cdf[drl_ctx], 2);
1481
1482
0
                if (blk_ptr->drl_index == idx) {
1483
0
                    return;
1484
0
                }
1485
0
            }
1486
0
        }
1487
0
        return;
1488
0
    }
1489
1490
0
    if (have_nearmv_in_inter_mode(mbmi->block_mi.mode)) {
1491
0
        int32_t idx;
1492
        // TODO(jingning): Temporary solution to compensate the NEARESTMV offset.
1493
0
        for (idx = 1; idx < 3; ++idx) {
1494
0
            if (blk_ptr->drl_ctx_near[idx - 1] != -1) {
1495
0
                uint8_t drl_ctx = (uint8_t)blk_ptr->drl_ctx_near[idx - 1];
1496
1497
0
                aom_write_symbol(ec_writer, blk_ptr->drl_index != (idx - 1), frame_context->drl_cdf[drl_ctx], 2);
1498
1499
0
                if (blk_ptr->drl_index == (idx - 1)) {
1500
0
                    return;
1501
0
                }
1502
0
            }
1503
0
        }
1504
0
        return;
1505
0
    }
1506
0
}
1507
1508
0
static void encode_mv_component(AomWriter* w, int32_t comp, NmvComponent* mvcomp, MvSubpelPrecision precision) {
1509
0
    int32_t       offset;
1510
0
    const int32_t sign     = comp < 0;
1511
0
    const int32_t mag      = sign ? -comp : comp;
1512
0
    const int32_t mv_class = svt_av1_get_mv_class(mag - 1, &offset);
1513
0
    const int32_t d        = offset >> 3; // int32_t mv data
1514
0
    const int32_t fr       = (offset >> 1) & 3; // fractional mv data
1515
0
    const int32_t hp       = offset & 1; // high precision mv data
1516
1517
0
    assert(comp != 0);
1518
1519
    // Sign
1520
0
    aom_write_symbol(w, sign, mvcomp->sign_cdf, 2);
1521
1522
    // Class
1523
0
    aom_write_symbol(w, mv_class, mvcomp->classes_cdf, MV_CLASSES);
1524
1525
    // Integer bits
1526
0
    if (mv_class == MV_CLASS_0) {
1527
0
        aom_write_symbol(w, d, mvcomp->class0_cdf, CLASS0_SIZE);
1528
0
    } else {
1529
0
        int32_t       i;
1530
0
        const int32_t n = mv_class + CLASS0_BITS - 1; // number of bits
1531
0
        for (i = 0; i < n; ++i) {
1532
0
            aom_write_symbol(w, (d >> i) & 1, mvcomp->bits_cdf[i], 2);
1533
0
        }
1534
0
    }
1535
    // Fractional bits
1536
0
    if (precision > MV_SUBPEL_NONE) {
1537
0
        aom_write_symbol(w, fr, mv_class == MV_CLASS_0 ? mvcomp->class0_fp_cdf[d] : mvcomp->fp_cdf, MV_FP_SIZE);
1538
0
    }
1539
1540
    // High precision bit
1541
0
    if (precision > MV_SUBPEL_LOW_PRECISION) {
1542
0
        aom_write_symbol(w, hp, mv_class == MV_CLASS_0 ? mvcomp->class0_hp_cdf : mvcomp->hp_cdf, 2);
1543
0
    }
1544
0
}
1545
1546
// can't mark the parameter as const due to MSVC not supporting c99 fully.
1547
#ifdef _MSC_VER
1548
static MvJointType av1_get_mv_joint_diff(const int32_t diff[2]) {
1549
#else
1550
0
static MvJointType av1_get_mv_joint_diff(const int32_t diff[const 2]) {
1551
0
#endif
1552
0
    if (diff[0] == 0) {
1553
0
        return diff[1] == 0 ? MV_JOINT_ZERO : MV_JOINT_HNZVZ;
1554
0
    }
1555
0
    return diff[1] == 0 ? MV_JOINT_HZVNZ : MV_JOINT_HNZVNZ;
1556
0
}
1557
1558
void svt_av1_encode_mv(PictureParentControlSet* pcs, AomWriter* ec_writer, const Mv* mv, const Mv* ref,
1559
0
                       NmvContext* mvctx, int32_t usehp) {
1560
    // The y-component (row component) of the MV is coded first
1561
0
    int32_t           diff[2] = {mv->y - ref->y, mv->x - ref->x};
1562
0
    const MvJointType j       = av1_get_mv_joint_diff(diff);
1563
1564
0
    if (pcs->frm_hdr.force_integer_mv) {
1565
0
        usehp = MV_SUBPEL_NONE;
1566
0
    }
1567
0
    aom_write_symbol(ec_writer, j, mvctx->joints_cdf, MV_JOINTS);
1568
0
    if (mv_joint_vertical(j)) {
1569
0
        encode_mv_component(ec_writer, diff[0], &mvctx->comps[0], (MvSubpelPrecision)usehp);
1570
0
    }
1571
1572
0
    if (mv_joint_horizontal(j)) {
1573
0
        encode_mv_component(ec_writer, diff[1], &mvctx->comps[1], (MvSubpelPrecision)usehp);
1574
0
    }
1575
1576
    // If auto_mv_step_size is enabled then keep track of the largest
1577
    // motion vector component used.
1578
    //if (cpi->sf.mv.auto_mv_step_size) {
1579
    //    uint32_t maxv = AOMMAX(abs(mv->row), abs(mv->col)) >> 3;
1580
    //    cpi->max_mv_magnitude = AOMMAX(maxv, cpi->max_mv_magnitude);
1581
    //}
1582
0
}
1583
1584
//Returns a context number for the given MB prediction signal
1585
0
static InterpFilter svt_aom_get_ref_filter_type(const BlockModeInfo* ref_mbmi, int dir, MvReferenceFrame ref_frame) {
1586
0
    return ((ref_mbmi->ref_frame[0] == ref_frame || ref_mbmi->ref_frame[1] == ref_frame)
1587
0
                ? av1_extract_interp_filter(ref_mbmi->interp_filters, dir & 0x01)
1588
0
                : SWITCHABLE_FILTERS);
1589
0
}
1590
1591
/* Get the context for the interpolation filter when SWITCHABLE filter is specified
1592
at the frame level.  Used for computing rate and for entropy coding. */
1593
int svt_aom_get_pred_context_switchable_interp(MvReferenceFrame rf0, MvReferenceFrame rf1, const MacroBlockD* xd,
1594
0
                                               int dir) {
1595
    /* When calling the function from MD, the current MBMI may not be updated yet, so pass
1596
       the ref frames instead of getting them from the current mbmi (as you could below):
1597
1598
            const MbModeInfo* const mbmi = &xd->mi[0]->mbmi;
1599
            const int ctx_offset = (mbmi->block_mi.ref_frame[1] > INTRA_FRAME) * INTER_FILTER_COMP_OFFSET;
1600
            assert(dir == 0 || dir == 1);
1601
            const MvReferenceFrame ref_frame = mbmi->block_mi.ref_frame[0];
1602
    */
1603
1604
0
    const int32_t ctx_offset = (rf1 > INTRA_FRAME) * INTER_FILTER_COMP_OFFSET;
1605
0
    assert(dir == 0 || dir == 1);
1606
0
    MvReferenceFrame ref_frame = rf0;
1607
1608
    // Note:
1609
    // The mode info data structure has a one element border above and to the
1610
    // left of the entries corresponding to real macroblocks.
1611
    // The prediction flags in these dummy entries are initialized to 0.
1612
0
    int filter_type_ctx = ctx_offset + (dir & 0x01) * INTER_FILTER_DIR_OFFSET;
1613
0
    int left_type       = SWITCHABLE_FILTERS;
1614
0
    int above_type      = SWITCHABLE_FILTERS;
1615
1616
0
    if (xd->left_available) {
1617
0
        left_type = svt_aom_get_ref_filter_type(&xd->mi[-1]->block_mi, dir, ref_frame);
1618
0
    }
1619
1620
0
    if (xd->up_available) {
1621
0
        above_type = svt_aom_get_ref_filter_type(&xd->mi[-xd->mi_stride]->block_mi, dir, ref_frame);
1622
0
    }
1623
1624
0
    if (left_type == above_type) {
1625
0
        filter_type_ctx += left_type;
1626
0
    } else if (left_type == SWITCHABLE_FILTERS) {
1627
0
        assert(above_type != SWITCHABLE_FILTERS);
1628
0
        filter_type_ctx += above_type;
1629
0
    } else if (above_type == SWITCHABLE_FILTERS) {
1630
0
        assert(left_type != SWITCHABLE_FILTERS);
1631
0
        filter_type_ctx += left_type;
1632
0
    } else {
1633
0
        filter_type_ctx += SWITCHABLE_FILTERS;
1634
0
    }
1635
0
    return filter_type_ctx;
1636
0
}
1637
1638
int svt_aom_is_nontrans_global_motion(const BlockModeInfo* block_mi, const BlockSize bsize,
1639
0
                                      PictureParentControlSet* pcs) {
1640
    // First check if all modes are GLOBALMV
1641
0
    if (block_mi->mode != GLOBALMV && block_mi->mode != GLOBAL_GLOBALMV) {
1642
0
        return 0;
1643
0
    }
1644
1645
0
    if (MIN(mi_size_wide[bsize], mi_size_high[bsize]) < 2) {
1646
0
        return 0;
1647
0
    }
1648
0
    const uint8_t is_compound = is_inter_compound_mode(block_mi->mode);
1649
    // Now check if all global motion is non translational
1650
0
    for (int ref = 0; ref < 1 + is_compound; ++ref) {
1651
0
        if (pcs->global_motion[block_mi->ref_frame[ref]].wmtype == TRANSLATION) {
1652
0
            return 0;
1653
0
        }
1654
0
    }
1655
0
    return 1;
1656
0
}
1657
1658
0
static int av1_is_interp_needed(const BlockModeInfo* block_mi, const BlockSize bsize, PictureParentControlSet* pcs) {
1659
0
    if (block_mi->skip_mode) {
1660
0
        return 0;
1661
0
    }
1662
1663
0
    if (block_mi->motion_mode == WARPED_CAUSAL) {
1664
0
        return 0;
1665
0
    }
1666
1667
0
    if (svt_aom_is_nontrans_global_motion(block_mi, bsize, pcs)) {
1668
0
        return 0;
1669
0
    }
1670
1671
0
    return 1;
1672
0
}
1673
1674
static void write_mb_interp_filter(BlockSize bsize, MvReferenceFrame rf0, MvReferenceFrame rf1,
1675
                                   PictureParentControlSet* pcs, AomWriter* ec_writer, MbModeInfo* mbmi,
1676
0
                                   EcBlkStruct* blk_ptr, EntropyCoder* ec) {
1677
0
    FrameHeader* const frm_hdr = &pcs->frm_hdr;
1678
1679
0
    if (frm_hdr->interpolation_filter != SWITCHABLE || !av1_is_interp_needed(&mbmi->block_mi, bsize, pcs)) {
1680
0
        return;
1681
0
    }
1682
1683
0
    const int max_dir = pcs->scs->seq_header.enable_dual_filter ? 2 : 1;
1684
0
    for (int dir = 0; dir < max_dir; ++dir) {
1685
0
        const int    ctx    = svt_aom_get_pred_context_switchable_interp(rf0, rf1, blk_ptr->av1xd, dir);
1686
0
        InterpFilter filter = av1_extract_interp_filter(mbmi->block_mi.interp_filters, dir);
1687
0
        assert(ctx < SWITCHABLE_FILTER_CONTEXTS);
1688
0
        assert(filter < CDF_SIZE(SWITCHABLE_FILTERS));
1689
0
        aom_write_symbol(ec_writer, filter, ec->fc->switchable_interp_cdf[ctx], SWITCHABLE_FILTERS);
1690
0
    }
1691
0
}
1692
1693
static void write_inter_compound_mode(FRAME_CONTEXT* frame_context, AomWriter* ec_writer, PredictionMode mode,
1694
0
                                      const int16_t mode_ctx) {
1695
0
    assert(is_inter_compound_mode(mode));
1696
0
    aom_write_symbol(
1697
0
        ec_writer, INTER_COMPOUND_OFFSET(mode), frame_context->inter_compound_mode_cdf[mode_ctx], INTER_COMPOUND_MODES);
1698
0
}
1699
1700
int svt_aom_get_reference_mode_context_new(const MacroBlockD* xd);
1701
1702
0
AomCdfProb* svt_aom_get_reference_mode_cdf(const MacroBlockD* xd) {
1703
0
    return xd->tile_ctx->comp_inter_cdf[svt_aom_get_reference_mode_context_new(xd)];
1704
0
}
1705
1706
int svt_aom_get_comp_reference_type_context_new(const MacroBlockD* xd);
1707
1708
// == Uni-directional contexts ==
1709
1710
int svt_av1_get_pred_context_uni_comp_ref_p(const MacroBlockD* xd);
1711
1712
int svt_av1_get_pred_context_uni_comp_ref_p1(const MacroBlockD* xd);
1713
1714
int svt_av1_get_pred_context_uni_comp_ref_p2(const MacroBlockD* xd);
1715
1716
0
AomCdfProb* svt_aom_get_comp_reference_type_cdf(const MacroBlockD* xd) {
1717
0
    const int pred_context = svt_aom_get_comp_reference_type_context_new(xd);
1718
0
    return xd->tile_ctx->comp_ref_type_cdf[pred_context];
1719
0
}
1720
1721
0
AomCdfProb* svt_aom_get_pred_cdf_uni_comp_ref_p(const MacroBlockD* xd) {
1722
0
    const int pred_context = svt_av1_get_pred_context_uni_comp_ref_p(xd);
1723
0
    return xd->tile_ctx->uni_comp_ref_cdf[pred_context][0];
1724
0
}
1725
1726
0
AomCdfProb* svt_aom_get_pred_cdf_uni_comp_ref_p1(const MacroBlockD* xd) {
1727
0
    const int pred_context = svt_av1_get_pred_context_uni_comp_ref_p1(xd);
1728
0
    return xd->tile_ctx->uni_comp_ref_cdf[pred_context][1];
1729
0
}
1730
1731
0
AomCdfProb* svt_aom_get_pred_cdf_uni_comp_ref_p2(const MacroBlockD* xd) {
1732
0
    const int pred_context = svt_av1_get_pred_context_uni_comp_ref_p2(xd);
1733
0
    return xd->tile_ctx->uni_comp_ref_cdf[pred_context][2];
1734
0
}
1735
1736
0
AomCdfProb* svt_aom_get_pred_cdf_comp_ref_p(const MacroBlockD* xd) {
1737
0
    const int pred_context = svt_av1_get_pred_context_comp_ref_p(xd);
1738
0
    return xd->tile_ctx->comp_ref_cdf[pred_context][0];
1739
0
}
1740
1741
0
AomCdfProb* svt_aom_get_pred_cdf_comp_ref_p1(const MacroBlockD* xd) {
1742
0
    const int pred_context = svt_av1_get_pred_context_comp_ref_p1(xd);
1743
0
    return xd->tile_ctx->comp_ref_cdf[pred_context][1];
1744
0
}
1745
1746
0
AomCdfProb* svt_aom_get_pred_cdf_comp_ref_p2(const MacroBlockD* xd) {
1747
0
    const int pred_context = svt_av1_get_pred_context_comp_ref_p2(xd);
1748
0
    return xd->tile_ctx->comp_ref_cdf[pred_context][2];
1749
0
}
1750
1751
0
AomCdfProb* svt_aom_get_pred_cdf_comp_bwdref_p(const MacroBlockD* xd) {
1752
0
    const int pred_context = svt_av1_get_pred_context_comp_bwdref_p(xd);
1753
0
    return xd->tile_ctx->comp_bwdref_cdf[pred_context][0];
1754
0
}
1755
1756
0
AomCdfProb* svt_aom_get_pred_cdf_comp_bwdref_p1(const MacroBlockD* xd) {
1757
0
    const int pred_context = svt_av1_get_pred_context_comp_bwdref_p1(xd);
1758
0
    return xd->tile_ctx->comp_bwdref_cdf[pred_context][1];
1759
0
}
1760
1761
0
int svt_aom_get_comp_reference_type_context_new(const MacroBlockD* xd) {
1762
0
    int                     pred_context;
1763
0
    const MbModeInfo* const above_mbmi     = xd->above_mbmi;
1764
0
    const MbModeInfo* const left_mbmi      = xd->left_mbmi;
1765
0
    const int               above_in_image = xd->up_available;
1766
0
    const int               left_in_image  = xd->left_available;
1767
1768
0
    if (above_in_image && left_in_image) { // both edges available
1769
0
        const int above_intra = !is_inter_block(&above_mbmi->block_mi);
1770
0
        const int left_intra  = !is_inter_block(&left_mbmi->block_mi);
1771
1772
0
        if (above_intra && left_intra) { // intra/intra
1773
0
            pred_context = 2;
1774
0
        } else if (above_intra || left_intra) { // intra/inter
1775
0
            const MbModeInfo* inter_mbmi = above_intra ? left_mbmi : above_mbmi;
1776
1777
0
            if (!has_second_ref(&inter_mbmi->block_mi)) { // single pred
1778
0
                pred_context = 2;
1779
0
            } else { // comp pred
1780
0
                pred_context = 1 + 2 * has_uni_comp_refs(&inter_mbmi->block_mi);
1781
0
            }
1782
0
        } else { // inter/inter
1783
0
            const int              a_sg = !has_second_ref(&above_mbmi->block_mi);
1784
0
            const int              l_sg = !has_second_ref(&left_mbmi->block_mi);
1785
0
            const MvReferenceFrame frfa = above_mbmi->block_mi.ref_frame[0];
1786
0
            const MvReferenceFrame frfl = left_mbmi->block_mi.ref_frame[0];
1787
1788
0
            if (a_sg && l_sg) { // single/single
1789
0
                pred_context = 1 + 2 * (!(IS_BACKWARD_REF_FRAME(frfa) ^ IS_BACKWARD_REF_FRAME(frfl)));
1790
0
            } else if (l_sg || a_sg) { // single/comp
1791
0
                const int uni_rfc = a_sg ? has_uni_comp_refs(&left_mbmi->block_mi)
1792
0
                                         : has_uni_comp_refs(&above_mbmi->block_mi);
1793
1794
0
                if (!uni_rfc) { // comp bidir
1795
0
                    pred_context = 1;
1796
0
                } else { // comp unidir
1797
0
                    pred_context = 3 + (!(IS_BACKWARD_REF_FRAME(frfa) ^ IS_BACKWARD_REF_FRAME(frfl)));
1798
0
                }
1799
0
            } else { // comp/comp
1800
0
                const int a_uni_rfc = has_uni_comp_refs(&above_mbmi->block_mi);
1801
0
                const int l_uni_rfc = has_uni_comp_refs(&left_mbmi->block_mi);
1802
1803
0
                if (!a_uni_rfc && !l_uni_rfc) { // bidir/bidir
1804
0
                    pred_context = 0;
1805
0
                } else if (!a_uni_rfc || !l_uni_rfc) { // unidir/bidir
1806
0
                    pred_context = 2;
1807
0
                } else { // unidir/unidir
1808
0
                    pred_context = 3 + (!((frfa == BWDREF_FRAME) ^ (frfl == BWDREF_FRAME)));
1809
0
                }
1810
0
            }
1811
0
        }
1812
0
    } else if (above_in_image || left_in_image) { // one edge available
1813
0
        const MbModeInfo* edge_mbmi = above_in_image ? above_mbmi : left_mbmi;
1814
1815
0
        if (!is_inter_block(&edge_mbmi->block_mi)) { // intra
1816
0
            pred_context = 2;
1817
0
        } else { // inter
1818
0
            if (!has_second_ref(&edge_mbmi->block_mi)) { // single pred
1819
0
                pred_context = 2;
1820
0
            } else { // comp pred
1821
0
                pred_context = 4 * has_uni_comp_refs(&edge_mbmi->block_mi);
1822
0
            }
1823
0
        }
1824
0
    } else { // no edges available
1825
0
        pred_context = 2;
1826
0
    }
1827
1828
0
    assert(pred_context >= 0 && pred_context < COMP_REF_TYPE_CONTEXTS);
1829
0
    return pred_context;
1830
0
}
1831
1832
// Returns a context number for the given MB prediction signal
1833
//
1834
// Signal the uni-directional compound reference frame pair as either
1835
// (BWDREF, ALTREF), or (LAST, LAST2) / (LAST, LAST3) / (LAST, GOLDEN),
1836
// conditioning on the pair is known as uni-directional.
1837
//
1838
// 3 contexts: Voting is used to compare the count of forward references with
1839
//             that of backward references from the spatial neighbors.
1840
0
int svt_av1_get_pred_context_uni_comp_ref_p(const MacroBlockD* xd) {
1841
0
    const uint8_t* const ref_counts = &xd->neighbors_ref_counts[0];
1842
1843
    // Count of forward references (L, L2, L3, or G)
1844
0
    const int frf_count = ref_counts[LAST_FRAME] + ref_counts[LAST2_FRAME] + ref_counts[LAST3_FRAME] +
1845
0
        ref_counts[GOLDEN_FRAME];
1846
    // Count of backward references (b or A)
1847
0
    const int brf_count = ref_counts[BWDREF_FRAME] + ref_counts[ALTREF2_FRAME] + ref_counts[ALTREF_FRAME];
1848
1849
0
    const int pred_context = (frf_count == brf_count) ? 1 : ((frf_count < brf_count) ? 0 : 2);
1850
1851
0
    assert(pred_context >= 0 && pred_context < UNI_COMP_REF_CONTEXTS);
1852
0
    return pred_context;
1853
0
}
1854
1855
// Returns a context number for the given MB prediction signal
1856
//
1857
// Signal the uni-directional compound reference frame pair as
1858
// either (LAST, LAST2), or (LAST, LAST3) / (LAST, GOLDEN),
1859
// conditioning on the pair is known as one of the above three.
1860
//
1861
// 3 contexts: Voting is used to compare the count of LAST2_FRAME with the
1862
//             total count of LAST3/GOLDEN from the spatial neighbors.
1863
0
int svt_av1_get_pred_context_uni_comp_ref_p1(const MacroBlockD* xd) {
1864
0
    const uint8_t* const ref_counts = &xd->neighbors_ref_counts[0];
1865
1866
    // Count of LAST2
1867
0
    const int last2_count = ref_counts[LAST2_FRAME];
1868
    // Count of LAST3 or GOLDEN
1869
0
    const int last3_or_gld_count = ref_counts[LAST3_FRAME] + ref_counts[GOLDEN_FRAME];
1870
1871
0
    const int pred_context = (last2_count == last3_or_gld_count) ? 1 : ((last2_count < last3_or_gld_count) ? 0 : 2);
1872
1873
0
    assert(pred_context >= 0 && pred_context < UNI_COMP_REF_CONTEXTS);
1874
0
    return pred_context;
1875
0
}
1876
1877
// Returns a context number for the given MB prediction signal
1878
//
1879
// Signal the uni-directional compound reference frame pair as
1880
// either (LAST, LAST3) or (LAST, GOLDEN),
1881
// conditioning on the pair is known as one of the above two.
1882
//
1883
// 3 contexts: Voting is used to compare the count of LAST3_FRAME with the
1884
//             total count of GOLDEN_FRAME from the spatial neighbors.
1885
0
int svt_av1_get_pred_context_uni_comp_ref_p2(const MacroBlockD* xd) {
1886
0
    const uint8_t* const ref_counts = &xd->neighbors_ref_counts[0];
1887
1888
    // Count of LAST3
1889
0
    const int last3_count = ref_counts[LAST3_FRAME];
1890
    // Count of GOLDEN
1891
0
    const int gld_count = ref_counts[GOLDEN_FRAME];
1892
1893
0
    const int pred_context = (last3_count == gld_count) ? 1 : ((last3_count < gld_count) ? 0 : 2);
1894
1895
0
    assert(pred_context >= 0 && pred_context < UNI_COMP_REF_CONTEXTS);
1896
0
    return pred_context;
1897
0
}
1898
1899
0
int svt_aom_get_reference_mode_context_new(const MacroBlockD* xd) {
1900
0
    int                     ctx;
1901
0
    const MbModeInfo* const above_mbmi = xd->above_mbmi;
1902
0
    const MbModeInfo* const left_mbmi  = xd->left_mbmi;
1903
0
    const int               has_above  = xd->up_available;
1904
0
    const int               has_left   = xd->left_available;
1905
1906
    // Note:
1907
    // The mode info data structure has a one element border above and to the
1908
    // left of the entries corresponding to real macroblocks.
1909
    // The prediction flags in these dummy entries are initialized to 0.
1910
0
    if (has_above && has_left) { // both edges available
1911
0
        if (!has_second_ref(&above_mbmi->block_mi) && !has_second_ref(&left_mbmi->block_mi)) {
1912
            // neither edge uses comp pred (0/1)
1913
0
            ctx = IS_BACKWARD_REF_FRAME(above_mbmi->block_mi.ref_frame[0]) ^
1914
0
                IS_BACKWARD_REF_FRAME(left_mbmi->block_mi.ref_frame[0]);
1915
0
        } else if (!has_second_ref(&above_mbmi->block_mi)) {
1916
            // one of two edges uses comp pred (2/3)
1917
0
            ctx = 2 +
1918
0
                (IS_BACKWARD_REF_FRAME(above_mbmi->block_mi.ref_frame[0]) || !is_inter_block(&above_mbmi->block_mi));
1919
0
        } else if (!has_second_ref(&left_mbmi->block_mi)) {
1920
            // one of two edges uses comp pred (2/3)
1921
0
            ctx = 2 +
1922
0
                (IS_BACKWARD_REF_FRAME(left_mbmi->block_mi.ref_frame[0]) || !is_inter_block(&left_mbmi->block_mi));
1923
0
        } else { // both edges use comp pred (4)
1924
0
            ctx = 4;
1925
0
        }
1926
0
    } else if (has_above || has_left) { // one edge available
1927
0
        const MbModeInfo* edge_mbmi = has_above ? above_mbmi : left_mbmi;
1928
1929
0
        if (!has_second_ref(&edge_mbmi->block_mi)) {
1930
            // edge does not use comp pred (0/1)
1931
0
            ctx = IS_BACKWARD_REF_FRAME(edge_mbmi->block_mi.ref_frame[0]);
1932
0
        } else {
1933
            // edge uses comp pred (3)
1934
0
            ctx = 3;
1935
0
        }
1936
0
    } else { // no edges available (1)
1937
0
        ctx = 1;
1938
0
    }
1939
0
    assert(ctx >= 0 && ctx < COMP_INTER_CONTEXTS);
1940
0
    return ctx;
1941
0
}
1942
1943
0
void svt_aom_collect_neighbors_ref_counts_new(MacroBlockD* const xd) {
1944
0
    av1_zero(xd->neighbors_ref_counts);
1945
1946
0
    uint8_t* const ref_counts = xd->neighbors_ref_counts;
1947
1948
0
    const MbModeInfo* const above_mbmi     = xd->above_mbmi;
1949
0
    const MbModeInfo* const left_mbmi      = xd->left_mbmi;
1950
0
    const int               above_in_image = xd->up_available;
1951
0
    const int               left_in_image  = xd->left_available;
1952
1953
    // Above neighbor
1954
0
    if (above_in_image && is_inter_block(&above_mbmi->block_mi)) {
1955
0
        ref_counts[above_mbmi->block_mi.ref_frame[0]]++;
1956
0
        if (has_second_ref(&above_mbmi->block_mi)) {
1957
0
            ref_counts[above_mbmi->block_mi.ref_frame[1]]++;
1958
0
        }
1959
0
    }
1960
1961
    // Left neighbor
1962
0
    if (left_in_image && is_inter_block(&left_mbmi->block_mi)) {
1963
0
        ref_counts[left_mbmi->block_mi.ref_frame[0]]++;
1964
0
        if (has_second_ref(&left_mbmi->block_mi)) {
1965
0
            ref_counts[left_mbmi->block_mi.ref_frame[1]]++;
1966
0
        }
1967
0
    }
1968
0
}
1969
1970
0
#define WRITE_REF_BIT(bname, pname) aom_write_symbol(w, bname, svt_aom_get_pred_cdf_##pname(xd), 2)
1971
1972
/***************************************************************************************/
1973
1974
// == Common context functions for both comp and single ref ==
1975
//
1976
// Obtain contexts to signal a reference frame to be either LAST/LAST2 or
1977
// LAST3/GOLDEN.
1978
0
static int32_t get_pred_context_ll2_or_l3gld(const MacroBlockD* xd) {
1979
0
    const uint8_t* const ref_counts = &xd->neighbors_ref_counts[0];
1980
1981
    // Count of LAST + LAST2
1982
0
    const int32_t last_last2_count = ref_counts[LAST_FRAME] + ref_counts[LAST2_FRAME];
1983
    // Count of LAST3 + GOLDEN
1984
0
    const int32_t last3_gld_count = ref_counts[LAST3_FRAME] + ref_counts[GOLDEN_FRAME];
1985
1986
0
    const int32_t pred_context = (last_last2_count == last3_gld_count) ? 1
1987
0
                                                                       : ((last_last2_count < last3_gld_count) ? 0 : 2);
1988
1989
0
    assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
1990
0
    return pred_context;
1991
0
}
1992
1993
// Obtain contexts to signal a reference frame to be either LAST or LAST2.
1994
0
static int32_t get_pred_context_last_or_last2(const MacroBlockD* xd) {
1995
0
    const uint8_t* const ref_counts = &xd->neighbors_ref_counts[0];
1996
1997
    // Count of LAST
1998
0
    const int32_t last_count = ref_counts[LAST_FRAME];
1999
    // Count of LAST2
2000
0
    const int32_t last2_count = ref_counts[LAST2_FRAME];
2001
2002
0
    const int32_t pred_context = (last_count == last2_count) ? 1 : ((last_count < last2_count) ? 0 : 2);
2003
2004
0
    assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
2005
0
    return pred_context;
2006
0
}
2007
2008
// Obtain contexts to signal a reference frame to be either LAST3 or GOLDEN.
2009
0
static int32_t get_pred_context_last3_or_gld(const MacroBlockD* xd) {
2010
0
    const uint8_t* const ref_counts = &xd->neighbors_ref_counts[0];
2011
2012
    // Count of LAST3
2013
0
    const int32_t last3_count = ref_counts[LAST3_FRAME];
2014
    // Count of GOLDEN
2015
0
    const int32_t gld_count = ref_counts[GOLDEN_FRAME];
2016
2017
0
    const int32_t pred_context = (last3_count == gld_count) ? 1 : ((last3_count < gld_count) ? 0 : 2);
2018
2019
0
    assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
2020
0
    return pred_context;
2021
0
}
2022
2023
// Obtain contexts to signal a reference frame be either BWDREF/ALTREF2, or
2024
// ALTREF.
2025
0
static int32_t get_pred_context_brfarf2_or_arf(const MacroBlockD* xd) {
2026
0
    const uint8_t* const ref_counts = &xd->neighbors_ref_counts[0];
2027
2028
    // Counts of BWDREF, ALTREF2, or ALTREF frames (b, A2, or A)
2029
0
    const int32_t brfarf2_count = ref_counts[BWDREF_FRAME] + ref_counts[ALTREF2_FRAME];
2030
0
    const int32_t arf_count     = ref_counts[ALTREF_FRAME];
2031
2032
0
    const int32_t pred_context = (brfarf2_count == arf_count) ? 1 : ((brfarf2_count < arf_count) ? 0 : 2);
2033
2034
0
    assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
2035
0
    return pred_context;
2036
0
}
2037
2038
// Obtain contexts to signal a reference frame be either BWDREF or ALTREF2.
2039
0
static int32_t get_pred_context_brf_or_arf2(const MacroBlockD* xd) {
2040
0
    const uint8_t* const ref_counts = &xd->neighbors_ref_counts[0];
2041
2042
    // Count of BWDREF frames (b)
2043
0
    const int32_t brf_count = ref_counts[BWDREF_FRAME];
2044
    // Count of ALTREF2 frames (A2)
2045
0
    const int32_t arf2_count = ref_counts[ALTREF2_FRAME];
2046
2047
0
    const int32_t pred_context = (brf_count == arf2_count) ? 1 : ((brf_count < arf2_count) ? 0 : 2);
2048
2049
0
    assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
2050
0
    return pred_context;
2051
0
}
2052
2053
// == Context functions for comp ref ==
2054
//
2055
// Returns a context number for the given MB prediction signal
2056
// Signal the first reference frame for a compound mode be either
2057
// GOLDEN/LAST3, or LAST/LAST2.
2058
0
int32_t svt_av1_get_pred_context_comp_ref_p(const MacroBlockD* xd) {
2059
0
    return get_pred_context_ll2_or_l3gld(xd);
2060
0
}
2061
2062
// Returns a context number for the given MB prediction signal
2063
// Signal the first reference frame for a compound mode be LAST,
2064
// conditioning on that it is known either LAST/LAST2.
2065
0
int32_t svt_av1_get_pred_context_comp_ref_p1(const MacroBlockD* xd) {
2066
0
    return get_pred_context_last_or_last2(xd);
2067
0
}
2068
2069
// Returns a context number for the given MB prediction signal
2070
// Signal the first reference frame for a compound mode be GOLDEN,
2071
// conditioning on that it is known either GOLDEN or LAST3.
2072
0
int32_t svt_av1_get_pred_context_comp_ref_p2(const MacroBlockD* xd) {
2073
0
    return get_pred_context_last3_or_gld(xd);
2074
0
}
2075
2076
// Signal the 2nd reference frame for a compound mode be either
2077
// ALTREF, or ALTREF2/BWDREF.
2078
0
int32_t svt_av1_get_pred_context_comp_bwdref_p(const MacroBlockD* xd) {
2079
0
    return get_pred_context_brfarf2_or_arf(xd);
2080
0
}
2081
2082
// Signal the 2nd reference frame for a compound mode be either
2083
// ALTREF2 or BWDREF.
2084
0
int32_t svt_av1_get_pred_context_comp_bwdref_p1(const MacroBlockD* xd) {
2085
0
    return get_pred_context_brf_or_arf2(xd);
2086
0
}
2087
2088
// == Context functions for single ref ==
2089
//
2090
// For the bit to signal whether the single reference is a forward reference
2091
// frame or a backward reference frame.
2092
0
int32_t svt_av1_get_pred_context_single_ref_p1(const MacroBlockD* xd) {
2093
0
    const uint8_t* const ref_counts = &xd->neighbors_ref_counts[0];
2094
2095
    // Count of forward reference frames
2096
0
    const int32_t fwd_count = ref_counts[LAST_FRAME] + ref_counts[LAST2_FRAME] + ref_counts[LAST3_FRAME] +
2097
0
        ref_counts[GOLDEN_FRAME];
2098
    // Count of backward reference frames
2099
0
    const int32_t bwd_count = ref_counts[BWDREF_FRAME] + ref_counts[ALTREF2_FRAME] + ref_counts[ALTREF_FRAME];
2100
2101
0
    const int32_t pred_context = (fwd_count == bwd_count) ? 1 : ((fwd_count < bwd_count) ? 0 : 2);
2102
2103
0
    assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
2104
0
    return pred_context;
2105
0
}
2106
2107
0
AomCdfProb* svt_aom_get_pred_cdf_single_ref_p1(const MacroBlockD* xd) {
2108
0
    return xd->tile_ctx->single_ref_cdf[svt_av1_get_pred_context_single_ref_p1(xd)][0];
2109
0
}
2110
2111
0
AomCdfProb* svt_aom_get_pred_cdf_single_ref_p2(const MacroBlockD* xd) {
2112
0
    return xd->tile_ctx->single_ref_cdf[svt_av1_get_pred_context_single_ref_p2(xd)][1];
2113
0
}
2114
2115
0
AomCdfProb* svt_aom_get_pred_cdf_single_ref_p3(const MacroBlockD* xd) {
2116
0
    return xd->tile_ctx->single_ref_cdf[svt_av1_get_pred_context_single_ref_p3(xd)][2];
2117
0
}
2118
2119
0
AomCdfProb* svt_aom_get_pred_cdf_single_ref_p4(const MacroBlockD* xd) {
2120
0
    return xd->tile_ctx->single_ref_cdf[svt_av1_get_pred_context_single_ref_p4(xd)][3];
2121
0
}
2122
2123
0
AomCdfProb* svt_aom_get_pred_cdf_single_ref_p5(const MacroBlockD* xd) {
2124
0
    return xd->tile_ctx->single_ref_cdf[svt_av1_get_pred_context_single_ref_p5(xd)][4];
2125
0
}
2126
2127
0
AomCdfProb* svt_aom_get_pred_cdf_single_ref_p6(const MacroBlockD* xd) {
2128
0
    return xd->tile_ctx->single_ref_cdf[svt_av1_get_pred_context_single_ref_p6(xd)][5];
2129
0
}
2130
2131
// For the bit to signal whether the single reference is ALTREF_FRAME or
2132
// non-ALTREF backward reference frame, knowing that it shall be either of
2133
// these 2 choices.
2134
0
int32_t svt_av1_get_pred_context_single_ref_p2(const MacroBlockD* xd) {
2135
0
    return get_pred_context_brfarf2_or_arf(xd);
2136
0
}
2137
2138
// For the bit to signal whether the single reference is LAST3/GOLDEN or
2139
// LAST2/LAST, knowing that it shall be either of these 2 choices.
2140
0
int32_t svt_av1_get_pred_context_single_ref_p3(const MacroBlockD* xd) {
2141
0
    return get_pred_context_ll2_or_l3gld(xd);
2142
0
}
2143
2144
// For the bit to signal whether the single reference is LAST2_FRAME or
2145
// LAST_FRAME, knowing that it shall be either of these 2 choices.
2146
0
int32_t svt_av1_get_pred_context_single_ref_p4(const MacroBlockD* xd) {
2147
0
    return get_pred_context_last_or_last2(xd);
2148
0
}
2149
2150
// For the bit to signal whether the single reference is GOLDEN_FRAME or
2151
// LAST3_FRAME, knowing that it shall be either of these 2 choices.
2152
0
int32_t svt_av1_get_pred_context_single_ref_p5(const MacroBlockD* xd) {
2153
0
    return get_pred_context_last3_or_gld(xd);
2154
0
}
2155
2156
// For the bit to signal whether the single reference is ALTREF2_FRAME or
2157
// BWDREF_FRAME, knowing that it shall be either of these 2 choices.
2158
0
int32_t svt_av1_get_pred_context_single_ref_p6(const MacroBlockD* xd) {
2159
0
    return get_pred_context_brf_or_arf2(xd);
2160
0
}
2161
2162
/***************************************************************************************/
2163
2164
0
static void write_ref_frames(PictureParentControlSet* pcs, const MacroBlockD* xd, AomWriter* w) {
2165
0
    FrameHeader*            frm_hdr     = &pcs->frm_hdr;
2166
0
    const MbModeInfo* const mbmi        = xd->mi[0];
2167
0
    const int               is_compound = has_second_ref(&mbmi->block_mi);
2168
0
    {
2169
        // does the feature use compound prediction or not
2170
        // (if not specified at the frame/segment level)
2171
0
        if (frm_hdr->reference_mode == REFERENCE_MODE_SELECT) {
2172
0
            if (is_comp_ref_allowed(mbmi->bsize)) {
2173
0
                aom_write_symbol(w, is_compound, svt_aom_get_reference_mode_cdf(xd), 2);
2174
0
            }
2175
0
        } else {
2176
0
            assert((!is_compound) == (frm_hdr->reference_mode == SINGLE_REFERENCE));
2177
0
        }
2178
2179
0
        if (is_compound) {
2180
0
            const CompReferenceType comp_ref_type = has_uni_comp_refs(&mbmi->block_mi) ? UNIDIR_COMP_REFERENCE
2181
0
                                                                                       : BIDIR_COMP_REFERENCE;
2182
0
            aom_write_symbol(w, comp_ref_type, svt_aom_get_comp_reference_type_cdf(xd), 2);
2183
2184
0
            if (comp_ref_type == UNIDIR_COMP_REFERENCE) {
2185
0
                const int bit = mbmi->block_mi.ref_frame[0] == BWDREF_FRAME;
2186
0
                WRITE_REF_BIT(bit, uni_comp_ref_p);
2187
2188
0
                if (!bit) {
2189
0
                    assert(mbmi->block_mi.ref_frame[0] == LAST_FRAME);
2190
0
                    const int bit1 = mbmi->block_mi.ref_frame[1] == LAST3_FRAME ||
2191
0
                        mbmi->block_mi.ref_frame[1] == GOLDEN_FRAME;
2192
0
                    WRITE_REF_BIT(bit1, uni_comp_ref_p1);
2193
0
                    if (bit1) {
2194
0
                        const int bit2 = mbmi->block_mi.ref_frame[1] == GOLDEN_FRAME;
2195
0
                        WRITE_REF_BIT(bit2, uni_comp_ref_p2);
2196
0
                    }
2197
0
                } else {
2198
0
                    assert(mbmi->block_mi.ref_frame[1] == ALTREF_FRAME);
2199
0
                }
2200
0
                return;
2201
0
            }
2202
2203
0
            assert(comp_ref_type == BIDIR_COMP_REFERENCE);
2204
2205
0
            const int bit = (mbmi->block_mi.ref_frame[0] == GOLDEN_FRAME || mbmi->block_mi.ref_frame[0] == LAST3_FRAME);
2206
0
            WRITE_REF_BIT(bit, comp_ref_p);
2207
2208
0
            if (!bit) {
2209
0
                const int bit1 = mbmi->block_mi.ref_frame[0] == LAST2_FRAME;
2210
0
                WRITE_REF_BIT(bit1, comp_ref_p1);
2211
0
            } else {
2212
0
                const int bit2 = mbmi->block_mi.ref_frame[0] == GOLDEN_FRAME;
2213
0
                WRITE_REF_BIT(bit2, comp_ref_p2);
2214
0
            }
2215
2216
0
            const int bit_bwd = mbmi->block_mi.ref_frame[1] == ALTREF_FRAME;
2217
0
            WRITE_REF_BIT(bit_bwd, comp_bwdref_p);
2218
2219
0
            if (!bit_bwd) {
2220
0
                WRITE_REF_BIT(mbmi->block_mi.ref_frame[1] == ALTREF2_FRAME, comp_bwdref_p1);
2221
0
            }
2222
0
        } else {
2223
0
            const int bit0 = (mbmi->block_mi.ref_frame[0] <= ALTREF_FRAME &&
2224
0
                              mbmi->block_mi.ref_frame[0] >= BWDREF_FRAME);
2225
0
            WRITE_REF_BIT(bit0, single_ref_p1);
2226
2227
0
            if (bit0) {
2228
0
                const int bit1 = mbmi->block_mi.ref_frame[0] == ALTREF_FRAME;
2229
0
                WRITE_REF_BIT(bit1, single_ref_p2);
2230
0
                if (!bit1) {
2231
0
                    WRITE_REF_BIT(mbmi->block_mi.ref_frame[0] == ALTREF2_FRAME, single_ref_p6);
2232
0
                }
2233
0
            } else {
2234
0
                const int bit2 = (mbmi->block_mi.ref_frame[0] == LAST3_FRAME ||
2235
0
                                  mbmi->block_mi.ref_frame[0] == GOLDEN_FRAME);
2236
0
                WRITE_REF_BIT(bit2, single_ref_p3);
2237
0
                if (!bit2) {
2238
0
                    const int bit3 = mbmi->block_mi.ref_frame[0] != LAST_FRAME;
2239
0
                    WRITE_REF_BIT(bit3, single_ref_p4);
2240
0
                } else {
2241
0
                    const int bit4 = mbmi->block_mi.ref_frame[0] != LAST3_FRAME;
2242
0
                    WRITE_REF_BIT(bit4, single_ref_p5);
2243
0
                }
2244
0
            }
2245
0
        }
2246
0
    }
2247
0
}
2248
2249
0
static void encode_restoration_mode(PictureParentControlSet* pcs, AomWriteBitBuffer* wb) {
2250
0
    FrameHeader* frm_hdr = &pcs->frm_hdr;
2251
    //SVT_ERROR("encode_restoration_mode might not work. Double check the reference code\n");
2252
0
    assert(!frm_hdr->all_lossless);
2253
    // move out side of the function
2254
    //if (!cm->seq_params.enable_restoration) return;
2255
2256
0
    if (frm_hdr->allow_intrabc) {
2257
0
        return;
2258
0
    }
2259
2260
0
    const int32_t num_planes = 3; // av1_num_planes(cm);
2261
0
    int32_t       all_none = 1, chroma_none = 1;
2262
0
    for (int32_t p = 0; p < num_planes; ++p) {
2263
0
        RestorationInfo* rsi = &pcs->child_pcs->rst_info[p];
2264
2265
0
        if (rsi->frame_restoration_type != RESTORE_NONE) {
2266
0
            all_none = 0;
2267
0
            chroma_none &= (int32_t)(p == 0);
2268
0
        }
2269
0
        switch (rsi->frame_restoration_type) {
2270
0
        case RESTORE_NONE:
2271
0
            svt_aom_wb_write_bit(wb, 0);
2272
0
            svt_aom_wb_write_bit(wb, 0);
2273
0
            break;
2274
0
        case RESTORE_WIENER:
2275
0
            svt_aom_wb_write_bit(wb, 1);
2276
0
            svt_aom_wb_write_bit(wb, 0);
2277
0
            break;
2278
0
        case RESTORE_SGRPROJ:
2279
0
            svt_aom_wb_write_bit(wb, 1);
2280
0
            svt_aom_wb_write_bit(wb, 1);
2281
0
            break;
2282
0
        case RESTORE_SWITCHABLE:
2283
0
            svt_aom_wb_write_bit(wb, 0);
2284
0
            svt_aom_wb_write_bit(wb, 1);
2285
0
            break;
2286
0
        default:
2287
0
            assert(0);
2288
0
        }
2289
0
    }
2290
0
    if (!all_none) {
2291
0
        const int32_t    sb_size = pcs->scs->seq_header.sb_size == BLOCK_128X128 ? 128 : 64;
2292
0
        RestorationInfo* rsi     = &pcs->child_pcs->rst_info[0];
2293
0
        assert(rsi->restoration_unit_size >= sb_size);
2294
0
        assert(RESTORATION_UNITSIZE_MAX == 256);
2295
2296
0
        if (sb_size == 64) {
2297
0
            svt_aom_wb_write_bit(wb, rsi->restoration_unit_size > 64);
2298
0
        }
2299
0
        if (rsi->restoration_unit_size > 64) {
2300
0
            svt_aom_wb_write_bit(wb, rsi->restoration_unit_size > 128);
2301
0
        }
2302
0
    }
2303
0
    if (!chroma_none) {
2304
0
        svt_aom_wb_write_bit(
2305
0
            wb, pcs->child_pcs->rst_info[1].restoration_unit_size != pcs->child_pcs->rst_info[0].restoration_unit_size);
2306
0
        assert(pcs->child_pcs->rst_info[1].restoration_unit_size == pcs->child_pcs->rst_info[0].restoration_unit_size ||
2307
0
               pcs->child_pcs->rst_info[1].restoration_unit_size ==
2308
0
                   (pcs->child_pcs->rst_info[0].restoration_unit_size >> 1));
2309
0
        assert(pcs->child_pcs->rst_info[2].restoration_unit_size == pcs->child_pcs->rst_info[1].restoration_unit_size);
2310
0
    }
2311
0
}
2312
2313
1.06k
static void encode_segmentation(PictureParentControlSet* pcs, AomWriteBitBuffer* wb) {
2314
1.06k
    SegmentationParams* segmentation_params = &pcs->frm_hdr.segmentation_params;
2315
1.06k
    svt_aom_wb_write_bit(wb, segmentation_params->segmentation_enabled);
2316
1.06k
    if (segmentation_params->segmentation_enabled) {
2317
0
        if (!(pcs->frm_hdr.primary_ref_frame == PRIMARY_REF_NONE)) {
2318
0
            svt_aom_wb_write_bit(wb, segmentation_params->segmentation_update_map);
2319
0
            if (segmentation_params->segmentation_update_map) {
2320
0
                svt_aom_wb_write_bit(wb, segmentation_params->segmentation_temporal_update);
2321
0
            }
2322
0
            svt_aom_wb_write_bit(wb, segmentation_params->segmentation_update_data);
2323
0
        }
2324
0
        if (segmentation_params->segmentation_update_data) {
2325
0
            for (int i = 0; i < MAX_SEGMENTS; i++) {
2326
0
                for (int j = 0; j < SEG_LVL_MAX; j++) {
2327
0
                    svt_aom_wb_write_bit(wb, segmentation_params->feature_enabled[i][j]);
2328
0
                    if (segmentation_params->feature_enabled[i][j]) {
2329
                        //TODO: add clamping
2330
0
                        if (svt_aom_segmentation_feature_signed[j]) {
2331
0
                            svt_aom_wb_write_inv_signed_literal(
2332
0
                                wb, segmentation_params->feature_data[i][j], svt_aom_segmentation_feature_bits[j]);
2333
0
                        } else {
2334
0
                            svt_aom_wb_write_literal(
2335
0
                                wb, segmentation_params->feature_data[i][j], svt_aom_segmentation_feature_bits[j]);
2336
0
                        }
2337
0
                    }
2338
0
                }
2339
0
            }
2340
0
        }
2341
0
    }
2342
1.06k
}
2343
2344
614
static void encode_loopfilter(PictureParentControlSet* pcs, AomWriteBitBuffer* wb) {
2345
614
    FrameHeader* frm_hdr = &pcs->frm_hdr;
2346
614
    assert(!frm_hdr->coded_lossless);
2347
614
    if (frm_hdr->allow_intrabc) {
2348
0
        return;
2349
0
    }
2350
2351
614
    LoopFilter* lf = &frm_hdr->loop_filter_params;
2352
2353
    // Encode the loop filter level and type
2354
614
    svt_aom_wb_write_literal(wb, lf->filter_level[0], 6);
2355
614
    svt_aom_wb_write_literal(wb, lf->filter_level[1], 6);
2356
614
    if (lf->filter_level[0] || lf->filter_level[1]) {
2357
578
        svt_aom_wb_write_literal(wb, lf->filter_level_u, 6);
2358
578
        svt_aom_wb_write_literal(wb, lf->filter_level_v, 6);
2359
578
    }
2360
614
    svt_aom_wb_write_literal(wb, lf->sharpness_level, 3);
2361
2362
    // Write out loop filter deltas applied at the MB level based on mode or
2363
    // ref frame (if they are enabled).
2364
614
    svt_aom_wb_write_bit(wb, lf->mode_ref_delta_enabled);
2365
614
    if (lf->mode_ref_delta_enabled) {
2366
0
        SVT_ERROR("Loop Filter is not supported yet \n");
2367
        /* svt_aom_wb_write_bit(wb, lf->mode_ref_delta_update);
2368
        if (lf->mode_ref_delta_update) {
2369
        const int32_t prime_idx = pcs->primary_ref_frame;
2370
        const int32_t buf_idx =
2371
        prime_idx == PRIMARY_REF_NONE ? -1 : cm->frame_refs[prime_idx].idx;
2372
        int8_t last_ref_deltas[TOTAL_REFS_PER_FRAME];
2373
        if (prime_idx == PRIMARY_REF_NONE || buf_idx < 0) {
2374
        av1_set_default_ref_deltas(last_ref_deltas);
2375
        } else {
2376
        svt_memcpy(last_ref_deltas, cm->buffer_pool->frame_bufs[buf_idx].ref_deltas,
2377
        TOTAL_REFS_PER_FRAME);
2378
        }
2379
        for (i = 0; i < TOTAL_REFS_PER_FRAME; i++) {
2380
        const int32_t delta = lf->ref_deltas[i];
2381
        const int32_t changed = delta != last_ref_deltas[i];
2382
        svt_aom_wb_write_bit(wb, changed);
2383
        if (changed) svt_aom_wb_write_inv_signed_literal(wb, delta, 6);
2384
        }
2385
        int8_t last_mode_deltas[MAX_MODE_LF_DELTAS];
2386
        if (prime_idx == PRIMARY_REF_NONE || buf_idx < 0) {
2387
        av1_set_default_mode_deltas(last_mode_deltas);
2388
        } else {
2389
        svt_memcpy(last_mode_deltas,
2390
        cm->buffer_pool->frame_bufs[buf_idx].mode_deltas,
2391
        MAX_MODE_LF_DELTAS);
2392
        }
2393
2394
        for (i = 0; i < MAX_MODE_LF_DELTAS; i++) {
2395
        const int32_t delta = lf->mode_deltas[i];
2396
        const int32_t changed = delta != last_mode_deltas[i];
2397
        svt_aom_wb_write_bit(wb, changed);
2398
        if (changed) svt_aom_wb_write_inv_signed_literal(wb, delta, 6);
2399
        }
2400
        }*/
2401
0
    }
2402
614
}
2403
2404
614
static void encode_cdef(const PictureParentControlSet* pcs, AomWriteBitBuffer* wb) {
2405
    //assert(!cm->coded_lossless);
2406
    // moved out side
2407
    //if (!cm->seq_params.cdef_level) return;
2408
2409
614
    const FrameHeader* frm_hdr = &pcs->frm_hdr;
2410
2411
614
    if (frm_hdr->allow_intrabc) {
2412
0
        return;
2413
0
    }
2414
2415
614
    svt_aom_wb_write_literal(wb, frm_hdr->cdef_params.cdef_damping - 3, 2);
2416
    //cdef_pri_damping & cdef_sec_damping consolidated to cdef_damping
2417
    //assert(pcs->cdef_pri_damping == pcs->cdef_sec_damping);
2418
614
    svt_aom_wb_write_literal(wb, frm_hdr->cdef_params.cdef_bits, 2);
2419
1.22k
    for (int32_t i = 0; i < pcs->nb_cdef_strengths; i++) {
2420
614
        svt_aom_wb_write_literal(wb, frm_hdr->cdef_params.cdef_y_strength[i], CDEF_STRENGTH_BITS);
2421
614
        svt_aom_wb_write_literal(wb, frm_hdr->cdef_params.cdef_uv_strength[i], CDEF_STRENGTH_BITS);
2422
614
    }
2423
614
}
2424
2425
3.19k
static void write_delta_q(AomWriteBitBuffer* wb, int32_t delta_q) {
2426
3.19k
    if (delta_q != 0) {
2427
0
        svt_aom_wb_write_bit(wb, 1);
2428
0
        svt_aom_wb_write_inv_signed_literal(wb, delta_q, 6);
2429
3.19k
    } else {
2430
3.19k
        svt_aom_wb_write_bit(wb, 0);
2431
3.19k
    }
2432
3.19k
}
2433
2434
1.06k
static void encode_quantization(const PictureParentControlSet* const pcs, AomWriteBitBuffer* wb) {
2435
1.06k
    const FrameHeader* frm_hdr = &pcs->frm_hdr;
2436
1.06k
    svt_aom_wb_write_literal(wb, frm_hdr->quantization_params.base_q_idx, QINDEX_BITS);
2437
1.06k
    write_delta_q(wb, frm_hdr->quantization_params.delta_q_dc[PLANE_Y]);
2438
1.06k
    int32_t diff_uv_delta = (frm_hdr->quantization_params.delta_q_dc[PLANE_U] !=
2439
1.06k
                             frm_hdr->quantization_params.delta_q_dc[PLANE_V]) ||
2440
1.06k
        (frm_hdr->quantization_params.delta_q_ac[PLANE_U] != frm_hdr->quantization_params.delta_q_ac[PLANE_V]);
2441
2442
1.06k
    if (diff_uv_delta) {
2443
0
        svt_aom_wb_write_bit(wb, diff_uv_delta);
2444
0
    }
2445
1.06k
    write_delta_q(wb, frm_hdr->quantization_params.delta_q_dc[PLANE_U]);
2446
1.06k
    write_delta_q(wb, frm_hdr->quantization_params.delta_q_ac[PLANE_U]);
2447
1.06k
    if (diff_uv_delta) {
2448
0
        write_delta_q(wb, frm_hdr->quantization_params.delta_q_dc[PLANE_V]);
2449
0
        write_delta_q(wb, frm_hdr->quantization_params.delta_q_ac[PLANE_V]);
2450
0
    }
2451
1.06k
    svt_aom_wb_write_bit(wb, frm_hdr->quantization_params.using_qmatrix);
2452
1.06k
    if (frm_hdr->quantization_params.using_qmatrix) {
2453
0
        svt_aom_wb_write_literal(wb, frm_hdr->quantization_params.qm[PLANE_Y], QM_LEVEL_BITS);
2454
0
        svt_aom_wb_write_literal(wb, frm_hdr->quantization_params.qm[PLANE_U], QM_LEVEL_BITS);
2455
0
        if (!diff_uv_delta) {
2456
0
            assert(frm_hdr->quantization_params.qm[PLANE_U] == frm_hdr->quantization_params.qm[PLANE_V]);
2457
0
        } else {
2458
0
            svt_aom_wb_write_literal(wb, frm_hdr->quantization_params.qm[PLANE_V], QM_LEVEL_BITS);
2459
0
        }
2460
0
    }
2461
1.06k
}
2462
2463
1.06k
static void write_tile_info_max_tile(const PictureParentControlSet* const pcs, AomWriteBitBuffer* wb) {
2464
1.06k
    Av1Common* cm = pcs->av1_cm;
2465
1.06k
    svt_aom_wb_write_bit(wb, cm->tiles_info.uniform_tile_spacing_flag);
2466
2467
1.06k
    if (cm->tiles_info.uniform_tile_spacing_flag) {
2468
        // Uniform spaced tiles with power-of-two number of rows and columns
2469
        // tile columns
2470
1.06k
        int32_t ones = cm->log2_tile_cols - cm->tiles_info.min_log2_tile_cols;
2471
2.98k
        while (ones--) {
2472
1.91k
            svt_aom_wb_write_bit(wb, 1);
2473
1.91k
        }
2474
1.06k
        if (cm->log2_tile_cols < cm->tiles_info.max_log2_tile_cols) {
2475
244
            svt_aom_wb_write_bit(wb, 0);
2476
244
        }
2477
        // rows
2478
1.06k
        cm->tiles_info.min_log2_tile_rows = AOMMAX(cm->tiles_info.min_log2_tiles - cm->log2_tile_cols, 0);
2479
1.06k
        ones                              = cm->log2_tile_rows - cm->tiles_info.min_log2_tile_rows;
2480
2.91k
        while (ones--) {
2481
1.84k
            svt_aom_wb_write_bit(wb, 1);
2482
1.84k
        }
2483
1.06k
        if (cm->log2_tile_rows < cm->tiles_info.max_log2_tile_rows) {
2484
116
            svt_aom_wb_write_bit(wb, 0);
2485
116
        }
2486
1.06k
    } else {
2487
        // Explicit tiles with configurable tile widths and heights
2488
0
        SVT_ERROR("NON uniform_tile_spacing_flag not supported yet\n");
2489
        //// columns
2490
        // int sb_size_log2 = pcs->scs->seq_header.sb_size_log2;
2491
        //for (i = 0; i < cm->tile_cols; i++) {
2492
        //    size_sb = (cm->tile_col_start_mi[i + 1] - cm->tile_col_start_mi[i]) >> sb_size_log2;
2493
        //    wb_write_uniform(wb, AOMMIN(width_sb, cm->max_tile_width_sb),
2494
        //        size_sb - 1);
2495
        //    width_sb -= size_sb;
2496
        //}
2497
        //assert(width_sb == 0);
2498
2499
        //// rows
2500
        //for (i = 0; i < cm->tile_rows; i++) {
2501
        //    size_sb = (cm->tile_row_start_mi[i + 1] - cm->tile_row_start_mi[i]) >> sb_size_log2;
2502
        //    wb_write_uniform(wb, AOMMIN(height_sb, cm->max_tile_height_sb),
2503
        //        size_sb - 1);
2504
        //    height_sb -= size_sb;
2505
        //}
2506
        //assert(height_sb == 0);
2507
0
    }
2508
1.06k
}
2509
2510
3.73k
void svt_av1_get_tile_limits(PictureParentControlSet* pcs) {
2511
3.73k
    Av1Common* cm = pcs->av1_cm;
2512
2513
3.73k
    int32_t mi_cols                  = ALIGN_POWER_OF_TWO(cm->mi_cols, pcs->log2_sb_size);
2514
3.73k
    int32_t mi_rows                  = ALIGN_POWER_OF_TWO(cm->mi_rows, pcs->log2_sb_size);
2515
3.73k
    int32_t sb_cols                  = mi_cols >> pcs->log2_sb_size;
2516
3.73k
    int32_t sb_rows                  = mi_rows >> pcs->log2_sb_size;
2517
3.73k
    int32_t sb_size_log2             = pcs->log2_sb_size + MI_SIZE_LOG2;
2518
3.73k
    cm->tiles_info.max_tile_width_sb = MAX_TILE_WIDTH >> sb_size_log2;
2519
3.73k
    int32_t max_tile_area_sb         = MAX_TILE_AREA >> (2 * sb_size_log2);
2520
2521
3.73k
    cm->tiles_info.min_log2_tile_cols = tile_log2(cm->tiles_info.max_tile_width_sb, sb_cols);
2522
3.73k
    cm->tiles_info.max_log2_tile_cols = tile_log2(1, AOMMIN(sb_cols, MAX_TILE_COLS));
2523
3.73k
    cm->tiles_info.max_log2_tile_rows = tile_log2(1, AOMMIN(sb_rows, MAX_TILE_ROWS));
2524
3.73k
    cm->tiles_info.min_log2_tile_rows = 0; // CHKN Tiles
2525
3.73k
    cm->tiles_info.min_log2_tiles     = tile_log2(max_tile_area_sb, sb_cols * sb_rows);
2526
3.73k
    cm->tiles_info.min_log2_tiles     = AOMMAX(cm->tiles_info.min_log2_tiles, cm->tiles_info.min_log2_tile_cols);
2527
3.73k
}
2528
2529
2.66k
void svt_av1_calculate_tile_cols(PictureParentControlSet* pcs) {
2530
2.66k
    Av1Common* const cm = pcs->av1_cm;
2531
2532
2.66k
    const int mi_cols      = ALIGN_POWER_OF_TWO(cm->mi_cols, pcs->log2_sb_size);
2533
2.66k
    const int mi_rows      = ALIGN_POWER_OF_TWO(cm->mi_rows, pcs->log2_sb_size);
2534
2.66k
    const int sb_cols      = mi_cols >> pcs->log2_sb_size;
2535
2.66k
    const int sb_rows      = mi_rows >> pcs->log2_sb_size;
2536
2.66k
    const int sb_size_log2 = pcs->log2_sb_size;
2537
2538
2.66k
    if (cm->tiles_info.uniform_tile_spacing_flag) {
2539
2.66k
        int size_sb = ALIGN_POWER_OF_TWO(sb_cols, cm->log2_tile_cols);
2540
2.66k
        size_sb >>= cm->log2_tile_cols;
2541
2.66k
        assert(size_sb > 0);
2542
2.66k
        int i = 0;
2543
11.3k
        for (int start_sb = 0; start_sb < sb_cols; i++) {
2544
8.71k
            cm->tiles_info.tile_col_start_mi[i] = start_sb << sb_size_log2;
2545
8.71k
            start_sb += size_sb;
2546
8.71k
        }
2547
2.66k
        cm->tiles_info.tile_cols            = i;
2548
2.66k
        cm->tiles_info.tile_col_start_mi[i] = sb_cols << sb_size_log2;
2549
2.66k
        cm->tiles_info.min_log2_tile_rows   = AOMMAX(cm->tiles_info.min_log2_tiles - cm->log2_tile_cols, 0);
2550
2.66k
        cm->tiles_info.max_tile_height_sb   = sb_rows >> cm->tiles_info.min_log2_tile_rows;
2551
2552
2.66k
        cm->tile_width = size_sb << pcs->log2_sb_size;
2553
2.66k
        cm->tile_width = AOMMIN(cm->tile_width, cm->mi_cols);
2554
2.66k
    } else {
2555
0
        int max_tile_area_sb = (sb_rows * sb_cols);
2556
0
        int widest_tile_sb   = 1;
2557
0
        cm->log2_tile_cols   = tile_log2(1, cm->tiles_info.tile_cols);
2558
0
        for (int i = 0; i < cm->tiles_info.tile_cols; i++) {
2559
0
            int size_sb = (cm->tiles_info.tile_col_start_mi[i + 1] - cm->tiles_info.tile_col_start_mi[i]) >>
2560
0
                sb_size_log2;
2561
0
            widest_tile_sb = AOMMAX(widest_tile_sb, size_sb);
2562
0
        }
2563
0
        if (cm->tiles_info.min_log2_tiles) {
2564
0
            max_tile_area_sb >>= (cm->tiles_info.min_log2_tiles + 1);
2565
0
        }
2566
2567
0
        cm->tiles_info.max_tile_height_sb = AOMMAX(max_tile_area_sb / widest_tile_sb, 1);
2568
0
    }
2569
2.66k
}
2570
2571
2.66k
void svt_av1_calculate_tile_rows(PictureParentControlSet* pcs) {
2572
2.66k
    Av1Common* const cm = pcs->av1_cm;
2573
2574
2.66k
    int mi_rows      = ALIGN_POWER_OF_TWO(cm->mi_rows, pcs->log2_sb_size);
2575
2.66k
    int sb_rows      = mi_rows >> pcs->log2_sb_size;
2576
2.66k
    int sb_size_log2 = pcs->log2_sb_size;
2577
2578
2.66k
    if (cm->tiles_info.uniform_tile_spacing_flag) {
2579
2.66k
        int size_sb = ALIGN_POWER_OF_TWO(sb_rows, cm->log2_tile_rows);
2580
2.66k
        size_sb >>= cm->log2_tile_rows;
2581
2.66k
        assert(size_sb > 0);
2582
2.66k
        int i = 0;
2583
11.1k
        for (int start_sb = 0; start_sb < sb_rows; i++) {
2584
8.44k
            cm->tiles_info.tile_row_start_mi[i] = start_sb << sb_size_log2;
2585
8.44k
            start_sb += size_sb;
2586
8.44k
        }
2587
2.66k
        cm->tiles_info.tile_rows            = i;
2588
2.66k
        cm->tiles_info.tile_row_start_mi[i] = sb_rows << sb_size_log2;
2589
2590
2.66k
        cm->tile_height = size_sb << pcs->log2_sb_size;
2591
2.66k
        cm->tile_height = AOMMIN(cm->tile_height, cm->mi_rows);
2592
2.66k
    } else {
2593
0
        cm->log2_tile_rows = tile_log2(1, cm->tiles_info.tile_rows);
2594
0
    }
2595
2.66k
}
2596
2597
2.66k
void svt_aom_set_tile_info(PictureParentControlSet* pcs) {
2598
    /*  Tiling algorithm:
2599
        input : log2_tile_count ==> tile_count = 1<<log2_tile_count
2600
2601
        step1) compute pic_size_in_sb
2602
        step2) then round up to the closed n.tile_count.
2603
        step3) tile_size = rounded_pic_size_in_sb / tile_count.
2604
        step4) we fill tiles of size tile_size until we reach the end of the pic
2605
2606
        Note that: the last tile could have smaller size, and the final number
2607
        of tiles could be less than tile_count
2608
     */
2609
2610
2.66k
    Av1Common* cm = pcs->av1_cm;
2611
    //to connect later if non uniform tile spacing is needed.
2612
2613
2.66k
    svt_av1_get_tile_limits(pcs);
2614
2615
    // configure tile columns
2616
2.66k
    cm->tiles_info.uniform_tile_spacing_flag = 1;
2617
2.66k
    cm->log2_tile_cols                       = AOMMAX(pcs->log2_tile_cols, cm->tiles_info.min_log2_tile_cols);
2618
2.66k
    cm->log2_tile_cols                       = AOMMIN(cm->log2_tile_cols, cm->tiles_info.max_log2_tile_cols);
2619
2620
2.66k
    svt_av1_calculate_tile_cols(pcs);
2621
2622
    // configure tile rows
2623
2.66k
    if (cm->tiles_info.uniform_tile_spacing_flag) {
2624
2.66k
        cm->log2_tile_rows = AOMMAX(pcs->log2_tile_rows, cm->tiles_info.min_log2_tile_rows);
2625
2.66k
        cm->log2_tile_rows = AOMMIN(cm->log2_tile_rows, cm->tiles_info.max_log2_tile_rows);
2626
2.66k
    } else {
2627
0
        int       i            = 0;
2628
0
        const int mi_rows      = ALIGN_POWER_OF_TWO(cm->mi_rows, pcs->log2_sb_size);
2629
0
        const int sb_rows      = mi_rows >> pcs->log2_sb_size;
2630
0
        const int sb_size_log2 = pcs->scs->seq_header.sb_size_log2;
2631
0
        for (int start_sb = 0; start_sb < sb_rows && i < MAX_TILE_ROWS; i++) {
2632
0
            cm->tiles_info.tile_row_start_mi[i] = start_sb << sb_size_log2;
2633
0
            start_sb += cm->tiles_info.max_tile_height_sb;
2634
0
        }
2635
0
        cm->tiles_info.tile_rows            = i;
2636
0
        cm->tiles_info.tile_row_start_mi[i] = sb_rows << sb_size_log2;
2637
0
    }
2638
2.66k
    svt_av1_calculate_tile_rows(pcs);
2639
2.66k
}
2640
2641
1.06k
static void write_tile_info(const PictureParentControlSet* const pcs, AomWriteBitBuffer* wb) {
2642
1.06k
    Av1Common* const cm                     = pcs->av1_cm;
2643
1.06k
    uint16_t         tile_cnt               = cm->tiles_info.tile_rows * cm->tiles_info.tile_cols;
2644
1.06k
    pcs->child_pcs->tile_size_bytes_minus_1 = 0;
2645
1.06k
    svt_av1_get_tile_limits((PictureParentControlSet*)pcs);
2646
1.06k
    write_tile_info_max_tile(pcs, wb);
2647
2648
1.06k
    if (pcs->av1_cm->tiles_info.tile_rows * pcs->av1_cm->tiles_info.tile_cols > 1) {
2649
        // tile id used for cdf update
2650
        // Force each frame to update their data so future frames can use it,
2651
        // even if the current frame did not use it.  This enables REF frames to
2652
        // have the feature off, while NREF frames can have it on.  Used for multi-threading.
2653
1.05k
        svt_aom_wb_write_literal(wb,
2654
1.05k
                                 pcs->av1_cm->tiles_info.tile_rows * pcs->av1_cm->tiles_info.tile_cols - 1,
2655
1.05k
                                 pcs->av1_cm->log2_tile_cols + pcs->av1_cm->log2_tile_rows);
2656
2657
        // Number of bytes in tile size - 1
2658
1.05k
        uint32_t max_tile_size = 0;
2659
11.3k
        for (int tile_idx = 0; tile_idx < tile_cnt - 1; tile_idx++) {
2660
10.2k
            max_tile_size = AOMMAX(max_tile_size, pcs->child_pcs->ec_info[tile_idx]->ec->ec_writer.pos);
2661
10.2k
        }
2662
1.05k
        if (max_tile_size >> 24 != 0) {
2663
0
            pcs->child_pcs->tile_size_bytes_minus_1 = 3;
2664
1.05k
        } else if (max_tile_size >> 16 != 0) {
2665
0
            pcs->child_pcs->tile_size_bytes_minus_1 = 2;
2666
1.05k
        } else if (max_tile_size >> 8 != 0) {
2667
0
            pcs->child_pcs->tile_size_bytes_minus_1 = 1;
2668
1.05k
        } else {
2669
1.05k
            pcs->child_pcs->tile_size_bytes_minus_1 = 0;
2670
1.05k
        }
2671
2672
1.05k
        svt_aom_wb_write_literal(wb, pcs->child_pcs->tile_size_bytes_minus_1, 2); //Jing: Change 3 to smaller size
2673
1.05k
    }
2674
1.06k
}
2675
2676
1.06k
static AOM_INLINE void write_render_size(AomWriteBitBuffer* wb, PictureParentControlSet* ppcs) {
2677
1.06k
    int render_and_frame_size_different = 0;
2678
1.06k
    if (ppcs->frame_resize_enabled) {
2679
0
        render_and_frame_size_different = 1;
2680
0
    }
2681
1.06k
    svt_aom_wb_write_bit(wb, render_and_frame_size_different);
2682
1.06k
    if (!render_and_frame_size_different) {
2683
1.06k
        return;
2684
1.06k
    }
2685
0
    uint32_t render_width_minus_1  = ppcs->render_width - 1;
2686
0
    uint32_t render_height_minus_1 = ppcs->render_height - 1;
2687
0
    svt_aom_wb_write_literal(wb, render_width_minus_1, 16);
2688
0
    svt_aom_wb_write_literal(wb, render_height_minus_1, 16);
2689
0
}
2690
2691
1.06k
static AOM_INLINE void write_superres_scale(AomWriteBitBuffer* wb, PictureParentControlSet* pcs) {
2692
1.06k
    SequenceControlSet* scs            = pcs->scs;
2693
1.06k
    Av1Common*          cm             = pcs->av1_cm;
2694
1.06k
    uint8_t             superres_denom = cm->frm_size.superres_denominator;
2695
2696
1.06k
    if (!scs->seq_header.enable_superres) {
2697
1.06k
        assert(cm->frm_size.superres_denominator == SCALE_NUMERATOR);
2698
1.06k
        return;
2699
1.06k
    }
2700
2701
    // First bit is whether to to scale or not
2702
0
    if (superres_denom == SCALE_NUMERATOR) {
2703
0
        svt_aom_wb_write_bit(wb, 0); // no scaling
2704
0
    } else {
2705
0
        svt_aom_wb_write_bit(wb, 1); // scaling, write scale factor
2706
0
        assert(superres_denom >= SUPERRES_SCALE_DENOMINATOR_MIN);
2707
0
        assert(superres_denom < SUPERRES_SCALE_DENOMINATOR_MIN + (1 << SUPERRES_SCALE_BITS));
2708
0
        svt_aom_wb_write_literal(wb, superres_denom - SUPERRES_SCALE_DENOMINATOR_MIN, SUPERRES_SCALE_BITS);
2709
0
    }
2710
0
}
2711
2712
1.06k
static void write_frame_size(PictureParentControlSet* pcs, int32_t frame_size_override, AomWriteBitBuffer* wb) {
2713
1.06k
    SequenceControlSet* scs = pcs->scs;
2714
1.06k
    (void)(*pcs);
2715
1.06k
    (void)frame_size_override;
2716
1.06k
    Av1Common*    cm           = pcs->av1_cm;
2717
1.06k
    const int32_t coded_width  = cm->frm_size.superres_upscaled_width - 1;
2718
1.06k
    const int32_t coded_height = cm->frm_size.superres_upscaled_height - 1;
2719
2720
1.06k
    if (frame_size_override) {
2721
0
        int32_t num_bits_width  = scs->seq_header.frame_width_bits;
2722
0
        int32_t num_bits_height = scs->seq_header.frame_height_bits;
2723
0
        svt_aom_wb_write_literal(wb, coded_width, num_bits_width);
2724
0
        svt_aom_wb_write_literal(wb, coded_height, num_bits_height);
2725
0
    }
2726
2727
1.06k
    write_superres_scale(wb, pcs);
2728
1.06k
    write_render_size(wb, pcs);
2729
1.06k
}
2730
2731
1.06k
static void write_profile(BitstreamProfile profile, AomWriteBitBuffer* wb) {
2732
1.06k
    assert(profile >= PROFILE_0 && profile < MAX_PROFILES);
2733
1.06k
    svt_aom_wb_write_literal(wb, profile, PROFILE_BITS);
2734
1.06k
}
2735
2736
1.06k
static AOM_INLINE void write_bitdepth(const SequenceControlSet* const scs, AomWriteBitBuffer* wb) {
2737
    // Profile 0/1: [0] for 8 bit, [1]  10-bit
2738
    // Profile   2: [0] for 8 bit, [10] 10-bit, [11] - 12-bit
2739
1.06k
    svt_aom_wb_write_bit(wb, scs->static_config.encoder_bit_depth == EB_EIGHT_BIT ? 0 : 1);
2740
1.06k
    if (scs->static_config.profile == PROFESSIONAL_PROFILE && scs->static_config.encoder_bit_depth != EB_EIGHT_BIT) {
2741
0
        SVT_ERROR("Profile 2 Not supported\n");
2742
0
        svt_aom_wb_write_bit(wb, scs->static_config.encoder_bit_depth == EB_TEN_BIT ? 0 : 1);
2743
0
    }
2744
1.06k
}
2745
2746
1.06k
static AOM_INLINE void write_color_config(const SequenceControlSet* const scs, AomWriteBitBuffer* wb) {
2747
1.06k
    write_bitdepth(scs, wb);
2748
1.06k
    const int is_monochrome = 0; // monochrome is not supported yet
2749
    // monochrome bit
2750
1.06k
    if (scs->static_config.profile != HIGH_PROFILE) {
2751
1.06k
        svt_aom_wb_write_bit(wb, is_monochrome);
2752
1.06k
    } else {
2753
0
        assert(!is_monochrome);
2754
0
    }
2755
1.06k
    if (scs->static_config.color_primaries == EB_CICP_CP_UNSPECIFIED &&
2756
1.06k
        scs->static_config.transfer_characteristics == EB_CICP_TC_UNSPECIFIED &&
2757
1.06k
        scs->static_config.matrix_coefficients == EB_CICP_MC_UNSPECIFIED) {
2758
1.06k
        svt_aom_wb_write_bit(wb, 0); // No color description present
2759
1.06k
    } else {
2760
0
        svt_aom_wb_write_bit(wb, 1); // Color description present
2761
0
        svt_aom_wb_write_literal(wb, scs->static_config.color_primaries, 8);
2762
0
        svt_aom_wb_write_literal(wb, scs->static_config.transfer_characteristics, 8);
2763
0
        svt_aom_wb_write_literal(wb, scs->static_config.matrix_coefficients, 8);
2764
0
    }
2765
    /* if (is_monochrome) {
2766
        // 0: [16, 235] (i.e. xvYCC), 1: [0, 255]
2767
        svt_aom_wb_write_bit(wb, scs->static_config.color_range);
2768
        return;
2769
    } */
2770
1.06k
    if (scs->static_config.color_primaries == EB_CICP_CP_BT_709 &&
2771
0
        scs->static_config.transfer_characteristics == EB_CICP_TC_SRGB &&
2772
0
        scs->static_config.matrix_coefficients == EB_CICP_MC_IDENTITY) {
2773
        /* assert(scs->subsampling_x == 0 && scs->subsampling_y == 0);
2774
        assert(scs->static_config.profile == HIGH_PROFILE ||
2775
               (scs->static_config.profile == PROFESSIONAL_PROFILE && scs->encoder_bit_depth == EB_TWELVE_BIT)); */
2776
1.06k
    } else {
2777
        // 0: [16, 235] (i.e. xvYCC), 1: [0, 255]
2778
1.06k
        svt_aom_wb_write_bit(wb, scs->static_config.color_range);
2779
1.06k
        if (scs->static_config.profile == MAIN_PROFILE) {
2780
            // 420 only
2781
1.06k
            assert(scs->subsampling_x == 1 && scs->subsampling_y == 1);
2782
1.06k
        } else if (scs->static_config.profile == HIGH_PROFILE) {
2783
            // 444 only
2784
0
            assert(scs->subsampling_x == 0 && scs->subsampling_y == 0);
2785
0
        } else if (scs->static_config.profile == PROFESSIONAL_PROFILE) {
2786
0
            if (scs->encoder_bit_depth == EB_TWELVE_BIT) {
2787
                // 420, 444 or 422
2788
0
                svt_aom_wb_write_bit(wb, scs->subsampling_x);
2789
0
                if (scs->subsampling_x == 0) {
2790
0
                    assert(scs->subsampling_y == 0 && "4:4:0 subsampling not allowed in AV1");
2791
0
                } else {
2792
0
                    svt_aom_wb_write_bit(wb, scs->subsampling_y);
2793
0
                }
2794
0
            } else {
2795
                // 422 only
2796
0
                assert(scs->subsampling_x == 1 && scs->subsampling_y == 0);
2797
0
            }
2798
0
        }
2799
1.06k
        if (scs->static_config.matrix_coefficients == EB_CICP_MC_IDENTITY) {
2800
0
            assert(scs->subsampling_x == 0 && scs->subsampling_y == 0);
2801
0
        }
2802
1.06k
        if (scs->subsampling_x == 1 && scs->subsampling_y == 1) {
2803
1.06k
            svt_aom_wb_write_literal(wb, scs->static_config.chroma_sample_position, 2);
2804
1.06k
        }
2805
1.06k
    }
2806
1.06k
    bool separate_uv_delta_q = (scs->static_config.chroma_u_ac_qindex_offset !=
2807
1.06k
                                    scs->static_config.chroma_v_ac_qindex_offset ||
2808
1.06k
                                scs->static_config.chroma_u_dc_qindex_offset !=
2809
1.06k
                                    scs->static_config.chroma_v_dc_qindex_offset);
2810
1.06k
    svt_aom_wb_write_bit(wb, separate_uv_delta_q);
2811
1.06k
}
2812
2813
1.06k
static void write_sequence_header(SequenceControlSet* scs, AomWriteBitBuffer* wb) {
2814
1.06k
    const int32_t max_frame_width   = scs->seq_header.max_frame_width;
2815
1.06k
    const int32_t max_frame_height  = scs->seq_header.max_frame_height;
2816
1.06k
    unsigned      frame_width_bits  = svt_log2f(max_frame_width);
2817
1.06k
    unsigned      frame_height_bits = svt_log2f(max_frame_height);
2818
1.06k
    if (max_frame_width > (1 << frame_width_bits)) {
2819
998
        ++frame_width_bits;
2820
998
    }
2821
1.06k
    if (max_frame_height > (1 << frame_height_bits)) {
2822
988
        ++frame_height_bits;
2823
988
    }
2824
    // AV1 spec requires at least 1 bit for frame dimensions
2825
1.06k
    if (frame_width_bits < 1) {
2826
0
        frame_width_bits = 1;
2827
0
    }
2828
1.06k
    if (frame_height_bits < 1) {
2829
0
        frame_height_bits = 1;
2830
0
    }
2831
1.06k
    scs->seq_header.frame_width_bits  = frame_width_bits;
2832
1.06k
    scs->seq_header.frame_height_bits = frame_height_bits;
2833
2834
1.06k
    svt_aom_wb_write_literal(wb, frame_width_bits - 1, 4);
2835
1.06k
    svt_aom_wb_write_literal(wb, frame_height_bits - 1, 4);
2836
1.06k
    svt_aom_wb_write_literal(wb, max_frame_width - 1, frame_width_bits);
2837
1.06k
    svt_aom_wb_write_literal(wb, max_frame_height - 1, frame_height_bits);
2838
2839
1.06k
    if (!scs->seq_header.reduced_still_picture_header) {
2840
        //scs->frame_id_numbers_present_flag = 0;
2841
        //    cm->large_scale_tile ? 0 : cm->error_resilient_mode;
2842
2843
0
        svt_aom_wb_write_bit(wb, scs->seq_header.frame_id_numbers_present_flag);
2844
0
        if (scs->seq_header.frame_id_numbers_present_flag) {
2845
            // We must always have delta_frame_id_length < frame_id_length,
2846
            // in order for a frame to be referenced with a unique delta.
2847
            // Avoid wasting bits by using a coding that enforces this restriction.
2848
0
            svt_aom_wb_write_literal(wb, scs->seq_header.delta_frame_id_length - 2, 4);
2849
0
            svt_aom_wb_write_literal(
2850
0
                wb, ((scs->seq_header.frame_id_length) - (scs->seq_header.delta_frame_id_length) - 1), 3);
2851
0
        }
2852
0
    }
2853
2854
1.06k
    svt_aom_wb_write_bit(wb, scs->seq_header.sb_size == BLOCK_128X128 ? 1 : 0);
2855
    //    svt_aom_write_sb_size(seq_params, wb);
2856
1.06k
    svt_aom_wb_write_bit(wb, scs->seq_header.filter_intra_level);
2857
1.06k
    svt_aom_wb_write_bit(wb, scs->seq_header.enable_intra_edge_filter);
2858
2859
1.06k
    if (!scs->seq_header.reduced_still_picture_header) {
2860
0
        svt_aom_wb_write_bit(wb, scs->seq_header.enable_interintra_compound);
2861
0
        svt_aom_wb_write_bit(wb, scs->seq_header.enable_masked_compound);
2862
        //        svt_aom_wb_write_bit(wb, scs->static_config.enable_warped_motion);
2863
0
        svt_aom_wb_write_bit(wb, scs->seq_header.enable_warped_motion);
2864
0
        svt_aom_wb_write_bit(wb, scs->seq_header.enable_dual_filter);
2865
2866
0
        svt_aom_wb_write_bit(wb, scs->seq_header.order_hint_info.enable_order_hint);
2867
2868
0
        if (scs->seq_header.order_hint_info.enable_order_hint) {
2869
0
            svt_aom_wb_write_bit(wb, scs->seq_header.order_hint_info.enable_jnt_comp);
2870
0
            svt_aom_wb_write_bit(wb, scs->seq_header.order_hint_info.enable_ref_frame_mvs);
2871
0
        }
2872
2873
0
        if (scs->seq_header.seq_force_screen_content_tools == 2) {
2874
0
            svt_aom_wb_write_bit(wb, 1);
2875
0
        } else {
2876
0
            svt_aom_wb_write_bit(wb, 0);
2877
0
            svt_aom_wb_write_bit(wb, scs->seq_header.seq_force_screen_content_tools);
2878
0
        }
2879
        //
2880
0
        if (scs->seq_header.seq_force_screen_content_tools > 0) {
2881
0
            if (scs->seq_header.seq_force_integer_mv == 2) {
2882
0
                svt_aom_wb_write_bit(wb, 1);
2883
0
            } else {
2884
0
                svt_aom_wb_write_bit(wb, 0);
2885
0
                svt_aom_wb_write_bit(wb, scs->seq_header.seq_force_integer_mv);
2886
0
            }
2887
0
        } else {
2888
0
            assert(scs->seq_header.seq_force_integer_mv == 2);
2889
0
        }
2890
0
        if (scs->seq_header.order_hint_info.enable_order_hint) {
2891
0
            svt_aom_wb_write_literal(wb, scs->seq_header.order_hint_info.order_hint_bits - 1, 3);
2892
0
        }
2893
0
    }
2894
2895
1.06k
    svt_aom_wb_write_bit(wb, scs->seq_header.enable_superres);
2896
1.06k
    svt_aom_wb_write_bit(wb, scs->seq_header.cdef_level);
2897
1.06k
    svt_aom_wb_write_bit(wb, scs->seq_header.enable_restoration);
2898
1.06k
}
2899
2900
// Recenters a non-negative literal v around a reference r
2901
0
static uint16_t recenter_nonneg(uint16_t r, uint16_t v) {
2902
0
    if (v > (r << 1)) {
2903
0
        return v;
2904
0
    } else if (v >= r) {
2905
0
        return ((v - r) << 1);
2906
0
    } else {
2907
0
        return ((r - v) << 1) - 1;
2908
0
    }
2909
0
}
2910
2911
// Recenters a non-negative literal v in [0, n-1] around a
2912
// reference r also in [0, n-1]
2913
0
static uint16_t recenter_finite_nonneg(uint16_t n, uint16_t r, uint16_t v) {
2914
0
    if ((r << 1) <= n) {
2915
0
        return recenter_nonneg(r, v);
2916
0
    } else {
2917
0
        return recenter_nonneg(n - 1 - r, n - 1 - v);
2918
0
    }
2919
0
}
2920
2921
// Encodes a value v in [0, n-1] quasi-uniformly
2922
0
void svt_aom_write_primitive_quniform(AomWriter* w, uint16_t n, uint16_t v) {
2923
0
    if (n <= 1) {
2924
0
        return;
2925
0
    }
2926
0
    const int32_t l = get_msb(n - 1) + 1;
2927
0
    const int32_t m = (1 << l) - n;
2928
0
    if (v < m) {
2929
0
        aom_write_literal(w, v, l - 1);
2930
0
    } else {
2931
0
        aom_write_literal(w, m + ((v - m) >> 1), l - 1);
2932
0
        aom_write_bit(w, (v - m) & 1);
2933
0
    }
2934
0
}
2935
2936
0
static void aom_wb_write_primitive_quniform(AomWriteBitBuffer* wb, uint16_t n, uint16_t v) {
2937
0
    if (n <= 1) {
2938
0
        return;
2939
0
    }
2940
0
    const int32_t l = get_msb(n - 1) + 1;
2941
0
    const int32_t m = (1 << l) - n;
2942
0
    if (v < m) {
2943
0
        svt_aom_wb_write_literal(wb, v, l - 1);
2944
0
    } else {
2945
0
        svt_aom_wb_write_literal(wb, m + ((v - m) >> 1), l - 1);
2946
0
        svt_aom_wb_write_bit(wb, (v - m) & 1);
2947
0
    }
2948
0
}
2949
2950
0
int32_t svt_aom_count_primitive_quniform(uint16_t n, uint16_t v) {
2951
0
    if (n <= 1) {
2952
0
        return 0;
2953
0
    }
2954
0
    const int32_t l = get_msb(n - 1) + 1;
2955
0
    const int32_t m = (1 << l) - n;
2956
0
    return v < m ? l - 1 : l;
2957
0
}
2958
2959
// Finite subexponential code that codes a symbol v in [0, n-1] with parameter k
2960
0
void svt_aom_write_primitive_subexpfin(AomWriter* w, uint16_t n, uint16_t k, uint16_t v) {
2961
0
    int32_t i  = 0;
2962
0
    int32_t mk = 0;
2963
0
    while (1) {
2964
0
        int32_t b = (i ? k + i - 1 : k);
2965
0
        int32_t a = (1 << b);
2966
0
        if (n <= mk + 3 * a) {
2967
0
            svt_aom_write_primitive_quniform(w, (uint16_t)(n - mk), (uint16_t)(v - mk));
2968
0
            break;
2969
0
        } else {
2970
0
            int32_t t = (v >= mk + a);
2971
0
            aom_write_bit(w, t);
2972
0
            if (t) {
2973
0
                i = i + 1;
2974
0
                mk += a;
2975
0
            } else {
2976
0
                aom_write_literal(w, v - mk, b);
2977
0
                break;
2978
0
            }
2979
0
        }
2980
0
    }
2981
0
}
2982
2983
0
static void aom_wb_write_primitive_subexpfin(AomWriteBitBuffer* wb, uint16_t n, uint16_t k, uint16_t v) {
2984
0
    int32_t i  = 0;
2985
0
    int32_t mk = 0;
2986
0
    while (1) {
2987
0
        int32_t b = (i ? k + i - 1 : k);
2988
0
        int32_t a = (1 << b);
2989
0
        if (n <= mk + 3 * a) {
2990
0
            aom_wb_write_primitive_quniform(wb, (uint16_t)(n - mk), (uint16_t)(v - mk));
2991
0
            break;
2992
0
        } else {
2993
0
            int32_t t = (v >= mk + a);
2994
0
            svt_aom_wb_write_bit(wb, t);
2995
0
            if (t) {
2996
0
                i = i + 1;
2997
0
                mk += a;
2998
0
            } else {
2999
0
                svt_aom_wb_write_literal(wb, v - mk, b);
3000
0
                break;
3001
0
            }
3002
0
        }
3003
0
    }
3004
0
}
3005
3006
0
int32_t svt_aom_count_primitive_subexpfin(uint16_t n, uint16_t k, uint16_t v) {
3007
0
    int32_t count = 0;
3008
0
    int32_t i     = 0;
3009
0
    int32_t mk    = 0;
3010
0
    while (1) {
3011
0
        int32_t b = (i ? k + i - 1 : k);
3012
0
        int32_t a = (1 << b);
3013
0
        if (n <= mk + 3 * a) {
3014
0
            count += svt_aom_count_primitive_quniform((uint16_t)(n - mk), (uint16_t)(v - mk));
3015
0
            break;
3016
0
        } else {
3017
0
            int32_t t = (v >= mk + a);
3018
0
            count++;
3019
0
            if (t) {
3020
0
                i = i + 1;
3021
0
                mk += a;
3022
0
            } else {
3023
0
                count += b;
3024
0
                break;
3025
0
            }
3026
0
        }
3027
0
    }
3028
0
    return count;
3029
0
}
3030
3031
// Finite subexponential code that codes a symbol v in[0, n - 1] with parameter k
3032
// based on a reference ref also in [0, n-1].
3033
// Recenters symbol around r first and then uses a finite subexponential code.
3034
0
void svt_aom_write_primitive_refsubexpfin(AomWriter* w, uint16_t n, uint16_t k, uint16_t ref, uint16_t v) {
3035
0
    svt_aom_write_primitive_subexpfin(w, n, k, recenter_finite_nonneg(n, ref, v));
3036
0
}
3037
3038
static void aom_wb_write_primitive_refsubexpfin(AomWriteBitBuffer* wb, uint16_t n, uint16_t k, uint16_t ref,
3039
0
                                                uint16_t v) {
3040
0
    aom_wb_write_primitive_subexpfin(wb, n, k, recenter_finite_nonneg(n, ref, v));
3041
0
}
3042
3043
void svt_aom_wb_write_signed_primitive_refsubexpfin(AomWriteBitBuffer* wb, uint16_t n, uint16_t k, int16_t ref,
3044
0
                                                    int16_t v) {
3045
0
    ref += n - 1;
3046
0
    v += n - 1;
3047
0
    const uint16_t scaled_n = (n << 1) - 1;
3048
0
    aom_wb_write_primitive_refsubexpfin(wb, scaled_n, k, ref, v);
3049
0
}
3050
3051
0
int32_t svt_aom_count_primitive_refsubexpfin(uint16_t n, uint16_t k, uint16_t ref, uint16_t v) {
3052
0
    return svt_aom_count_primitive_subexpfin(n, k, recenter_finite_nonneg(n, ref, v));
3053
0
}
3054
3055
static void write_global_motion_params(const WarpedMotionParams* params, const WarpedMotionParams* ref_params,
3056
0
                                       AomWriteBitBuffer* wb, int32_t allow_hp) {
3057
0
    const TransformationType type = params->wmtype;
3058
0
    svt_aom_wb_write_bit(wb, type != IDENTITY);
3059
0
    if (type != IDENTITY) {
3060
0
        svt_aom_wb_write_bit(wb, type == ROTZOOM);
3061
0
        if (type != ROTZOOM) {
3062
0
            svt_aom_wb_write_bit(wb, type == TRANSLATION);
3063
0
        }
3064
0
    }
3065
3066
0
    if (type >= ROTZOOM) {
3067
0
        int16_t ref2 = (int16_t)((ref_params->wmmat[2] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS));
3068
0
        int16_t v2   = (int16_t)((params->wmmat[2] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS));
3069
3070
0
        int16_t ref3 = (int16_t)(ref_params->wmmat[3] >> GM_ALPHA_PREC_DIFF);
3071
0
        int16_t v3   = (int16_t)(params->wmmat[3] >> GM_ALPHA_PREC_DIFF);
3072
3073
0
        svt_aom_wb_write_signed_primitive_refsubexpfin(
3074
0
            wb,
3075
0
            GM_ALPHA_MAX + 1,
3076
0
            SUBEXPFIN_K,
3077
0
            ref2 /*(ref_params->wmmat[2] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS)*/,
3078
0
            v2 /*(int16_t)((params->wmmat[2] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS))*/);
3079
0
        svt_aom_wb_write_signed_primitive_refsubexpfin(wb,
3080
0
                                                       GM_ALPHA_MAX + 1,
3081
0
                                                       SUBEXPFIN_K,
3082
0
                                                       ref3 /*(ref_params->wmmat[3] >> GM_ALPHA_PREC_DIFF)*/,
3083
0
                                                       v3 /*(int16_t)(params->wmmat[3] >> GM_ALPHA_PREC_DIFF)*/);
3084
0
    }
3085
3086
0
    if (type >= AFFINE) {
3087
0
        int16_t ref4 = (int16_t)(ref_params->wmmat[4] >> GM_ALPHA_PREC_DIFF);
3088
0
        int16_t v4   = (int16_t)(params->wmmat[4] >> GM_ALPHA_PREC_DIFF);
3089
3090
0
        int16_t ref5 = (int16_t)((ref_params->wmmat[5] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS));
3091
0
        int16_t v5   = (int16_t)((params->wmmat[5] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS));
3092
3093
0
        svt_aom_wb_write_signed_primitive_refsubexpfin(wb,
3094
0
                                                       GM_ALPHA_MAX + 1,
3095
0
                                                       SUBEXPFIN_K,
3096
0
                                                       ref4 /*(ref_params->wmmat[4] >> GM_ALPHA_PREC_DIFF)*/,
3097
0
                                                       v4 /*(int16_t)(params->wmmat[4] >> GM_ALPHA_PREC_DIFF)*/);
3098
0
        svt_aom_wb_write_signed_primitive_refsubexpfin(
3099
0
            wb,
3100
0
            GM_ALPHA_MAX + 1,
3101
0
            SUBEXPFIN_K,
3102
0
            ref5 /*(ref_params->wmmat[5] >> GM_ALPHA_PREC_DIFF) -    (1 << GM_ALPHA_PREC_BITS)*/,
3103
0
            v5 /*(int16_t)(params->wmmat[5] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS)*/);
3104
0
    }
3105
3106
0
    if (type >= TRANSLATION) {
3107
0
        const int32_t trans_bits      = (type == TRANSLATION) ? GM_ABS_TRANS_ONLY_BITS - !allow_hp : GM_ABS_TRANS_BITS;
3108
0
        const int32_t trans_prec_diff = (type == TRANSLATION) ? GM_TRANS_ONLY_PREC_DIFF + !allow_hp
3109
0
                                                              : GM_TRANS_PREC_DIFF;
3110
0
        svt_aom_wb_write_signed_primitive_refsubexpfin(wb,
3111
0
                                                       (1 << trans_bits) + 1,
3112
0
                                                       SUBEXPFIN_K,
3113
0
                                                       (int16_t)(ref_params->wmmat[0] >> trans_prec_diff),
3114
0
                                                       (int16_t)(params->wmmat[0] >> trans_prec_diff));
3115
0
        svt_aom_wb_write_signed_primitive_refsubexpfin(wb,
3116
0
                                                       (1 << trans_bits) + 1,
3117
0
                                                       SUBEXPFIN_K,
3118
0
                                                       (int16_t)(ref_params->wmmat[1] >> trans_prec_diff),
3119
0
                                                       (int16_t)(params->wmmat[1] >> trans_prec_diff));
3120
0
    }
3121
0
}
3122
3123
static void write_global_motion(PictureParentControlSet* pcs, AomWriteBitBuffer* wb)
3124
3125
0
{
3126
0
    int32_t      frame;
3127
0
    FrameHeader* frm_hdr = &pcs->frm_hdr;
3128
0
    for (frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame) {
3129
0
        const WarpedMotionParams* ref_params = (frm_hdr->primary_ref_frame != PRIMARY_REF_NONE)
3130
0
            ? &pcs->child_pcs->ref_global_motion[frame]
3131
0
            : &default_warp_params;
3132
0
        write_global_motion_params(&pcs->global_motion[frame], ref_params, wb, frm_hdr->allow_high_precision_mv);
3133
        // The logic in the commented out code below
3134
        // does not work currently and causes mismatches when resize is on.
3135
        // Fix it before turning the optimization back on.
3136
        /*
3137
        Yv12BufferConfig *ref_buf = get_ref_frame_buffer(cpi, frame);
3138
        if (cpi->source->y_crop_width == ref_buf->y_crop_width &&
3139
        cpi->source->y_crop_height == ref_buf->y_crop_height) {
3140
        write_global_motion_params(&cm->global_motion[frame],
3141
        &cm->prev_frame->global_motion[frame], wb,
3142
        cm->allow_high_precision_mv);
3143
        } else {
3144
        assert(cm->global_motion[frame].wmtype == IDENTITY &&
3145
        "Invalid warp type for frames of different resolutions");
3146
        }
3147
        */
3148
        /*
3149
        SVT_LOG("Frame %d/%d: Enc Ref %d: %d %d %d %d\n",
3150
        cm->current_video_frame, cm->show_frame, frame,
3151
        cm->global_motion[frame].wmmat[0],
3152
        cm->global_motion[frame].wmmat[1], cm->global_motion[frame].wmmat[2],
3153
        cm->global_motion[frame].wmmat[3]);
3154
        */
3155
0
    }
3156
0
}
3157
3158
#if CONFIG_ENABLE_FILM_GRAIN
3159
0
static void write_film_grain_params(PictureParentControlSet* pcs, AomWriteBitBuffer* wb) {
3160
0
    FrameHeader*  frm_hdr = &pcs->frm_hdr;
3161
0
    AomFilmGrain* pars    = &frm_hdr->film_grain_params;
3162
3163
0
    svt_aom_wb_write_bit(wb, pars->apply_grain);
3164
0
    if (!pars->apply_grain) {
3165
0
        return;
3166
0
    }
3167
3168
0
    svt_aom_wb_write_literal(wb, pars->random_seed, 16);
3169
3170
0
    if (frm_hdr->frame_type == INTER_FRAME) {
3171
0
        EbReferenceObject* ref_obj_0 = (EbReferenceObject*)pcs->child_pcs->ref_pic_ptr_array[REF_LIST_0][0]->object_ptr;
3172
0
        int32_t            ref_idx   = 0;
3173
0
        pars->update_parameters      = 1;
3174
3175
0
        if (!pars->ignore_ref) {
3176
0
            if (svt_aom_film_grain_params_equal(&ref_obj_0->film_grain_params, pars)) {
3177
0
                pars->update_parameters = 0;
3178
0
                ref_idx                 = get_ref_frame_map_idx(pcs, LAST_FRAME);
3179
0
            } else if (pcs->child_pcs->slice_type == B_SLICE) {
3180
0
                EbReferenceObject* ref_obj_1 =
3181
0
                    (EbReferenceObject*)pcs->child_pcs->ref_pic_ptr_array[REF_LIST_1][0]->object_ptr;
3182
0
                if (svt_aom_film_grain_params_equal(&ref_obj_1->film_grain_params, pars)) {
3183
0
                    pars->update_parameters = 0;
3184
0
                    ref_idx = get_ref_frame_map_idx(pcs, ALTREF_FRAME); //todo: will it always be ALF_REF in L1?
3185
0
                }
3186
0
            }
3187
0
        }
3188
3189
0
        svt_aom_wb_write_bit(wb, pars->update_parameters);
3190
0
        if (!pars->update_parameters) {
3191
0
            svt_aom_wb_write_literal(wb, ref_idx, 3);
3192
0
            return;
3193
0
        }
3194
0
    } else {
3195
0
        pars->update_parameters = 1;
3196
0
    }
3197
3198
    // Scaling functions parameters
3199
0
    svt_aom_wb_write_literal(wb, pars->num_y_points, 4); // max 14
3200
0
    for (int32_t i = 0; i < pars->num_y_points; i++) {
3201
0
        svt_aom_wb_write_literal(wb, pars->scaling_points_y[i][0], 8);
3202
0
        svt_aom_wb_write_literal(wb, pars->scaling_points_y[i][1], 8);
3203
0
    }
3204
3205
0
    if (!pcs->scs->seq_header.color_config.mono_chrome) {
3206
0
        svt_aom_wb_write_bit(wb, pars->chroma_scaling_from_luma);
3207
0
    } else {
3208
0
        pars->chroma_scaling_from_luma = 0; // for monochrome override to 0
3209
0
    }
3210
3211
0
    if (pcs->scs->seq_header.color_config.mono_chrome || pars->chroma_scaling_from_luma ||
3212
        // todo: add corresponding check when subsampling variables are present
3213
0
        ((pcs->scs->subsampling_x == 1) && (pcs->scs->subsampling_y == 1) && (pars->num_y_points == 0))) {
3214
0
        pars->num_cb_points = 0;
3215
0
        pars->num_cr_points = 0;
3216
0
    } else {
3217
0
        svt_aom_wb_write_literal(wb, pars->num_cb_points, 4); // max 10
3218
0
        for (int32_t i = 0; i < pars->num_cb_points; i++) {
3219
0
            svt_aom_wb_write_literal(wb, pars->scaling_points_cb[i][0], 8);
3220
0
            svt_aom_wb_write_literal(wb, pars->scaling_points_cb[i][1], 8);
3221
0
        }
3222
3223
0
        svt_aom_wb_write_literal(wb, pars->num_cr_points, 4); // max 10
3224
0
        for (int32_t i = 0; i < pars->num_cr_points; i++) {
3225
0
            svt_aom_wb_write_literal(wb, pars->scaling_points_cr[i][0], 8);
3226
0
            svt_aom_wb_write_literal(wb, pars->scaling_points_cr[i][1], 8);
3227
0
        }
3228
0
    }
3229
3230
0
    svt_aom_wb_write_literal(wb, pars->scaling_shift - 8, 2); // 8 + value
3231
3232
    // AR coefficients
3233
    // Only sent if the corresponsing scaling function has
3234
    // more than 0 points
3235
3236
0
    svt_aom_wb_write_literal(wb, pars->ar_coeff_lag, 2);
3237
3238
0
    int32_t num_pos_luma   = 2 * pars->ar_coeff_lag * (pars->ar_coeff_lag + 1);
3239
0
    int32_t num_pos_chroma = num_pos_luma;
3240
0
    if (pars->num_y_points > 0) {
3241
0
        ++num_pos_chroma;
3242
0
    }
3243
3244
0
    if (pars->num_y_points) {
3245
0
        for (int32_t i = 0; i < num_pos_luma; i++) {
3246
0
            svt_aom_wb_write_literal(wb, pars->ar_coeffs_y[i] + 128, 8);
3247
0
        }
3248
0
    }
3249
3250
0
    if (pars->num_cb_points || pars->chroma_scaling_from_luma) {
3251
0
        for (int32_t i = 0; i < num_pos_chroma; i++) {
3252
0
            svt_aom_wb_write_literal(wb, pars->ar_coeffs_cb[i] + 128, 8);
3253
0
        }
3254
0
    }
3255
3256
0
    if (pars->num_cr_points || pars->chroma_scaling_from_luma) {
3257
0
        for (int32_t i = 0; i < num_pos_chroma; i++) {
3258
0
            svt_aom_wb_write_literal(wb, pars->ar_coeffs_cr[i] + 128, 8);
3259
0
        }
3260
0
    }
3261
3262
0
    svt_aom_wb_write_literal(wb, pars->ar_coeff_shift - 6, 2); // 8 + value
3263
3264
0
    svt_aom_wb_write_literal(wb, pars->grain_scale_shift, 2);
3265
3266
0
    if (pars->num_cb_points) {
3267
0
        svt_aom_wb_write_literal(wb, pars->cb_mult, 8);
3268
0
        svt_aom_wb_write_literal(wb, pars->cb_luma_mult, 8);
3269
0
        svt_aom_wb_write_literal(wb, pars->cb_offset, 9);
3270
0
    }
3271
3272
0
    if (pars->num_cr_points) {
3273
0
        svt_aom_wb_write_literal(wb, pars->cr_mult, 8);
3274
0
        svt_aom_wb_write_literal(wb, pars->cr_luma_mult, 8);
3275
0
        svt_aom_wb_write_literal(wb, pars->cr_offset, 9);
3276
0
    }
3277
3278
0
    svt_aom_wb_write_bit(wb, pars->overlap_flag);
3279
3280
0
    svt_aom_wb_write_bit(wb, pars->clip_to_restricted_range);
3281
0
}
3282
#endif
3283
3284
0
static uint32_t get_ref_order_hint(PictureParentControlSet* pcs, MvReferenceFrame ref_frame) {
3285
0
    int32_t ref_idx = get_ref_frame_map_idx(pcs, ref_frame);
3286
0
    if (ref_idx == INVALID_IDX) {
3287
0
        return INVALID_IDX;
3288
0
    }
3289
0
    return pcs->dpb_order_hint[ref_idx];
3290
0
}
3291
3292
0
static void write_frame_size_with_refs(PictureParentControlSet* pcs, AomWriteBitBuffer* wb) {
3293
#if DEBUG_SFRAME
3294
    fprintf(stderr,
3295
            "\nFrame %d, dpb buf order hint %u,%u,%u,%u,%u,%u,%u\n",
3296
            (int)pcs->picture_number,
3297
            get_ref_order_hint(pcs, LAST_FRAME),
3298
            get_ref_order_hint(pcs, LAST2_FRAME),
3299
            get_ref_order_hint(pcs, LAST3_FRAME),
3300
            get_ref_order_hint(pcs, GOLDEN_FRAME),
3301
            get_ref_order_hint(pcs, BWDREF_FRAME),
3302
            get_ref_order_hint(pcs, ALTREF2_FRAME),
3303
            get_ref_order_hint(pcs, ALTREF_FRAME));
3304
#endif
3305
0
    for (uint32_t ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
3306
0
        int32_t  found          = 0;
3307
0
        uint32_t ref_order_hint = get_ref_order_hint(pcs, ref_frame);
3308
0
        if ((int32_t)ref_order_hint != INVALID_IDX) {
3309
0
            for (uint8_t i = 0; i < pcs->ref_list0_count; ++i) {
3310
0
                EbReferenceObject* ref =
3311
0
                    (EbReferenceObject*)pcs->child_pcs->ref_pic_ptr_array[REF_LIST_0][i]->object_ptr;
3312
0
                if (ref->order_hint != ref_order_hint) {
3313
0
                    continue;
3314
0
                }
3315
                // Both super-res upscaled size and render size should be checked as per spec 5.9.7,
3316
                // but in current implementation, render_and_frame_size_different is fixed to 0, see
3317
                // function write_render_size()
3318
0
                found = pcs->enhanced_pic->width == ref->reference_picture->width &&
3319
0
                    pcs->enhanced_pic->height == ref->reference_picture->height;
3320
0
                if (found) {
3321
0
                    break;
3322
0
                }
3323
0
            }
3324
0
            if (!found) {
3325
0
                for (uint8_t i = 0; i < pcs->ref_list1_count; ++i) {
3326
0
                    EbReferenceObject* ref =
3327
0
                        (EbReferenceObject*)pcs->child_pcs->ref_pic_ptr_array[REF_LIST_1][i]->object_ptr;
3328
0
                    if (ref->order_hint != ref_order_hint) {
3329
0
                        continue;
3330
0
                    }
3331
0
                    found = pcs->enhanced_pic->width == ref->reference_picture->width &&
3332
0
                        pcs->enhanced_pic->height == ref->reference_picture->height;
3333
0
                    if (found) {
3334
0
                        break;
3335
0
                    }
3336
0
                }
3337
0
            }
3338
0
        }
3339
3340
0
        svt_aom_wb_write_bit(wb, found);
3341
0
        if (found) {
3342
0
            write_superres_scale(wb, pcs);
3343
0
            return;
3344
0
        }
3345
0
    }
3346
3347
    // not found
3348
0
    const int frame_size_override = 1; // Always equal to 1 in this function
3349
0
    write_frame_size(pcs, frame_size_override, wb);
3350
0
}
3351
3352
// New function based on HLS R18
3353
static void write_uncompressed_header_obu(SequenceControlSet* scs /*Av1Comp *cpi*/, PictureParentControlSet* pcs,
3354
1.06k
                                          AomWriteBitBuffer* wb, uint8_t show_existing) {
3355
    // Av1Common *const cm = &cpi->common;
3356
    // MacroBlockD *const xd = &cpi->td.mb.e_mbd;
3357
1.06k
    Av1Common* const cm       = pcs->av1_cm;
3358
1.06k
    uint16_t         tile_cnt = cm->tiles_info.tile_rows * cm->tiles_info.tile_cols;
3359
3360
1.06k
    FrameHeader* frm_hdr = &pcs->frm_hdr;
3361
1.06k
    if (!scs->seq_header.reduced_still_picture_header) {
3362
0
        if (show_existing) {
3363
            //SVT_ERROR("show_existing_frame not supported yet\n");
3364
            //RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
3365
            //const int32_t frame_to_show = cm->ref_frame_map[cpi->show_existing_frame];
3366
3367
            //if (frame_to_show < 0 || frame_bufs[frame_to_show].ref_count < 1) {
3368
            //    aom_internal_error(&cm->error, SVT_AOM_CODEC_UNSUP_BITSTREAM,
3369
            //        "Buffer %d does not contain a reconstructed frame",
3370
            //        frame_to_show);
3371
            //}
3372
            //ref_cnt_fb(frame_bufs, &cm->new_fb_idx, frame_to_show);
3373
3374
0
            svt_aom_wb_write_bit(wb, 1); // show_existing_frame
3375
0
            svt_aom_wb_write_literal(wb, frm_hdr->show_existing_frame, 3);
3376
0
            if (scs->seq_header.frame_id_numbers_present_flag) {
3377
0
                SVT_ERROR("frame_id_numbers_present_flag not supported yet\n");
3378
                /*int32_t frame_id_len = cm->seq_params.frame_id_length;
3379
                int32_t display_frame_id = cm->ref_frame_id[cpi->show_existing_frame];
3380
                svt_aom_wb_write_literal(wb, display_frame_id, frame_id_len);*/
3381
0
            }
3382
3383
            //        if (cm->reset_decoder_state &&
3384
            //            frame_bufs[frame_to_show].frame_type != KEY_FRAME) {
3385
            //            aom_internal_error(
3386
            //                &cm->error, SVT_AOM_CODEC_UNSUP_BITSTREAM,
3387
            //                "show_existing_frame to reset state on KEY_FRAME only");
3388
            //        }
3389
3390
0
            return;
3391
0
        } else {
3392
0
            svt_aom_wb_write_bit(wb, 0); // show_existing_frame
3393
0
        }
3394
3395
0
        svt_aom_wb_write_literal(wb, frm_hdr->frame_type, 2);
3396
3397
0
        svt_aom_wb_write_bit(wb, frm_hdr->show_frame);
3398
3399
0
        if (!frm_hdr->show_frame) {
3400
0
            svt_aom_wb_write_bit(wb, frm_hdr->showable_frame);
3401
0
        }
3402
0
        if (frm_hdr->frame_type == S_FRAME) {
3403
0
            assert(frm_hdr->error_resilient_mode);
3404
0
        } else if (!(frm_hdr->frame_type == KEY_FRAME && frm_hdr->show_frame)) {
3405
0
            svt_aom_wb_write_bit(wb, frm_hdr->error_resilient_mode);
3406
0
        }
3407
0
    }
3408
3409
1.06k
    svt_aom_wb_write_bit(wb, frm_hdr->disable_cdf_update);
3410
3411
1.06k
    if (scs->seq_header.seq_force_screen_content_tools == 2) {
3412
1.06k
        svt_aom_wb_write_bit(wb, frm_hdr->allow_screen_content_tools);
3413
1.06k
    } else {
3414
0
        assert(frm_hdr->allow_screen_content_tools == scs->seq_header.seq_force_screen_content_tools);
3415
0
    }
3416
3417
1.06k
    if (frm_hdr->allow_screen_content_tools) {
3418
0
        if (scs->seq_header.seq_force_integer_mv == 2) {
3419
0
            svt_aom_wb_write_bit(wb, frm_hdr->force_integer_mv);
3420
0
        } else {
3421
0
            assert(frm_hdr->force_integer_mv == scs->seq_header.seq_force_integer_mv);
3422
0
        }
3423
1.06k
    } else {
3424
1.06k
        assert(frm_hdr->force_integer_mv == 0);
3425
1.06k
    }
3426
3427
1.06k
    const int32_t frame_size_override_flag = frame_is_sframe(pcs) || pcs->frame_resize_enabled
3428
1.06k
        ? 1
3429
1.06k
        : ((pcs->av1_cm->frm_size.superres_upscaled_width != scs->seq_header.max_frame_width) ||
3430
1.06k
           (pcs->av1_cm->frm_size.superres_upscaled_height != scs->seq_header.max_frame_height));
3431
3432
1.06k
    if (!scs->seq_header.reduced_still_picture_header) {
3433
0
        if (scs->seq_header.frame_id_numbers_present_flag) {
3434
0
            int32_t frame_id_len = scs->seq_header.frame_id_length;
3435
0
            svt_aom_wb_write_literal(wb, frm_hdr->current_frame_id, frame_id_len);
3436
0
        }
3437
3438
        //if (cm->width > cm->seq_params.max_frame_width ||
3439
        //    cm->height > cm->seq_params.max_frame_height) {
3440
        //    aom_internal_error(&cm->error, SVT_AOM_CODEC_UNSUP_BITSTREAM,
3441
        //        "Frame dimensions are larger than the maximum values");
3442
        //}
3443
3444
0
        if (!frame_is_sframe(pcs)) {
3445
0
            svt_aom_wb_write_bit(wb, frame_size_override_flag);
3446
0
        }
3447
3448
0
        if (scs->seq_header.order_hint_info.enable_order_hint) {
3449
0
            svt_aom_wb_write_literal(wb, (int32_t)pcs->frame_offset, scs->seq_header.order_hint_info.order_hint_bits);
3450
0
        }
3451
3452
0
        if (!frm_hdr->error_resilient_mode && !frame_is_intra_only(pcs)) {
3453
0
            svt_aom_wb_write_literal(wb, frm_hdr->primary_ref_frame, PRIMARY_REF_BITS);
3454
0
        }
3455
1.06k
    } else { // reduced_still_picture_header
3456
1.06k
        assert(frame_size_override_flag == 0);
3457
1.06k
    }
3458
1.06k
    if (frm_hdr->frame_type == KEY_FRAME) {
3459
1.06k
        if (!frm_hdr->show_frame) {
3460
0
            svt_aom_wb_write_literal(wb, pcs->av1_ref_signal.refresh_frame_mask, REF_FRAMES);
3461
0
        }
3462
1.06k
    } else {
3463
0
        if (frm_hdr->frame_type == INTRA_ONLY_FRAME) {
3464
            // pcs->refresh_frame_mask = get_refresh_mask(cpi);
3465
0
            int32_t updated_fb = -1;
3466
0
            for (int32_t i = 0; i < REF_FRAMES; i++) {
3467
                // If more than one frame is refreshed, it doesn't matter which one
3468
                // we pick, so pick the first.
3469
0
                if (pcs->av1_ref_signal.refresh_frame_mask & (1 << i)) {
3470
0
                    updated_fb = i;
3471
0
                    break;
3472
0
                }
3473
0
            }
3474
0
            assert(updated_fb >= 0);
3475
0
            pcs->fb_of_context_type[pcs->frame_context_idx] = updated_fb;
3476
3477
0
            svt_aom_wb_write_literal(wb, pcs->av1_ref_signal.refresh_frame_mask, REF_FRAMES);
3478
0
        } else if (frm_hdr->frame_type == INTER_FRAME || frame_is_sframe(pcs)) {
3479
            //pcs->refresh_frame_mask = get_refresh_mask(cpi);
3480
0
            if (frm_hdr->frame_type == INTER_FRAME) {
3481
0
                svt_aom_wb_write_literal(wb, pcs->av1_ref_signal.refresh_frame_mask, REF_FRAMES);
3482
0
            } else {
3483
0
                assert(frame_is_sframe(pcs) && pcs->av1_ref_signal.refresh_frame_mask == 0xFF);
3484
0
            }
3485
3486
            // write ref order hint map into bitstream
3487
0
            if (pcs->frm_hdr.error_resilient_mode && scs->seq_header.order_hint_info.enable_order_hint) {
3488
0
                for (int32_t ref_idx = 0; ref_idx < REF_FRAMES; ref_idx++) {
3489
0
                    svt_aom_wb_write_literal(
3490
0
                        wb, pcs->dpb_order_hint[ref_idx], scs->seq_header.order_hint_info.order_hint_bits);
3491
0
                }
3492
0
            }
3493
3494
0
            int32_t updated_fb = -1;
3495
0
            for (int32_t i = 0; i < REF_FRAMES; i++) {
3496
                // If more than one frame is refreshed, it doesn't matter which one
3497
                // we pick, so pick the first.
3498
0
                if (pcs->av1_ref_signal.refresh_frame_mask & (1 << i)) {
3499
0
                    updated_fb = i;
3500
0
                    break;
3501
0
                }
3502
0
            }
3503
            // large scale tile sometimes won't refresh any fbs
3504
0
            if (updated_fb >= 0) {
3505
0
                pcs->fb_of_context_type[pcs->frame_context_idx] = updated_fb;
3506
0
            }
3507
0
        }
3508
0
    }
3509
3510
#if DEBUG_SFRAME
3511
    {
3512
        uint32_t* _ref_frame_map = pcs->dpb_order_hint;
3513
        fprintf(stderr,
3514
                "\nFrame %d, use_ref_frame_mvs %u, ref_order_hint_map %d,%d,%d,%d,%d,%d,%d,%d\n",
3515
                (int)pcs->picture_number,
3516
                frm_hdr->use_ref_frame_mvs,
3517
                _ref_frame_map[0],
3518
                _ref_frame_map[1],
3519
                _ref_frame_map[2],
3520
                _ref_frame_map[3],
3521
                _ref_frame_map[4],
3522
                _ref_frame_map[5],
3523
                _ref_frame_map[6],
3524
                _ref_frame_map[7]);
3525
    }
3526
#endif
3527
3528
1.06k
    if (frm_hdr->frame_type == KEY_FRAME) {
3529
1.06k
        write_frame_size(pcs, frame_size_override_flag, wb);
3530
1.06k
        assert(av1_superres_unscaled(&(pcs->av1_cm->frm_size)) || !(frm_hdr->allow_intrabc));
3531
1.06k
        if (frm_hdr->allow_screen_content_tools && av1_superres_unscaled(&(pcs->av1_cm->frm_size))) {
3532
0
            svt_aom_wb_write_bit(wb, frm_hdr->allow_intrabc);
3533
0
        }
3534
        // all eight fbs are refreshed, pick one that will live long enough
3535
1.06k
        pcs->fb_of_context_type[REGULAR_FRAME] = 0;
3536
1.06k
    } else {
3537
0
        if (frm_hdr->frame_type == INTRA_ONLY_FRAME) {
3538
0
            write_frame_size(pcs, frame_size_override_flag, wb);
3539
0
            assert(av1_superres_unscaled(&(pcs->av1_cm->frm_size)) || !(frm_hdr->allow_intrabc));
3540
0
            if (frm_hdr->allow_screen_content_tools && av1_superres_unscaled(&(pcs->av1_cm->frm_size))) {
3541
0
                svt_aom_wb_write_bit(wb, frm_hdr->allow_intrabc);
3542
0
            }
3543
0
        } else if (frm_hdr->frame_type == INTER_FRAME || frame_is_sframe(pcs)) {
3544
0
            MvReferenceFrame ref_frame;
3545
3546
0
            assert(frm_hdr->frame_refs_short_signaling == 0);
3547
            // NOTE: Error resilient mode turns off frame_refs_short_signaling
3548
            //       automatically.
3549
0
            if (scs->seq_header.order_hint_info.enable_order_hint) {
3550
0
                svt_aom_wb_write_bit(wb, frm_hdr->frame_refs_short_signaling);
3551
0
            }
3552
3553
0
            if (frm_hdr->frame_refs_short_signaling) {
3554
0
                svt_aom_wb_write_literal(wb, get_ref_frame_map_idx(pcs, LAST_FRAME), REF_FRAMES_LOG2);
3555
0
                svt_aom_wb_write_literal(wb, get_ref_frame_map_idx(pcs, GOLDEN_FRAME), REF_FRAMES_LOG2);
3556
0
            }
3557
0
            for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
3558
0
                assert(get_ref_frame_map_idx(pcs, ref_frame) != INVALID_IDX);
3559
0
                if (!frm_hdr->frame_refs_short_signaling) {
3560
0
                    svt_aom_wb_write_literal(wb, get_ref_frame_map_idx(pcs, ref_frame), REF_FRAMES_LOG2);
3561
0
                }
3562
3563
0
                if (scs->seq_header.frame_id_numbers_present_flag) {
3564
0
                    SVT_ERROR("frame_id_numbers_present_flag not supported yet\n");
3565
                    //int32_t i = get_ref_frame_map_idx(cpi, ref_frame);
3566
                    //int32_t frame_id_len = cm->seq_params.frame_id_length;
3567
                    //int32_t diff_len = cm->seq_params.delta_frame_id_length;
3568
                    //int32_t delta_frame_id_minus1 =
3569
                    //    ((cm->current_frame_id - cm->ref_frame_id[i] +
3570
                    //    (1 << frame_id_len)) %
3571
                    //    (1 << frame_id_len)) -
3572
                    //    1;
3573
                    //if (delta_frame_id_minus1 < 0 ||
3574
                    //    delta_frame_id_minus1 >= (1 << diff_len))
3575
                    //    cm->invalid_delta_frame_id_minus1 = 1;
3576
                    //svt_aom_wb_write_literal(wb, delta_frame_id_minus1, diff_len);
3577
0
                }
3578
0
            }
3579
3580
0
            if (!pcs->frm_hdr.error_resilient_mode && frame_size_override_flag) {
3581
0
                write_frame_size_with_refs(pcs, wb);
3582
0
            } else {
3583
0
                write_frame_size(pcs, frame_size_override_flag, wb);
3584
0
            }
3585
3586
0
            if (frm_hdr->force_integer_mv) {
3587
0
                frm_hdr->allow_high_precision_mv = 0;
3588
0
            } else {
3589
0
                svt_aom_wb_write_bit(wb, frm_hdr->allow_high_precision_mv);
3590
0
            }
3591
0
#define LOG_SWITCHABLE_FILTERS 2
3592
3593
0
            svt_aom_wb_write_bit(wb, pcs->frm_hdr.interpolation_filter == SWITCHABLE);
3594
0
            if (pcs->frm_hdr.interpolation_filter != SWITCHABLE) {
3595
0
                svt_aom_wb_write_literal(wb, pcs->frm_hdr.interpolation_filter, LOG_SWITCHABLE_FILTERS);
3596
0
            }
3597
3598
0
            svt_aom_wb_write_bit(wb, frm_hdr->is_motion_mode_switchable);
3599
0
            if (frame_might_allow_ref_frame_mvs(pcs, scs)) {
3600
0
                svt_aom_wb_write_bit(wb, frm_hdr->use_ref_frame_mvs);
3601
0
            }
3602
0
        }
3603
0
    }
3604
3605
    //if (scs->frame_id_numbers_present_flag)
3606
    //    pcs->refresh_mask = get_refresh_mask(pcs);
3607
1.06k
    const int32_t might_bwd_adapt = !(scs->seq_header.reduced_still_picture_header) && !(frm_hdr->disable_cdf_update);
3608
1.06k
    if (pcs->large_scale_tile) {
3609
0
        pcs->refresh_frame_context = REFRESH_FRAME_CONTEXT_DISABLED;
3610
0
    }
3611
1.06k
    if (might_bwd_adapt) {
3612
0
        svt_aom_wb_write_bit(wb, pcs->refresh_frame_context == REFRESH_FRAME_CONTEXT_DISABLED);
3613
0
    }
3614
3615
1.06k
    write_tile_info(pcs, /*saved_wb,*/ wb);
3616
3617
1.06k
    encode_quantization(pcs, wb);
3618
1.06k
    encode_segmentation(pcs, wb);
3619
    //svt_aom_wb_write_bit(wb, 0);
3620
    //encode_segmentation(cm, xd, wb);
3621
    //if (pcs->delta_q_present_flag)
3622
    // assert(delta_q_allowed == 1 && frm_hdr->quantisation_params.base_q_idx > 0);
3623
3624
1.06k
    if (frm_hdr->quantization_params.base_q_idx > 0) {
3625
614
        svt_aom_wb_write_bit(wb, frm_hdr->delta_q_params.delta_q_present);
3626
614
        if (frm_hdr->delta_q_params.delta_q_present) {
3627
0
            svt_aom_wb_write_literal(wb, svt_log2f_safe(frm_hdr->delta_q_params.delta_q_res), 2);
3628
0
            for (uint16_t tile_idx = 0; tile_idx < tile_cnt; tile_idx++) {
3629
0
                pcs->prev_qindex[tile_idx] = frm_hdr->quantization_params.base_q_idx;
3630
0
            }
3631
0
            if (frm_hdr->allow_intrabc) {
3632
0
                assert(frm_hdr->delta_lf_params.delta_lf_present == 0);
3633
0
            } else {
3634
0
                svt_aom_wb_write_bit(wb, frm_hdr->delta_lf_params.delta_lf_present);
3635
0
            }
3636
0
            if (frm_hdr->delta_lf_params.delta_lf_present) {
3637
0
                svt_aom_wb_write_literal(wb, svt_log2f_safe(frm_hdr->delta_lf_params.delta_lf_res), 2);
3638
0
                pcs->prev_delta_lf_from_base = 0;
3639
0
                svt_aom_wb_write_bit(wb, frm_hdr->delta_lf_params.delta_lf_multi);
3640
0
                const int32_t frame_lf_count = pcs->monochrome == 0 ? FRAME_LF_COUNT : FRAME_LF_COUNT - 2;
3641
0
                for (int32_t lf_id = 0; lf_id < frame_lf_count; ++lf_id) {
3642
0
                    pcs->prev_delta_lf[lf_id] = 0;
3643
0
                }
3644
0
            }
3645
0
        }
3646
614
    }
3647
3648
1.06k
    if (frm_hdr->all_lossless) {
3649
452
        assert(av1_superres_unscaled(&(pcs->av1_cm->frm_size)));
3650
614
    } else {
3651
614
        if (!frm_hdr->coded_lossless) {
3652
614
            encode_loopfilter(pcs, wb);
3653
614
            if (scs->seq_header.cdef_level) {
3654
614
                encode_cdef(pcs, wb);
3655
614
            }
3656
614
        }
3657
3658
614
        if (scs->seq_header.enable_restoration) {
3659
0
            encode_restoration_mode(pcs, wb);
3660
0
        }
3661
614
    }
3662
1.06k
    if (frm_hdr->coded_lossless) {
3663
452
        assert(1); // assert(frm_hdr->tx_mode == ONLY_4X4);
3664
614
    } else {
3665
614
        svt_aom_wb_write_bit(wb, frm_hdr->tx_mode == TX_MODE_SELECT);
3666
614
    }
3667
    //write_tx_mode(cm, &pcs->tx_mode, wb);
3668
3669
1.06k
    if (pcs->allow_comp_inter_inter) {
3670
0
        const int32_t use_hybrid_pred = frm_hdr->reference_mode == REFERENCE_MODE_SELECT;
3671
3672
0
        svt_aom_wb_write_bit(wb, use_hybrid_pred);
3673
0
    }
3674
3675
1.06k
    if (frm_hdr->skip_mode_params.skip_mode_allowed) {
3676
0
        svt_aom_wb_write_bit(wb, frm_hdr->skip_mode_params.skip_mode_flag);
3677
0
    }
3678
3679
1.06k
    if (frame_might_allow_warped_motion(pcs, scs)) {
3680
0
        svt_aom_wb_write_bit(wb, frm_hdr->allow_warped_motion);
3681
1.06k
    } else {
3682
1.06k
        assert(!frm_hdr->allow_warped_motion);
3683
1.06k
    }
3684
3685
1.06k
    svt_aom_wb_write_bit(wb, frm_hdr->reduced_tx_set);
3686
3687
1.06k
    if (!frame_is_intra_only(pcs)) {
3688
        //  SVT_ERROR("Global motion not supported yet\n");
3689
0
        write_global_motion(pcs, wb);
3690
0
    }
3691
1.06k
#if CONFIG_ENABLE_FILM_GRAIN
3692
1.06k
    if (scs->seq_header.film_grain_params_present && (frm_hdr->show_frame || frm_hdr->showable_frame)) {
3693
0
        write_film_grain_params(pcs, wb);
3694
0
    }
3695
1.06k
#endif
3696
1.06k
}
3697
3698
1.59k
static uint32_t write_obu_header(ObuType obu_type, int32_t obuExtension, uint8_t* const dst) {
3699
1.59k
    AomWriteBitBuffer wb   = {dst, 0};
3700
1.59k
    uint32_t          size = 0;
3701
3702
1.59k
    svt_aom_wb_write_literal(&wb, 0, 1); // forbidden bit.
3703
1.59k
    svt_aom_wb_write_literal(&wb, (int32_t)obu_type, 4);
3704
1.59k
    svt_aom_wb_write_literal(&wb, obuExtension ? 1 : 0, 1);
3705
1.59k
    svt_aom_wb_write_literal(&wb, 1, 1); // obu_has_payload_length_field
3706
1.59k
    svt_aom_wb_write_literal(&wb, 0, 1); // reserved
3707
3708
1.59k
    if (obuExtension) {
3709
0
        svt_aom_wb_write_literal(&wb, obuExtension & 0xFF, 8);
3710
0
    }
3711
1.59k
    size = svt_aom_wb_bytes_written(&wb);
3712
1.59k
    return size;
3713
1.59k
}
3714
3715
533
static int32_t write_uleb_obu_size(uint32_t obu_header_size, uint32_t obu_payload_size, uint8_t* dest) {
3716
533
    const uint32_t obu_size       = obu_payload_size;
3717
533
    const uint32_t offset         = obu_header_size;
3718
533
    size_t         coded_obu_size = 0;
3719
3720
533
    if (svt_aom_uleb_encode(obu_size, sizeof(obu_size), dest + offset, &coded_obu_size) != 0) {
3721
0
        return SVT_AOM_CODEC_ERROR;
3722
0
    }
3723
3724
533
    return SVT_AOM_CODEC_OK;
3725
533
}
3726
3727
1.06k
static void add_trailing_bits(AomWriteBitBuffer* wb) {
3728
1.06k
    if (svt_aom_wb_is_byte_aligned(wb)) {
3729
568
        svt_aom_wb_write_literal(wb, 0x80, 8);
3730
568
    } else {
3731
        // assumes that the other bits are already 0s
3732
498
        svt_aom_wb_write_bit(wb, 1);
3733
498
    }
3734
1.06k
}
3735
3736
// writes the type and payload of the provided metadata to the address dst as a metadata OBU
3737
0
static uint32_t write_obu_metadata(SvtMetadataT* metadata, uint8_t* const dst) {
3738
0
    if (!metadata || !metadata->payload) {
3739
0
        return 0;
3740
0
    }
3741
0
    AomWriteBitBuffer wb   = {dst, 0};
3742
0
    uint32_t          size = 0;
3743
0
    svt_aom_wb_write_literal(&wb, metadata->type, 8);
3744
0
    for (size_t i = 0; i < metadata->sz; ++i) {
3745
0
        svt_aom_wb_write_literal(&wb, metadata->payload[i], 8);
3746
0
    }
3747
0
    add_trailing_bits(&wb);
3748
0
    size = svt_aom_wb_bytes_written(&wb);
3749
0
    return size;
3750
0
}
3751
3752
1.06k
static void write_bitstream_level(BitstreamLevel bl, AomWriteBitBuffer* wb) {
3753
1.06k
    uint8_t seq_level_idx = major_minor_to_seq_level_idx(bl);
3754
1.06k
    assert(is_valid_seq_level_idx(seq_level_idx));
3755
1.06k
    svt_aom_wb_write_literal(wb, seq_level_idx, LEVEL_BITS);
3756
1.06k
}
3757
3758
1.06k
static uint32_t write_sequence_header_obu(SequenceControlSet* scs, uint8_t* const dst, uint8_t numberSpatialLayers) {
3759
1.06k
    AomWriteBitBuffer wb   = {dst, 0};
3760
1.06k
    uint32_t          size = 0;
3761
3762
1.06k
    set_bitstream_level_tier(scs);
3763
3764
1.06k
    write_profile((BitstreamProfile)scs->static_config.profile, &wb);
3765
3766
    // Still picture or not
3767
1.06k
    svt_aom_wb_write_bit(&wb, scs->seq_header.still_picture);
3768
1.06k
    assert(IMPLIES(!scs->seq_header.still_picture, !scs->seq_header.reduced_still_picture_header));
3769
3770
    // whether to use reduced still picture header
3771
1.06k
    svt_aom_wb_write_bit(&wb, scs->seq_header.reduced_still_picture_header);
3772
3773
1.06k
    if (scs->seq_header.reduced_still_picture_header) {
3774
1.06k
        write_bitstream_level(scs->level[0], &wb);
3775
1.06k
    } else {
3776
0
        svt_aom_wb_write_bit(&wb, scs->seq_header.timing_info.timing_info_present); // timing info present flag
3777
3778
0
        if (scs->seq_header.timing_info.timing_info_present) {
3779
            // timing_info
3780
0
            SVT_ERROR("timing_info_present not supported\n");
3781
            /*write_timing_info_header(cm, &wb);
3782
            svt_aom_wb_write_bit(&wb, cm->decoder_model_info_present_flag);
3783
            if (cm->decoder_model_info_present_flag) write_decoder_model_info(cm, &wb);*/
3784
0
        }
3785
0
        svt_aom_wb_write_bit(&wb, scs->seq_header.initial_display_delay_present_flag);
3786
3787
0
        uint8_t operating_points_cnt_minus_1 = numberSpatialLayers > 1 ? numberSpatialLayers - 1 : 0;
3788
0
        svt_aom_wb_write_literal(&wb, operating_points_cnt_minus_1, OP_POINTS_CNT_MINUS_1_BITS);
3789
0
        int32_t i;
3790
0
        for (i = 0; i < operating_points_cnt_minus_1 + 1; i++) {
3791
0
            svt_aom_wb_write_literal(&wb, scs->seq_header.operating_point[i].op_idc, OP_POINTS_IDC_BITS);
3792
0
            write_bitstream_level(scs->level[i], &wb);
3793
0
            if (scs->level[i].major > 3) {
3794
0
                svt_aom_wb_write_bit(&wb, scs->seq_header.operating_point[i].seq_tier);
3795
0
            }
3796
0
            if (scs->seq_header.decoder_model_info_present_flag) {
3797
0
                SVT_ERROR("decoder_model_info_present_flag not supported\n");
3798
                //svt_aom_wb_write_bit(&wb,
3799
                //    cm->op_params[i].decoder_model_param_present_flag);
3800
                //if (cm->op_params[i].decoder_model_param_present_flag)
3801
                //    write_dec_model_op_parameters(cm, &wb, i);
3802
0
            }
3803
0
            if (scs->seq_header.initial_display_delay_present_flag) {
3804
0
                SVT_ERROR("display_model_info_present_flag not supported\n");
3805
                //svt_aom_wb_write_bit(&wb,
3806
                //    cm->op_params[i].display_model_param_present_flag);
3807
                //if (cm->op_params[i].display_model_param_present_flag) {
3808
                //    assert(cm->op_params[i].initial_display_delay <= 10);
3809
                //    svt_aom_wb_write_literal(&wb, cm->op_params[i].initial_display_delay - 1,
3810
                //        4);
3811
                //}
3812
0
            }
3813
0
        }
3814
0
    }
3815
1.06k
    write_sequence_header(scs, &wb);
3816
3817
1.06k
    write_color_config(scs, &wb);
3818
3819
1.06k
    svt_aom_wb_write_bit(&wb, scs->seq_header.film_grain_params_present);
3820
3821
1.06k
    add_trailing_bits(&wb);
3822
3823
1.06k
    size = svt_aom_wb_bytes_written(&wb);
3824
1.06k
    return size;
3825
1.06k
}
3826
3827
static uint32_t write_tile_group_header(uint8_t* const dst, int startTile, int endTile, int tiles_log2,
3828
1.06k
                                        int tile_start_and_end_present_flag) {
3829
1.06k
    AomWriteBitBuffer wb   = {dst, 0};
3830
1.06k
    uint32_t          size = 0;
3831
3832
1.06k
    if (!tiles_log2) {
3833
12
        return size;
3834
12
    }
3835
1.05k
    svt_aom_wb_write_bit(&wb, tile_start_and_end_present_flag);
3836
3837
1.05k
    if (tile_start_and_end_present_flag) {
3838
0
        svt_aom_wb_write_literal(&wb, startTile, tiles_log2);
3839
0
        svt_aom_wb_write_literal(&wb, endTile, tiles_log2);
3840
0
    }
3841
3842
1.05k
    size = svt_aom_wb_bytes_written(&wb);
3843
1.05k
    return size;
3844
1.06k
}
3845
3846
static uint32_t write_frame_header_obu(SequenceControlSet* scs, PictureParentControlSet* pcs, uint8_t* const dst,
3847
1.06k
                                       uint8_t show_existing, int32_t appendTrailingBits) {
3848
1.06k
    AomWriteBitBuffer wb         = {dst, 0};
3849
1.06k
    uint32_t          total_size = 0;
3850
3851
1.06k
    write_uncompressed_header_obu(scs, pcs, /* saved_wb,*/ &wb, show_existing);
3852
3853
1.06k
    if (appendTrailingBits) {
3854
0
        add_trailing_bits(&wb);
3855
0
    }
3856
3857
1.06k
    if (show_existing) {
3858
0
        total_size = svt_aom_wb_bytes_written(&wb);
3859
0
        return total_size;
3860
0
    }
3861
3862
1.06k
    total_size = svt_aom_wb_bytes_written(&wb);
3863
1.06k
    return total_size;
3864
1.06k
}
3865
3866
EbErrorType svt_aom_write_metadata_av1(Bitstream* bitstream_ptr, SvtMetadataArrayT* metadata,
3867
1.59k
                                       const EbAv1MetadataType type) {
3868
1.59k
    EbErrorType return_error = EB_ErrorNone;
3869
1.59k
    if (!metadata || !metadata->metadata_array) {
3870
1.59k
        return EB_ErrorBadParameter;
3871
1.59k
    }
3872
3873
0
    OutputBitstreamUnit* output_bitstream_ptr = (OutputBitstreamUnit*)bitstream_ptr->output_bitstream_ptr;
3874
0
    uint8_t*             data                 = output_bitstream_ptr->buffer_av1;
3875
3876
0
    for (size_t i = 0; i < metadata->sz; i++) {
3877
0
        SvtMetadataT* current_metadata = metadata->metadata_array[i];
3878
0
        if (current_metadata && current_metadata->payload && current_metadata->type == type) {
3879
            // Phase 1: measure header + payload sizes
3880
0
            uint32_t obu_header_size   = write_obu_header(OBU_METADATA, 0, data);
3881
0
            uint32_t obu_payload_size  = write_obu_metadata(current_metadata, data + obu_header_size);
3882
0
            size_t   length_field_size = svt_aom_uleb_size_in_bytes(obu_payload_size);
3883
3884
            // Phase 2: write at correct offsets (re-write payload after LEB128)
3885
            // OBU header already at data[0]
3886
0
            size_t  coded_size;
3887
0
            int32_t ret = svt_aom_uleb_encode(
3888
0
                obu_payload_size, sizeof(obu_payload_size), data + obu_header_size, &coded_size);
3889
0
            assert(ret == 0 && coded_size == length_field_size);
3890
0
            if (ret != 0 || coded_size != length_field_size) {
3891
0
                return EB_ErrorBadParameter;
3892
0
            }
3893
0
            write_obu_metadata(current_metadata, data + obu_header_size + length_field_size);
3894
3895
0
            data += obu_header_size + length_field_size + obu_payload_size;
3896
0
        }
3897
0
    }
3898
0
    output_bitstream_ptr->buffer_av1 = data;
3899
0
    return return_error;
3900
0
}
3901
3902
/**************************************************
3903
* EncodeFrameHeaderHeader
3904
**************************************************/
3905
EbErrorType svt_aom_write_frame_header_av1(Bitstream* bitstream_ptr, SequenceControlSet* scs, PictureControlSet* pcs,
3906
533
                                           uint8_t show_existing) {
3907
533
    EbErrorType              return_error         = EB_ErrorNone;
3908
533
    OutputBitstreamUnit*     output_bitstream_ptr = (OutputBitstreamUnit*)bitstream_ptr->output_bitstream_ptr;
3909
533
    PictureParentControlSet* ppcs                 = pcs->ppcs;
3910
533
    Av1Common* const         cm                   = ppcs->av1_cm;
3911
533
    uint16_t                 tile_cnt             = cm->tiles_info.tile_rows * cm->tiles_info.tile_cols;
3912
533
    uint8_t*                 data                 = output_bitstream_ptr->buffer_av1;
3913
3914
533
    ObuType obu_type                        = show_existing ? OBU_FRAME_HEADER : OBU_FRAME;
3915
533
    int     n_log2_tiles                    = ppcs->av1_cm->log2_tile_rows + ppcs->av1_cm->log2_tile_cols;
3916
533
    int     tile_start_and_end_present_flag = 0;
3917
3918
    // Phase 1: Measure header sizes by writing to data (will be overwritten in phase 2).
3919
533
    uint32_t obu_header_size = write_obu_header(obu_type, 0, data);
3920
533
    uint32_t frame_hdr_size  = write_frame_header_obu(scs, ppcs, data + obu_header_size, show_existing, show_existing);
3921
533
    uint32_t tg_hdr_size     = write_tile_group_header(
3922
533
        data + obu_header_size + frame_hdr_size, 0, 0, n_log2_tiles, tile_start_and_end_present_flag);
3923
533
    uint32_t hdr_payload_size = frame_hdr_size + tg_hdr_size;
3924
3925
    // Compute tile data size (tile size prefixes + tile data).
3926
533
    uint32_t tile_data_size = 0;
3927
533
    if (!show_existing) {
3928
6.20k
        for (int tile_idx = 0; tile_idx < tile_cnt; tile_idx++) {
3929
5.67k
            tile_data_size += pcs->ec_info[tile_idx]->ec->ec_writer.pos;
3930
5.67k
            if (tile_idx != tile_cnt - 1 && tile_cnt > 1) {
3931
5.14k
                tile_data_size += pcs->tile_size_bytes_minus_1 + 1;
3932
5.14k
            }
3933
5.67k
        }
3934
533
    }
3935
3936
    // Compute exact OBU payload size and LEB128 field size.
3937
533
    uint32_t obu_payload_size  = hdr_payload_size + tile_data_size;
3938
533
    size_t   length_field_size = svt_aom_uleb_size_in_bytes(obu_payload_size);
3939
3940
    // Ensure buffer is large enough for the complete OBU.
3941
533
    uint32_t total_obu_size = obu_header_size + (uint32_t)length_field_size + obu_payload_size;
3942
533
    uint32_t buf_needed     = total_obu_size +
3943
533
        (uint32_t)(output_bitstream_ptr->buffer_av1 - output_bitstream_ptr->buffer_begin_av1);
3944
533
    if (output_bitstream_ptr->size < buf_needed) {
3945
0
        svt_realloc_output_bitstream_unit(output_bitstream_ptr, buf_needed + 1);
3946
0
        data = output_bitstream_ptr->buffer_av1;
3947
0
    }
3948
3949
    // Phase 2: Write everything at the correct offsets — no memmove needed.
3950
    // OBU header is already at data[0] from phase 1 (same content, same position).
3951
3952
    // LEB128 size field right after OBU header.
3953
533
    size_t coded_size;
3954
533
    svt_aom_uleb_encode(obu_payload_size, sizeof(obu_payload_size), data + obu_header_size, &coded_size);
3955
3956
    // Re-write frame header + tile group header at the correct offset (after LEB128).
3957
533
    uint32_t write_offset = obu_header_size + (uint32_t)length_field_size;
3958
533
    write_frame_header_obu(scs, ppcs, data + write_offset, show_existing, show_existing);
3959
533
    write_offset += frame_hdr_size;
3960
533
    write_tile_group_header(data + write_offset, 0, 0, n_log2_tiles, tile_start_and_end_present_flag);
3961
533
    write_offset += tg_hdr_size;
3962
3963
    // Copy tile data.
3964
533
    if (!show_existing) {
3965
6.20k
        for (int tile_idx = 0; tile_idx < tile_cnt; tile_idx++) {
3966
5.67k
            int32_t tile_size       = pcs->ec_info[tile_idx]->ec->ec_writer.pos;
3967
5.67k
            uint8_t tile_size_bytes = 0;
3968
5.67k
            if (tile_idx != tile_cnt - 1 && tile_cnt > 1) {
3969
5.14k
                tile_size_bytes = pcs->tile_size_bytes_minus_1 + 1;
3970
5.14k
                mem_put_varsize(data + write_offset, tile_size_bytes, tile_size - 1);
3971
5.14k
            }
3972
5.67k
            OutputBitstreamUnit* ec_output_bitstream_ptr =
3973
5.67k
                (OutputBitstreamUnit*)pcs->ec_info[tile_idx]->ec->ec_output_bitstream_ptr;
3974
5.67k
            svt_memcpy(data + write_offset + tile_size_bytes, ec_output_bitstream_ptr->buffer_begin_av1, tile_size);
3975
5.67k
            write_offset += (tile_size + tile_size_bytes);
3976
5.67k
        }
3977
533
    }
3978
3979
533
    data += total_obu_size;
3980
533
    output_bitstream_ptr->buffer_av1 = data;
3981
533
    return return_error;
3982
533
}
3983
3984
/**************************************************
3985
* svt_aom_encode_sps_av1
3986
**************************************************/
3987
533
EbErrorType svt_aom_encode_sps_av1(Bitstream* bitstream_ptr, SequenceControlSet* scs) {
3988
533
    EbErrorType          return_error             = EB_ErrorNone;
3989
533
    OutputBitstreamUnit* output_bitstream_ptr     = (OutputBitstreamUnit*)bitstream_ptr->output_bitstream_ptr;
3990
533
    uint8_t*             data                     = output_bitstream_ptr->buffer_av1;
3991
533
    const uint8_t        enhancement_layers_count = 0; // cm->enhancement_layers_count;
3992
3993
    // Phase 1: measure
3994
533
    uint32_t obu_header_size   = write_obu_header(OBU_SEQUENCE_HEADER, 0, data);
3995
533
    uint32_t obu_payload_size  = write_sequence_header_obu(scs, data + obu_header_size, enhancement_layers_count);
3996
533
    size_t   length_field_size = svt_aom_uleb_size_in_bytes(obu_payload_size);
3997
3998
    // Phase 2: write at correct offsets (re-write payload after LEB128)
3999
533
    size_t  coded_size;
4000
533
    int32_t ret = svt_aom_uleb_encode(obu_payload_size, sizeof(obu_payload_size), data + obu_header_size, &coded_size);
4001
533
    assert(ret == 0 && coded_size == length_field_size);
4002
533
    if (ret != 0 || coded_size != length_field_size) {
4003
0
        return EB_ErrorBadParameter;
4004
0
    }
4005
533
    write_sequence_header_obu(scs, data + obu_header_size + length_field_size, enhancement_layers_count);
4006
4007
533
    data += obu_header_size + length_field_size + obu_payload_size;
4008
533
    output_bitstream_ptr->buffer_av1 = data;
4009
533
    return return_error;
4010
533
}
4011
4012
/**************************************************
4013
* svt_aom_encode_td_av1
4014
**************************************************/
4015
533
EbErrorType svt_aom_encode_td_av1(uint8_t* output_bitstream_ptr) {
4016
533
    assert(output_bitstream_ptr != NULL);
4017
4018
    // move data and insert OBU_TD preceded by optional 4 byte size
4019
    // OBUs are preceded/succeeded by an unsigned leb128 coded integer.
4020
533
    write_uleb_obu_size(write_obu_header(OBU_TEMPORAL_DELIMITER, 0, output_bitstream_ptr), 0, output_bitstream_ptr);
4021
533
    return EB_ErrorNone;
4022
533
}
4023
4024
0
static void av1_write_delta_q_index(FRAME_CONTEXT* frame_context, int32_t delta_qindex, AomWriter* w) {
4025
0
    int32_t sign     = delta_qindex < 0;
4026
0
    int32_t abs      = sign ? -delta_qindex : delta_qindex;
4027
0
    int32_t smallval = abs < DELTA_Q_SMALL ? 1 : 0;
4028
    //FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
4029
4030
0
    aom_write_symbol(w, AOMMIN(abs, DELTA_Q_SMALL), frame_context->delta_q_cdf, DELTA_Q_PROBS + 1);
4031
4032
0
    if (!smallval) {
4033
0
        int32_t rem_bits = svt_log2f(abs - 1);
4034
0
        int32_t thr      = (1 << rem_bits) + 1;
4035
0
        aom_write_literal(w, rem_bits - 1, 3);
4036
0
        aom_write_literal(w, abs - thr, rem_bits);
4037
0
    }
4038
0
    if (abs > 0) {
4039
0
        aom_write_bit(w, sign);
4040
0
    }
4041
0
}
4042
4043
static void write_cdef(SequenceControlSet* scs, PictureControlSet* pcs, EntropyCodingContext* ctx, AomWriter* w,
4044
146k
                       int32_t skip, int32_t mi_col, int32_t mi_row) {
4045
146k
    Av1Common*   cm      = pcs->ppcs->av1_cm;
4046
146k
    FrameHeader* frm_hdr = &pcs->ppcs->frm_hdr;
4047
4048
146k
    if (frm_hdr->coded_lossless || frm_hdr->allow_intrabc) {
4049
        // Initialize to indicate no CDEF for safety.
4050
138k
        frm_hdr->cdef_params.cdef_bits           = 0;
4051
138k
        frm_hdr->cdef_params.cdef_y_strength[0]  = 0;
4052
138k
        pcs->ppcs->nb_cdef_strengths             = 1;
4053
138k
        frm_hdr->cdef_params.cdef_uv_strength[0] = 0;
4054
138k
        return;
4055
138k
    }
4056
4057
8.21k
    const int32_t     m    = ~((1 << (6 - MI_SIZE_LOG2)) - 1);
4058
8.21k
    const MbModeInfo* mbmi = pcs->mi_grid_base[(mi_row & m) * cm->mi_stride + (mi_col & m)];
4059
4060
    // Initialise when at top left part of the superblock
4061
8.21k
    if (!(mi_row & (scs->seq_header.sb_mi_size - 1)) && !(mi_col & (scs->seq_header.sb_mi_size - 1))) { // Top left?
4062
4.18k
        ctx->cdef_transmitted[0] = ctx->cdef_transmitted[1] = ctx->cdef_transmitted[2] = ctx->cdef_transmitted[3] =
4063
4.18k
            false;
4064
4.18k
    }
4065
4066
    // Emit CDEF param at first non-skip coding block
4067
8.21k
    const int32_t mask  = 1 << (6 - MI_SIZE_LOG2);
4068
8.21k
    const int32_t index = scs->seq_header.sb_size == BLOCK_128X128 ? !!(mi_col & mask) + 2 * !!(mi_row & mask) : 0;
4069
4070
8.21k
    if (!ctx->cdef_transmitted[index] && !skip) {
4071
3.80k
        aom_write_literal(w, mbmi->cdef_strength, frm_hdr->cdef_params.cdef_bits);
4072
3.80k
        ctx->cdef_transmitted[index] = true;
4073
3.80k
    }
4074
8.21k
}
4075
4076
5.67k
void svt_av1_reset_loop_restoration(EntropyCodingContext* ctx) {
4077
22.7k
    for (int32_t p = 0; p < MAX_PLANES; ++p) {
4078
17.0k
        set_default_wiener(ctx->wiener_info + p);
4079
17.0k
        set_default_sgrproj(ctx->sgrproj_info + p);
4080
17.0k
    }
4081
5.67k
}
4082
4083
static void write_wiener_filter(int32_t wiener_win, const WienerInfo* wiener_info, WienerInfo* ref_wiener_info,
4084
0
                                AomWriter* wb) {
4085
0
    if (wiener_win == WIENER_WIN) {
4086
0
        svt_aom_write_primitive_refsubexpfin(wb,
4087
0
                                             WIENER_FILT_TAP0_MAXV - WIENER_FILT_TAP0_MINV + 1,
4088
0
                                             WIENER_FILT_TAP0_SUBEXP_K,
4089
0
                                             ref_wiener_info->vfilter[0] - WIENER_FILT_TAP0_MINV,
4090
0
                                             wiener_info->vfilter[0] - WIENER_FILT_TAP0_MINV);
4091
0
    } else {
4092
0
        assert(wiener_info->vfilter[0] == 0 && wiener_info->vfilter[WIENER_WIN - 1] == 0);
4093
0
    }
4094
0
    svt_aom_write_primitive_refsubexpfin(wb,
4095
0
                                         WIENER_FILT_TAP1_MAXV - WIENER_FILT_TAP1_MINV + 1,
4096
0
                                         WIENER_FILT_TAP1_SUBEXP_K,
4097
0
                                         ref_wiener_info->vfilter[1] - WIENER_FILT_TAP1_MINV,
4098
0
                                         wiener_info->vfilter[1] - WIENER_FILT_TAP1_MINV);
4099
0
    svt_aom_write_primitive_refsubexpfin(wb,
4100
0
                                         WIENER_FILT_TAP2_MAXV - WIENER_FILT_TAP2_MINV + 1,
4101
0
                                         WIENER_FILT_TAP2_SUBEXP_K,
4102
0
                                         ref_wiener_info->vfilter[2] - WIENER_FILT_TAP2_MINV,
4103
0
                                         wiener_info->vfilter[2] - WIENER_FILT_TAP2_MINV);
4104
0
    if (wiener_win == WIENER_WIN) {
4105
0
        svt_aom_write_primitive_refsubexpfin(wb,
4106
0
                                             WIENER_FILT_TAP0_MAXV - WIENER_FILT_TAP0_MINV + 1,
4107
0
                                             WIENER_FILT_TAP0_SUBEXP_K,
4108
0
                                             ref_wiener_info->hfilter[0] - WIENER_FILT_TAP0_MINV,
4109
0
                                             wiener_info->hfilter[0] - WIENER_FILT_TAP0_MINV);
4110
0
    } else {
4111
0
        assert(wiener_info->hfilter[0] == 0 && wiener_info->hfilter[WIENER_WIN - 1] == 0);
4112
0
    }
4113
0
    svt_aom_write_primitive_refsubexpfin(wb,
4114
0
                                         WIENER_FILT_TAP1_MAXV - WIENER_FILT_TAP1_MINV + 1,
4115
0
                                         WIENER_FILT_TAP1_SUBEXP_K,
4116
0
                                         ref_wiener_info->hfilter[1] - WIENER_FILT_TAP1_MINV,
4117
0
                                         wiener_info->hfilter[1] - WIENER_FILT_TAP1_MINV);
4118
0
    svt_aom_write_primitive_refsubexpfin(wb,
4119
0
                                         WIENER_FILT_TAP2_MAXV - WIENER_FILT_TAP2_MINV + 1,
4120
0
                                         WIENER_FILT_TAP2_SUBEXP_K,
4121
0
                                         ref_wiener_info->hfilter[2] - WIENER_FILT_TAP2_MINV,
4122
0
                                         wiener_info->hfilter[2] - WIENER_FILT_TAP2_MINV);
4123
0
    svt_memcpy(ref_wiener_info, wiener_info, sizeof(*wiener_info));
4124
0
}
4125
4126
0
static void write_sgrproj_filter(const SgrprojInfo* sgrproj_info, SgrprojInfo* ref_sgrproj_info, AomWriter* wb) {
4127
0
    aom_write_literal(wb, sgrproj_info->ep, SGRPROJ_PARAMS_BITS);
4128
0
    const SgrParamsType* params = &svt_aom_eb_sgr_params[sgrproj_info->ep];
4129
4130
0
    if (params->r[0] == 0) {
4131
0
        assert(sgrproj_info->xqd[0] == 0);
4132
0
        svt_aom_write_primitive_refsubexpfin(wb,
4133
0
                                             SGRPROJ_PRJ_MAX1 - SGRPROJ_PRJ_MIN1 + 1,
4134
0
                                             SGRPROJ_PRJ_SUBEXP_K,
4135
0
                                             (uint16_t)(ref_sgrproj_info->xqd[1] - SGRPROJ_PRJ_MIN1),
4136
0
                                             (uint16_t)(sgrproj_info->xqd[1] - SGRPROJ_PRJ_MIN1));
4137
0
    } else if (params->r[1] == 0) {
4138
0
        svt_aom_write_primitive_refsubexpfin(wb,
4139
0
                                             SGRPROJ_PRJ_MAX0 - SGRPROJ_PRJ_MIN0 + 1,
4140
0
                                             SGRPROJ_PRJ_SUBEXP_K,
4141
0
                                             (uint16_t)(ref_sgrproj_info->xqd[0] - SGRPROJ_PRJ_MIN0),
4142
0
                                             (uint16_t)(sgrproj_info->xqd[0] - SGRPROJ_PRJ_MIN0));
4143
0
    } else {
4144
0
        svt_aom_write_primitive_refsubexpfin(wb,
4145
0
                                             SGRPROJ_PRJ_MAX0 - SGRPROJ_PRJ_MIN0 + 1,
4146
0
                                             SGRPROJ_PRJ_SUBEXP_K,
4147
0
                                             (uint16_t)(ref_sgrproj_info->xqd[0] - SGRPROJ_PRJ_MIN0),
4148
0
                                             (uint16_t)(sgrproj_info->xqd[0] - SGRPROJ_PRJ_MIN0));
4149
0
        svt_aom_write_primitive_refsubexpfin(wb,
4150
0
                                             SGRPROJ_PRJ_MAX1 - SGRPROJ_PRJ_MIN1 + 1,
4151
0
                                             SGRPROJ_PRJ_SUBEXP_K,
4152
0
                                             (uint16_t)(ref_sgrproj_info->xqd[1] - SGRPROJ_PRJ_MIN1),
4153
0
                                             (uint16_t)(sgrproj_info->xqd[1] - SGRPROJ_PRJ_MIN1));
4154
0
    }
4155
4156
0
    svt_memcpy(ref_sgrproj_info, sgrproj_info, sizeof(*sgrproj_info));
4157
0
}
4158
4159
static void loop_restoration_write_sb_coeffs(PictureControlSet* pcs, FRAME_CONTEXT* frame_context,
4160
                                             EntropyCodingContext* ctx, const RestorationUnitInfo* rui,
4161
0
                                             AomWriter* const w, int32_t plane) {
4162
0
    const RestorationInfo* rsi         = pcs->rst_info + plane;
4163
0
    RestorationType        frame_rtype = rsi->frame_restoration_type;
4164
0
    if (frame_rtype == RESTORE_NONE) {
4165
0
        return;
4166
0
    }
4167
4168
0
    const int32_t   wiener_win   = (plane > 0) ? WIENER_WIN_CHROMA : WIENER_WIN;
4169
0
    WienerInfo*     wiener_info  = &ctx->wiener_info[plane];
4170
0
    SgrprojInfo*    sgrproj_info = &ctx->sgrproj_info[plane];
4171
0
    RestorationType unit_rtype   = rui->restoration_type;
4172
4173
0
    assert(unit_rtype < CDF_SIZE(RESTORE_SWITCHABLE_TYPES));
4174
4175
0
    if (frame_rtype == RESTORE_SWITCHABLE) {
4176
0
        aom_write_symbol(w,
4177
0
                         unit_rtype,
4178
0
                         /*xd->tile_ctx->*/ frame_context->switchable_restore_cdf,
4179
0
                         RESTORE_SWITCHABLE_TYPES);
4180
0
        switch (unit_rtype) {
4181
0
        case RESTORE_WIENER:
4182
0
            write_wiener_filter(wiener_win, &rui->wiener_info, wiener_info, w);
4183
            //SVT_LOG("POC:%i plane:%i v:%i %i %i  h:%i %i %i\n", piCSetPtr->picture_number, plane, rui->wiener_info.vfilter[0], rui->wiener_info.vfilter[1], rui->wiener_info.vfilter[2], rui->wiener_info.hfilter[0], rui->wiener_info.hfilter[1], rui->wiener_info.hfilter[2]);
4184
0
            break;
4185
0
        case RESTORE_SGRPROJ:
4186
0
            write_sgrproj_filter(&rui->sgrproj_info, sgrproj_info, w);
4187
            //SVT_LOG("POC:%i plane:%i ep:%i xqd_0:%i  xqd_1:%i\n", piCSetPtr->picture_number, plane, rui->sgrproj_info.ep, rui->sgrproj_info.xqd[0], rui->sgrproj_info.xqd[1]);
4188
0
            break;
4189
0
        default:
4190
0
            assert(unit_rtype == RESTORE_NONE); // SVT_LOG("POC:%i plane:%i OFF\n", piCSetPtr->picture_number, plane);
4191
0
            break;
4192
0
        }
4193
0
    } else if (frame_rtype == RESTORE_WIENER) {
4194
0
        aom_write_symbol(w,
4195
0
                         unit_rtype != RESTORE_NONE,
4196
0
                         /*xd->tile_ctx->*/ frame_context->wiener_restore_cdf,
4197
0
                         2);
4198
0
        if (unit_rtype != RESTORE_NONE) {
4199
0
            write_wiener_filter(wiener_win, &rui->wiener_info, wiener_info, w);
4200
            //SVT_LOG("POC:%i plane:%i v:%i %i %i  h:%i %i %i\n", piCSetPtr->picture_number, plane, rui->wiener_info.vfilter[0], rui->wiener_info.vfilter[1], rui->wiener_info.vfilter[2], rui->wiener_info.hfilter[0], rui->wiener_info.hfilter[1], rui->wiener_info.hfilter[2]);
4201
0
        }
4202
        //else
4203
        //SVT_LOG("POC:%i plane:%i OFF\n", piCSetPtr->picture_number, plane);
4204
0
    } else if (frame_rtype == RESTORE_SGRPROJ) {
4205
0
        aom_write_symbol(w,
4206
0
                         unit_rtype != RESTORE_NONE,
4207
0
                         /*xd->tile_ctx->*/ frame_context->sgrproj_restore_cdf,
4208
0
                         2);
4209
0
        if (unit_rtype != RESTORE_NONE) {
4210
0
            write_sgrproj_filter(&rui->sgrproj_info, sgrproj_info, w);
4211
            //SVT_LOG("POC:%i plane:%i ep:%i xqd_0:%i  xqd_1:%i\n", piCSetPtr->picture_number, plane, rui->sgrproj_info.ep, rui->sgrproj_info.xqd[0], rui->sgrproj_info.xqd[1]);
4212
0
        }
4213
        //else
4214
        //    SVT_LOG("POC:%i plane:%i OFF\n", piCSetPtr->picture_number, plane);
4215
0
    }
4216
0
}
4217
4218
static void ec_update_neighbors(PictureControlSet* pcs, EntropyCodingContext* ec_ctx, uint32_t blk_org_x,
4219
146k
                                uint32_t blk_org_y, uint16_t tile_idx, BlockSize bsize) {
4220
146k
    NeighborArrayUnit* partition_context_na        = pcs->partition_context_na[tile_idx];
4221
146k
    NeighborArrayUnit* luma_dc_sign_level_coeff_na = pcs->luma_dc_sign_level_coeff_na[tile_idx];
4222
146k
    NeighborArrayUnit* cr_dc_sign_level_coeff_na   = pcs->cr_dc_sign_level_coeff_na[tile_idx];
4223
146k
    NeighborArrayUnit* cb_dc_sign_level_coeff_na   = pcs->cb_dc_sign_level_coeff_na[tile_idx];
4224
146k
    MbModeInfo*        mbmi                        = get_mbmi(pcs, blk_org_x, blk_org_y);
4225
146k
    uint8_t            skip_coeff                  = mbmi->block_mi.skip;
4226
146k
    const int          bwidth                      = block_size_wide[bsize];
4227
146k
    const int          bheight                     = block_size_high[bsize];
4228
146k
    const bool         has_uv                      = is_chroma_reference(blk_org_y >> 2, blk_org_x >> 2, bsize, 1, 1);
4229
4230
    // Update the Leaf Depth Neighbor Array
4231
146k
    svt_aom_neighbor_array_unit_mode_write_pu(partition_context_na,
4232
146k
                                              (uint8_t*)&partition_context_lookup[bsize].above,
4233
146k
                                              blk_org_x,
4234
146k
                                              blk_org_y,
4235
146k
                                              bwidth,
4236
146k
                                              bheight,
4237
146k
                                              NEIGHBOR_ARRAY_UNIT_TOP_MASK);
4238
146k
    svt_aom_neighbor_array_unit_mode_write_pu(partition_context_na,
4239
146k
                                              (uint8_t*)&partition_context_lookup[bsize].left,
4240
146k
                                              blk_org_x,
4241
146k
                                              blk_org_y,
4242
146k
                                              bwidth,
4243
146k
                                              bheight,
4244
146k
                                              NEIGHBOR_ARRAY_UNIT_LEFT_MASK);
4245
146k
    if (skip_coeff) {
4246
140k
        uint8_t dc_sign_level_coeff = 0;
4247
4248
140k
        svt_aom_neighbor_array_unit_mode_write_pu(luma_dc_sign_level_coeff_na,
4249
140k
                                                  (uint8_t*)&dc_sign_level_coeff,
4250
140k
                                                  blk_org_x,
4251
140k
                                                  blk_org_y,
4252
140k
                                                  bwidth,
4253
140k
                                                  bheight,
4254
140k
                                                  NEIGHBOR_ARRAY_UNIT_TOP_AND_LEFT_ONLY_MASK);
4255
4256
140k
        if (has_uv) {
4257
140k
            const BlockSize bsize_uv   = get_plane_block_size(bsize, 1, 1);
4258
140k
            const int       bwidth_uv  = block_size_wide[bsize_uv];
4259
140k
            const int       bheight_uv = block_size_high[bsize_uv];
4260
140k
            svt_aom_neighbor_array_unit_mode_write_pu(cb_dc_sign_level_coeff_na,
4261
140k
                                                      &dc_sign_level_coeff,
4262
140k
                                                      ((blk_org_x >> 3) << 3) >> 1,
4263
140k
                                                      ((blk_org_y >> 3) << 3) >> 1,
4264
140k
                                                      bwidth_uv,
4265
140k
                                                      bheight_uv,
4266
140k
                                                      NEIGHBOR_ARRAY_UNIT_TOP_AND_LEFT_ONLY_MASK);
4267
140k
            svt_aom_neighbor_array_unit_mode_write_pu(cr_dc_sign_level_coeff_na,
4268
140k
                                                      &dc_sign_level_coeff,
4269
140k
                                                      ((blk_org_x >> 3) << 3) >> 1,
4270
140k
                                                      ((blk_org_y >> 3) << 3) >> 1,
4271
140k
                                                      bwidth_uv,
4272
140k
                                                      bheight_uv,
4273
140k
                                                      NEIGHBOR_ARRAY_UNIT_TOP_AND_LEFT_ONLY_MASK);
4274
140k
            ec_ctx->coded_area_sb_uv += bwidth_uv * bheight_uv;
4275
140k
        }
4276
140k
        ec_ctx->coded_area_sb += bwidth * bheight;
4277
140k
    }
4278
146k
}
4279
4280
437k
int svt_aom_allow_palette(int allow_screen_content_tools, BlockSize bsize) {
4281
437k
    return allow_screen_content_tools && block_size_wide[bsize] <= 64 && block_size_high[bsize] <= 64 &&
4282
0
        bsize >= BLOCK_8X8;
4283
437k
}
4284
4285
0
int svt_aom_get_palette_bsize_ctx(BlockSize bsize) {
4286
0
    return eb_num_pels_log2_lookup[bsize] - eb_num_pels_log2_lookup[BLOCK_8X8];
4287
0
}
4288
4289
void svt_av1_tokenize_color_map(FRAME_CONTEXT* frame_context, EcBlkStruct* blk_ptr, int plane, TOKENEXTRA** t,
4290
                                BlockSize bsize, TxSize tx_size, COLOR_MAP_TYPE type, int allow_update_cdf);
4291
void svt_aom_get_block_dimensions(BlockSize bsize, int plane, const MacroBlockD* xd, int* width, int* height,
4292
                                  int* rows_within_bounds, int* cols_within_bounds);
4293
int  svt_get_palette_cache_y(const MacroBlockD* const xd, uint16_t* cache);
4294
int  svt_av1_index_color_cache(const uint16_t* color_cache, int n_cache, const uint16_t* colors, int n_colors,
4295
                               uint8_t* cache_color_found, int* out_cache_colors);
4296
4297
0
int svt_aom_get_palette_mode_ctx(const MacroBlockD* xd) {
4298
0
    const MbModeInfo* const above_mi = xd->above_mbmi;
4299
0
    const MbModeInfo* const left_mi  = xd->left_mbmi;
4300
0
    int                     ctx      = 0;
4301
0
    if (above_mi) {
4302
0
        ctx += (above_mi->palette_mode_info.palette_size > 0);
4303
0
    }
4304
0
    if (left_mi) {
4305
0
        ctx += (left_mi->palette_mode_info.palette_size > 0);
4306
0
    }
4307
0
    return ctx;
4308
0
}
4309
4310
// Transmit color values with delta encoding. Write the first value as
4311
// literal, and the deltas between each value and the previous one. "min_val" is
4312
// the smallest possible value of the deltas.
4313
static AOM_INLINE void delta_encode_palette_colors(const int* colors, int num, int bit_depth, int min_val,
4314
0
                                                   AomWriter* w) {
4315
0
    if (num <= 0) {
4316
0
        return;
4317
0
    }
4318
0
    assert(colors[0] < (1 << bit_depth));
4319
0
    aom_write_literal(w, colors[0], bit_depth);
4320
0
    if (num == 1) {
4321
0
        return;
4322
0
    }
4323
0
    int max_delta = 0;
4324
0
    int deltas[PALETTE_MAX_SIZE];
4325
0
    memset(deltas, 0, sizeof(deltas));
4326
0
    for (int i = 1; i < num; ++i) {
4327
0
        assert(colors[i] < (1 << bit_depth));
4328
0
        const int delta = colors[i] - colors[i - 1];
4329
0
        deltas[i - 1]   = delta;
4330
0
        assert(delta >= min_val);
4331
0
        if (delta > max_delta) {
4332
0
            max_delta = delta;
4333
0
        }
4334
0
    }
4335
0
    const int min_bits = bit_depth - 3;
4336
0
    int       bits     = AOMMAX(av1_ceil_log2(max_delta + 1 - min_val), min_bits);
4337
0
    assert(bits <= bit_depth);
4338
0
    int range = (1 << bit_depth) - colors[0] - min_val;
4339
0
    aom_write_literal(w, bits - min_bits, 2);
4340
0
    for (int i = 0; i < num - 1; ++i) {
4341
0
        aom_write_literal(w, deltas[i] - min_val, bits);
4342
0
        range -= deltas[i];
4343
0
        bits = AOMMIN(bits, av1_ceil_log2(range));
4344
0
    }
4345
0
}
4346
4347
0
static INLINE int get_unsigned_bits(unsigned int num_values) {
4348
0
    return num_values > 0 ? get_msb(num_values) + 1 : 0;
4349
0
}
4350
4351
0
static INLINE void write_uniform(AomWriter* w, int n, int v) {
4352
0
    const int l = get_unsigned_bits(n);
4353
0
    const int m = (1 << l) - n;
4354
0
    if (l == 0) {
4355
0
        return;
4356
0
    }
4357
0
    if (v < m) {
4358
0
        aom_write_literal(w, v, l - 1);
4359
0
    } else {
4360
0
        aom_write_literal(w, m + ((v - m) >> 1), l - 1);
4361
0
        aom_write_literal(w, (v - m) & 1, 1);
4362
0
    }
4363
0
}
4364
4365
0
int svt_aom_write_uniform_cost(int n, int v) {
4366
0
    const int l = get_unsigned_bits(n);
4367
0
    const int m = (1 << l) - n;
4368
0
    if (l == 0) {
4369
0
        return 0;
4370
0
    }
4371
0
    if (v < m) {
4372
0
        return av1_cost_literal(l - 1);
4373
0
    } else {
4374
0
        return av1_cost_literal(l);
4375
0
    }
4376
0
}
4377
4378
// Transmit luma palette color values. First signal if each color in the color
4379
// cache is used. Those colors that are not in the cache are transmitted with
4380
// delta encoding.
4381
static AOM_INLINE void write_palette_colors_y(const MacroBlockD* const xd, const PaletteModeInfo* const pmi,
4382
0
                                              int bit_depth, AomWriter* w, const int palette_size) {
4383
0
    const int n = palette_size;
4384
0
    uint16_t  color_cache[2 * PALETTE_MAX_SIZE];
4385
0
    const int n_cache = svt_get_palette_cache_y(xd, color_cache);
4386
0
    int       out_cache_colors[PALETTE_MAX_SIZE];
4387
0
    uint8_t   cache_color_found[2 * PALETTE_MAX_SIZE];
4388
0
    const int n_out_cache = svt_av1_index_color_cache(
4389
0
        color_cache, n_cache, pmi->palette_colors, n, cache_color_found, out_cache_colors);
4390
0
    int n_in_cache = 0;
4391
0
    for (int i = 0; i < n_cache && n_in_cache < n; ++i) {
4392
0
        const int found = cache_color_found[i];
4393
0
        aom_write_bit(w, found);
4394
0
        n_in_cache += found;
4395
0
    }
4396
0
    assert(n_in_cache + n_out_cache == n);
4397
0
    delta_encode_palette_colors(out_cache_colors, n_out_cache, bit_depth, 1, w);
4398
0
}
4399
4400
0
static inline void pack_map_tokens(AomWriter* w, const TOKENEXTRA** tp, int n, int num) {
4401
0
    const TOKENEXTRA* p = *tp;
4402
0
    write_uniform(w, n, p->token); // The first color index.
4403
0
    ++p;
4404
0
    --num;
4405
0
    for (int i = 0; i < num; ++i) {
4406
0
        aom_write_symbol(w, p->token, p->color_map_cdf, n);
4407
0
        ++p;
4408
0
    }
4409
0
    *tp = p;
4410
0
}
4411
4412
static void write_palette_mode_info(PictureParentControlSet* ppcs, FRAME_CONTEXT* ec_ctx, MbModeInfo* mbmi,
4413
0
                                    EcBlkStruct* blk_ptr, BlockSize bsize, int mi_row, int mi_col, AomWriter* w) {
4414
0
    const uint32_t intra_luma_mode   = mbmi->block_mi.mode;
4415
0
    uint32_t       intra_chroma_mode = mbmi->block_mi.uv_mode;
4416
4417
0
    const PaletteModeInfo* const pmi       = &blk_ptr->palette_info->pmi;
4418
0
    const int                    bsize_ctx = svt_aom_get_palette_bsize_ctx(bsize);
4419
0
    assert(bsize_ctx >= 0);
4420
0
    if (intra_luma_mode == DC_PRED) {
4421
0
        const int n                  = blk_ptr->palette_size[0];
4422
0
        const int palette_y_mode_ctx = svt_aom_get_palette_mode_ctx(blk_ptr->av1xd);
4423
0
        aom_write_symbol(w, n > 0, ec_ctx->palette_y_mode_cdf[bsize_ctx][palette_y_mode_ctx], 2);
4424
0
        if (n > 0) {
4425
0
            aom_write_symbol(w, n - PALETTE_MIN_SIZE, ec_ctx->palette_y_size_cdf[bsize_ctx], PALETTE_SIZES);
4426
0
            write_palette_colors_y(blk_ptr->av1xd, pmi, ppcs->scs->static_config.encoder_bit_depth, w, n);
4427
0
        }
4428
0
    }
4429
4430
0
    const int uv_dc_pred = intra_chroma_mode == UV_DC_PRED && is_chroma_reference(mi_row, mi_col, bsize, 1, 1);
4431
0
    if (uv_dc_pred) {
4432
0
        assert(blk_ptr->palette_size[1] == 0); //remove when chroma is on
4433
0
        const int palette_uv_mode_ctx = (blk_ptr->palette_size[0] > 0);
4434
0
        aom_write_symbol(w, 0, ec_ctx->palette_uv_mode_cdf[palette_uv_mode_ctx], 2);
4435
0
    }
4436
0
}
4437
4438
0
void svt_av1_encode_dv(AomWriter* w, const Mv* mv, const Mv* ref, NmvContext* mvctx) {
4439
    // DV and ref DV should not have sub-pel.
4440
0
    assert((mv->x & 7) == 0);
4441
0
    assert((mv->y & 7) == 0);
4442
0
    assert((ref->x & 7) == 0);
4443
0
    assert((ref->y & 7) == 0);
4444
    // The y-component (row component) of the MV is coded first
4445
0
    const Mv          diff = {{mv->x - ref->x, mv->y - ref->y}};
4446
0
    const MvJointType j    = svt_av1_get_mv_joint(&diff);
4447
4448
0
    aom_write_symbol(w, j, mvctx->joints_cdf, MV_JOINTS);
4449
0
    if (mv_joint_vertical(j)) {
4450
0
        encode_mv_component(w, diff.y, &mvctx->comps[0], MV_SUBPEL_NONE);
4451
0
    }
4452
4453
0
    if (mv_joint_horizontal(j)) {
4454
0
        encode_mv_component(w, diff.x, &mvctx->comps[1], MV_SUBPEL_NONE);
4455
0
    }
4456
0
}
4457
4458
437k
int svt_aom_allow_intrabc(const FrameHeader* frm_hdr, SliceType slice_type) {
4459
437k
    return (slice_type == I_SLICE && frm_hdr->allow_screen_content_tools && frm_hdr->allow_intrabc);
4460
437k
}
4461
4462
0
static void write_intrabc_info(FRAME_CONTEXT* ec_ctx, MbModeInfo* mbmi, EcBlkStruct* blk_ptr, AomWriter* w) {
4463
0
    int use_intrabc = mbmi->block_mi.use_intrabc;
4464
0
    aom_write_symbol(w, use_intrabc, ec_ctx->intrabc_cdf, 2);
4465
0
    if (use_intrabc) {
4466
        //assert(mbmi->mode == DC_PRED);
4467
        //assert(mbmi->uv_mode == UV_DC_PRED);
4468
        //assert(mbmi->motion_mode == SIMPLE_TRANSLATION);
4469
0
        Mv dv_ref = blk_ptr->predmv[0];
4470
0
        Mv mv     = mbmi->block_mi.mv[INTRA_FRAME];
4471
0
        svt_av1_encode_dv(w, &mv, &dv_ref, &ec_ctx->ndvc);
4472
0
    }
4473
0
}
4474
4475
154k
static INLINE int block_signals_txsize(BlockSize bsize) {
4476
154k
    return bsize > BLOCK_4X4;
4477
154k
}
4478
4479
0
static INLINE int get_vartx_max_txsize(/*const MbModeInfo *xd,*/ BlockSize bsize, int plane) {
4480
    /* if (xd->lossless[xd->mi[0]->segment_id]) return TX_4X4;*/
4481
0
    const TxSize max_txsize = blocksize_to_txsize[bsize];
4482
0
    if (plane == 0) {
4483
0
        return max_txsize; // luma
4484
0
    }
4485
0
    return av1_get_adjusted_tx_size(max_txsize); // chroma
4486
0
}
4487
4488
0
static INLINE int max_block_wide(const MacroBlockD* xd, BlockSize bsize, int plane) {
4489
0
    int max_blocks_wide = block_size_wide[bsize];
4490
4491
0
    if (xd->mb_to_right_edge < 0) {
4492
0
        max_blocks_wide += gcc_right_shift(xd->mb_to_right_edge, 3 + !!plane);
4493
0
    }
4494
4495
    // Scale the width in the transform block unit.
4496
0
    return max_blocks_wide >> tx_size_wide_log2[0];
4497
0
}
4498
4499
0
static INLINE int max_block_high(const MacroBlockD* xd, BlockSize bsize, int plane) {
4500
0
    int max_blocks_high = block_size_high[bsize];
4501
4502
0
    if (xd->mb_to_bottom_edge < 0) {
4503
0
        max_blocks_high += gcc_right_shift(xd->mb_to_bottom_edge, 3 + !!plane);
4504
0
    }
4505
4506
    // Scale the height in the transform block unit.
4507
0
    return max_blocks_high >> tx_size_high_log2[0];
4508
0
}
4509
4510
static INLINE void txfm_partition_update(TXFM_CONTEXT* above_ctx, TXFM_CONTEXT* left_ctx, TxSize tx_size,
4511
0
                                         TxSize txb_size) {
4512
0
    BlockSize bsize = txsize_to_bsize[txb_size];
4513
0
    assert(bsize < BLOCK_SIZES_ALL);
4514
0
    int     bh  = mi_size_high[bsize];
4515
0
    int     bw  = mi_size_wide[bsize];
4516
0
    uint8_t txw = tx_size_wide[tx_size];
4517
0
    uint8_t txh = tx_size_high[tx_size];
4518
0
    int     i;
4519
0
    for (i = 0; i < bh; ++i) {
4520
0
        left_ctx[i] = txh;
4521
0
    }
4522
0
    for (i = 0; i < bw; ++i) {
4523
0
        above_ctx[i] = txw;
4524
0
    }
4525
0
}
4526
4527
0
static INLINE TxSize get_sqr_tx_size(int tx_dim) {
4528
0
    switch (tx_dim) {
4529
0
    case 128:
4530
0
    case 64:
4531
0
        return TX_64X64;
4532
0
        break;
4533
0
    case 32:
4534
0
        return TX_32X32;
4535
0
        break;
4536
0
    case 16:
4537
0
        return TX_16X16;
4538
0
        break;
4539
0
    case 8:
4540
0
        return TX_8X8;
4541
0
        break;
4542
0
    default:
4543
0
        return TX_4X4;
4544
0
    }
4545
0
}
4546
4547
static INLINE int txfm_partition_context(TXFM_CONTEXT* above_ctx, TXFM_CONTEXT* left_ctx, BlockSize bsize,
4548
0
                                         TxSize tx_size) {
4549
0
    const uint8_t txw      = tx_size_wide[tx_size];
4550
0
    const uint8_t txh      = tx_size_high[tx_size];
4551
0
    const int     above    = *above_ctx < txw;
4552
0
    const int     left     = *left_ctx < txh;
4553
0
    int           category = TXFM_PARTITION_CONTEXTS;
4554
4555
    // dummy return, not used by others.
4556
0
    if (tx_size == TX_4X4) {
4557
0
        return 0;
4558
0
    }
4559
4560
0
    TxSize max_tx_size = get_sqr_tx_size(AOMMAX(block_size_wide[bsize], block_size_high[bsize]));
4561
4562
0
    if (max_tx_size >= TX_8X8) {
4563
0
        category = (txsize_sqr_up_map[tx_size] != max_tx_size && max_tx_size > TX_8X8) +
4564
0
            (TX_SIZES - 1 - max_tx_size) * 2;
4565
0
    }
4566
0
    assert(category != TXFM_PARTITION_CONTEXTS);
4567
0
    return category * 3 + above + left;
4568
0
}
4569
4570
static void write_tx_size_vartx(MacroBlockD* xd, const MbModeInfo* mbmi, TxSize tx_size, int depth, int blk_row,
4571
0
                                int blk_col, FRAME_CONTEXT* ec_ctx, AomWriter* w) {
4572
0
    const int max_blocks_high = max_block_high(xd, mbmi->bsize, 0);
4573
0
    const int max_blocks_wide = max_block_wide(xd, mbmi->bsize, 0);
4574
4575
0
    if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) {
4576
0
        return;
4577
0
    }
4578
4579
0
    if (depth == MAX_VARTX_DEPTH) {
4580
0
        txfm_partition_update(xd->above_txfm_context + blk_col, xd->left_txfm_context + blk_row, tx_size, tx_size);
4581
0
        return;
4582
0
    }
4583
4584
0
    const int ctx = txfm_partition_context(
4585
0
        xd->above_txfm_context + blk_col, xd->left_txfm_context + blk_row, mbmi->bsize, tx_size);
4586
0
    const int write_txfm_partition = (tx_size == tx_depth_to_tx_size[mbmi->block_mi.tx_depth][mbmi->bsize]);
4587
4588
0
    if (write_txfm_partition) {
4589
0
        aom_write_symbol(w, 0, ec_ctx->txfm_partition_cdf[ctx], 2);
4590
4591
0
        txfm_partition_update(xd->above_txfm_context + blk_col, xd->left_txfm_context + blk_row, tx_size, tx_size);
4592
0
    } else {
4593
0
        ASSERT(tx_size < TX_SIZES_ALL);
4594
0
        const TxSize sub_txs = eb_sub_tx_size_map[tx_size];
4595
0
        const int    bsw     = eb_tx_size_wide_unit[sub_txs];
4596
0
        const int    bsh     = eb_tx_size_high_unit[sub_txs];
4597
4598
0
        aom_write_symbol(w, 1, ec_ctx->txfm_partition_cdf[ctx], 2);
4599
4600
0
        if (sub_txs == TX_4X4) {
4601
0
            txfm_partition_update(xd->above_txfm_context + blk_col, xd->left_txfm_context + blk_row, sub_txs, tx_size);
4602
0
            return;
4603
0
        }
4604
4605
0
        assert(bsw > 0 && bsh > 0);
4606
0
        for (int row = 0; row < eb_tx_size_high_unit[tx_size]; row += bsh) {
4607
0
            for (int col = 0; col < eb_tx_size_wide_unit[tx_size]; col += bsw) {
4608
0
                int offsetr = blk_row + row;
4609
0
                int offsetc = blk_col + col;
4610
0
                write_tx_size_vartx(xd, mbmi, sub_txs, depth + 1, offsetr, offsetc, ec_ctx, w);
4611
0
            }
4612
0
        }
4613
0
    }
4614
0
}
4615
4616
293k
static INLINE void set_txfm_ctx(TXFM_CONTEXT* txfm_ctx, uint8_t txs, int len) {
4617
293k
    int i;
4618
978k
    for (i = 0; i < len; ++i) {
4619
685k
        txfm_ctx[i] = txs;
4620
685k
    }
4621
293k
}
4622
4623
146k
static INLINE void set_txfm_ctxs(TxSize tx_size, int n8_w, int n8_h, int skip, const MacroBlockD* xd) {
4624
146k
    uint8_t bw = tx_size_wide[tx_size];
4625
146k
    uint8_t bh = tx_size_high[tx_size];
4626
4627
146k
    if (skip) {
4628
0
        bw = n8_w * MI_SIZE;
4629
0
        bh = n8_h * MI_SIZE;
4630
0
    }
4631
4632
146k
    set_txfm_ctx(xd->above_txfm_context, bw, n8_w);
4633
146k
    set_txfm_ctx(xd->left_txfm_context, bh, n8_h);
4634
146k
}
4635
4636
8.21k
static INLINE int tx_size_to_depth(TxSize tx_size, BlockSize bsize) {
4637
8.21k
    TxSize ctx_size = blocksize_to_txsize[bsize];
4638
8.21k
    int    depth    = 0;
4639
8.21k
    while (tx_size != ctx_size) {
4640
0
        depth++;
4641
0
        ctx_size = eb_sub_tx_size_map[ctx_size];
4642
0
        assert(depth <= MAX_TX_DEPTH);
4643
0
    }
4644
8.21k
    return depth;
4645
8.21k
}
4646
4647
// Returns a context number for the given MB prediction signal
4648
// The mode info data structure has a one element border above and to the
4649
// left of the entries corresponding to real blocks.
4650
// The prediction flags in these dummy entries are initialized to 0.
4651
8.21k
static INLINE int get_tx_size_context(const MacroBlockD* xd) {
4652
8.21k
    const MbModeInfo*       mbmi        = xd->mi[0];
4653
8.21k
    const MbModeInfo* const above_mbmi  = xd->above_mbmi;
4654
8.21k
    const MbModeInfo* const left_mbmi   = xd->left_mbmi;
4655
8.21k
    const TxSize            max_tx_size = blocksize_to_txsize[mbmi->bsize];
4656
8.21k
    const int               max_tx_wide = tx_size_wide[max_tx_size];
4657
8.21k
    const int               max_tx_high = tx_size_high[max_tx_size];
4658
8.21k
    const int               has_above   = xd->up_available;
4659
8.21k
    const int               has_left    = xd->left_available;
4660
4661
8.21k
    int above = xd->above_txfm_context[0] >= max_tx_wide;
4662
8.21k
    int left  = xd->left_txfm_context[0] >= max_tx_high;
4663
4664
8.21k
    if (has_above) {
4665
2.65k
        if (is_inter_block(&above_mbmi->block_mi)) {
4666
0
            above = block_size_wide[above_mbmi->bsize] >= max_tx_wide;
4667
0
        }
4668
2.65k
    }
4669
4670
8.21k
    if (has_left) {
4671
2.48k
        if (is_inter_block(&left_mbmi->block_mi)) {
4672
0
            left = block_size_high[left_mbmi->bsize] >= max_tx_high;
4673
0
        }
4674
2.48k
    }
4675
4676
8.21k
    if (has_above && has_left) {
4677
206
        return (above + left);
4678
8.01k
    } else if (has_above) {
4679
2.45k
        return above;
4680
5.55k
    } else if (has_left) {
4681
2.27k
        return left;
4682
3.28k
    } else {
4683
3.28k
        return 0;
4684
3.28k
    }
4685
8.21k
}
4686
4687
8.21k
static void write_selected_tx_size(const MacroBlockD* xd, FRAME_CONTEXT* ec_ctx, AomWriter* w, TxSize tx_size) {
4688
8.21k
    const MbModeInfo* const mbmi  = xd->mi[0];
4689
8.21k
    const BlockSize         bsize = mbmi->bsize;
4690
4691
8.21k
    if (block_signals_txsize(bsize)) {
4692
8.21k
        const int tx_size_ctx = get_tx_size_context(xd);
4693
8.21k
        assert(bsize < BLOCK_SIZES_ALL);
4694
8.21k
        const int     depth       = tx_size_to_depth(tx_size, bsize);
4695
8.21k
        const int     max_depths  = bsize_to_max_depth(bsize);
4696
8.21k
        const int32_t tx_size_cat = bsize_to_tx_size_cat(bsize);
4697
4698
8.21k
        assert(depth >= 0 && depth <= max_depths);
4699
8.21k
        assert(!is_inter_block(&mbmi->block_mi));
4700
8.21k
        assert(IMPLIES(is_rect_tx(tx_size), is_rect_tx_allowed(/*xd,*/ mbmi)));
4701
4702
8.21k
        aom_write_symbol(w, depth, ec_ctx->tx_size_cdf[tx_size_cat][tx_size_ctx], max_depths + 1);
4703
8.21k
    }
4704
8.21k
}
4705
4706
static EbErrorType av1_code_tx_size(PictureControlSet* pcs, int segment_id, FRAME_CONTEXT* ec_ctx, AomWriter* w,
4707
                                    MacroBlockD* xd, const MbModeInfo* mbmi, TxSize tx_size, TxMode tx_mode,
4708
146k
                                    BlockSize bsize, uint8_t skip) {
4709
146k
    EbErrorType return_error = EB_ErrorNone;
4710
146k
    int         is_inter_tx  = is_inter_block(&mbmi->block_mi);
4711
    //int skip = mbmi->skip;
4712
    //int segment_id = 0;// mbmi->segment_id;
4713
146k
    if (tx_mode == TX_MODE_SELECT && block_signals_txsize(bsize) && !(is_inter_tx && skip) &&
4714
146k
        !svt_av1_is_lossless_segment(pcs, segment_id)) {
4715
8.21k
        if (is_inter_tx) { // This implies skip flag is 0.
4716
0
            const TxSize max_tx_size = get_vartx_max_txsize(/*xd,*/ bsize, 0);
4717
0
            const int    txbh        = eb_tx_size_high_unit[max_tx_size];
4718
0
            const int    txbw        = eb_tx_size_wide_unit[max_tx_size];
4719
0
            const int    width       = block_size_wide[bsize] >> tx_size_wide_log2[0];
4720
0
            const int    height      = block_size_high[bsize] >> tx_size_high_log2[0];
4721
0
            int          idx, idy;
4722
0
            for (idy = 0; idy < height; idy += txbh) {
4723
0
                for (idx = 0; idx < width; idx += txbw) {
4724
0
                    write_tx_size_vartx(xd, mbmi, max_tx_size, 0, idy, idx, ec_ctx, w);
4725
0
                }
4726
0
            }
4727
8.21k
        } else {
4728
8.21k
            write_selected_tx_size(xd, ec_ctx, w, tx_size);
4729
8.21k
            set_txfm_ctxs(tx_size, xd->n8_w, xd->n8_h, 0, xd);
4730
8.21k
        }
4731
138k
    } else {
4732
138k
        set_txfm_ctxs(tx_size, xd->n8_w, xd->n8_h, skip && is_inter_tx, xd);
4733
138k
    }
4734
4735
146k
    return return_error;
4736
146k
}
4737
4738
void set_mi_row_col(PictureControlSet* pcs, MacroBlockD* xd, TileInfo* tile, int mi_row, int bh, int mi_col, int bw,
4739
146k
                    uint32_t mi_stride, int mi_rows, int mi_cols) {
4740
146k
    xd->mb_to_top_edge    = -((mi_row * MI_SIZE) * 8);
4741
146k
    xd->mb_to_bottom_edge = ((mi_rows - bh - mi_row) * MI_SIZE) * 8;
4742
146k
    xd->mb_to_left_edge   = -((mi_col * MI_SIZE) * 8);
4743
146k
    xd->mb_to_right_edge  = ((mi_cols - bw - mi_col) * MI_SIZE) * 8;
4744
4745
146k
    xd->mi_stride = mi_stride;
4746
4747
    // Are edges available for intra prediction?
4748
146k
    xd->up_available     = (mi_row > tile->mi_row_start);
4749
146k
    xd->left_available   = (mi_col > tile->mi_col_start);
4750
146k
    const int32_t offset = mi_row * mi_stride + mi_col;
4751
146k
    xd->mi               = pcs->mi_grid_base + offset;
4752
4753
146k
    if (xd->up_available) {
4754
122k
        xd->above_mbmi = xd->mi[-xd->mi_stride];
4755
122k
    } else {
4756
24.1k
        xd->above_mbmi = NULL;
4757
24.1k
    }
4758
4759
146k
    if (xd->left_available) {
4760
123k
        xd->left_mbmi = xd->mi[-1];
4761
123k
    } else {
4762
23.4k
        xd->left_mbmi = NULL;
4763
23.4k
    }
4764
4765
146k
    xd->n8_h        = bh;
4766
146k
    xd->n8_w        = bw;
4767
146k
    xd->is_sec_rect = 0;
4768
146k
    if (xd->n8_w < xd->n8_h) {
4769
        // Only mark is_sec_rect as 1 for the last block.
4770
        // For PARTITION_VERT_4, it would be (0, 0, 0, 1);
4771
        // For other partitions, it would be (0, 1).
4772
0
        if (!((mi_col + xd->n8_w) & (xd->n8_h - 1))) {
4773
0
            xd->is_sec_rect = 1;
4774
0
        }
4775
0
    }
4776
4777
146k
    if (xd->n8_w > xd->n8_h) {
4778
0
        if (mi_row & (xd->n8_w - 1)) {
4779
0
            xd->is_sec_rect = 1;
4780
0
        }
4781
0
    }
4782
146k
}
4783
4784
static INLINE int svt_aom_get_segment_id(Av1Common* cm, const uint8_t* segment_ids, BlockSize bsize, int mi_row,
4785
0
                                         int mi_col) {
4786
0
    const int mi_offset = mi_row * cm->mi_cols + mi_col;
4787
0
    const int bw        = mi_size_wide[bsize];
4788
0
    const int bh        = mi_size_high[bsize];
4789
0
    const int xmis      = AOMMIN(cm->mi_cols - mi_col, bw);
4790
0
    const int ymis      = AOMMIN(cm->mi_rows - mi_row, bh);
4791
0
    int       x, y, segment_id = MAX_SEGMENTS;
4792
4793
0
    for (y = 0; y < ymis; ++y) {
4794
0
        for (x = 0; x < xmis; ++x) {
4795
0
            segment_id = AOMMIN(segment_id, segment_ids[mi_offset + y * cm->mi_cols + x]);
4796
0
        }
4797
0
    }
4798
4799
0
    assert(segment_id >= 0 && segment_id < MAX_SEGMENTS);
4800
0
    return segment_id;
4801
0
}
4802
4803
static void code_tx_size(PictureControlSet* pcs, uint32_t blk_org_x, uint32_t blk_org_y, EcBlkStruct* blk_ptr,
4804
                         const BlockSize bsize, NeighborArrayUnit* txfm_context_array, FRAME_CONTEXT* ec_ctx,
4805
146k
                         AomWriter* w, uint8_t skip) {
4806
146k
    TxMode       tx_mode = pcs->ppcs->frm_hdr.tx_mode;
4807
146k
    Av1Common*   cm      = pcs->ppcs->av1_cm;
4808
146k
    MacroBlockD* xd      = blk_ptr->av1xd;
4809
    // xd fields (mi, up_available, left_available, etc.) are already set by
4810
    // the caller (write_modes_b) via set_mi_row_col — no need to redo.
4811
4812
146k
    const MbModeInfo* const mbmi              = xd->mi[0];
4813
146k
    xd->above_txfm_context                    = (TXFM_CONTEXT*)svt_aom_na_top_ptr_pu(txfm_context_array, blk_org_x);
4814
146k
    xd->left_txfm_context                     = (TXFM_CONTEXT*)svt_aom_na_left_ptr_pu(txfm_context_array, blk_org_y);
4815
146k
    const TxSize             tx_size          = tx_depth_to_tx_size[mbmi->block_mi.tx_depth][bsize];
4816
146k
    FrameHeader*             frm_hdr          = &pcs->ppcs->frm_hdr;
4817
146k
    SegmentationNeighborMap* segmentation_map = pcs->segmentation_neighbor_map;
4818
146k
    int32_t                  mi_row           = blk_org_y >> MI_SIZE_LOG2;
4819
146k
    int32_t                  mi_col           = blk_org_x >> MI_SIZE_LOG2;
4820
146k
    av1_code_tx_size(pcs,
4821
146k
                     frm_hdr->segmentation_params.segmentation_enabled
4822
146k
                         ? svt_aom_get_segment_id(cm, segmentation_map->data, BLOCK_4X4, mi_row, mi_col)
4823
146k
                         : 0,
4824
146k
                     ec_ctx,
4825
146k
                     w,
4826
146k
                     xd,
4827
146k
                     mbmi,
4828
146k
                     tx_size,
4829
146k
                     tx_mode,
4830
146k
                     bsize,
4831
146k
                     skip);
4832
146k
}
4833
4834
int svt_av1_get_spatial_seg_prediction(PictureControlSet* pcs, MacroBlockD* xd, uint32_t blk_org_x, uint32_t blk_org_y,
4835
0
                                       int* cdf_index) {
4836
0
    int prev_ul = -1; // top left segment_id
4837
0
    int prev_l  = -1; // left segment_id
4838
0
    int prev_u  = -1; // top segment_id
4839
4840
0
    uint32_t                 mi_col           = blk_org_x >> MI_SIZE_LOG2;
4841
0
    uint32_t                 mi_row           = blk_org_y >> MI_SIZE_LOG2;
4842
0
    bool                     left_available   = xd->left_available;
4843
0
    bool                     up_available     = xd->up_available;
4844
0
    Av1Common*               cm               = pcs->ppcs->av1_cm;
4845
0
    SegmentationNeighborMap* segmentation_map = pcs->segmentation_neighbor_map;
4846
4847
    //    SVT_LOG("Left available = %d, Up Available = %d ", left_available, up_available);
4848
4849
0
    if ((up_available) && (left_available)) {
4850
0
        prev_ul = svt_aom_get_segment_id(cm, segmentation_map->data, BLOCK_4X4, mi_row - 1, mi_col - 1);
4851
0
    }
4852
4853
0
    if (up_available) {
4854
0
        prev_u = svt_aom_get_segment_id(cm, segmentation_map->data, BLOCK_4X4, mi_row - 1, mi_col - 0);
4855
0
    }
4856
4857
0
    if (left_available) {
4858
0
        prev_l = svt_aom_get_segment_id(cm, segmentation_map->data, BLOCK_4X4, mi_row - 0, mi_col - 1);
4859
0
    }
4860
4861
    // Pick CDF index based on number of matching/out-of-bounds segment IDs.
4862
0
    if (prev_ul < 0 || prev_u < 0 || prev_l < 0) { /* Edge case */
4863
0
        *cdf_index = 0;
4864
0
    } else if ((prev_ul == prev_u) && (prev_ul == prev_l)) {
4865
0
        *cdf_index = 2;
4866
0
    } else if ((prev_ul == prev_u) || (prev_ul == prev_l) || (prev_u == prev_l)) {
4867
0
        *cdf_index = 1;
4868
0
    } else {
4869
0
        *cdf_index = 0;
4870
0
    }
4871
4872
    // If 2 or more are identical returns that as predictor, otherwise prev_l.
4873
0
    if (prev_u == -1) { // edge case
4874
0
        return prev_l == -1 ? 0 : prev_l;
4875
0
    }
4876
0
    if (prev_l == -1) { // edge case
4877
0
        return prev_u;
4878
0
    }
4879
0
    return (prev_ul == prev_u) ? prev_u : prev_l;
4880
0
}
4881
4882
0
int svt_av1_neg_interleave(int x, int ref, int max) {
4883
0
    assert(x < max);
4884
0
    const int diff = x - ref;
4885
0
    if (!ref) {
4886
0
        return x;
4887
0
    }
4888
0
    if (ref >= (max - 1)) {
4889
0
        return -x + max - 1;
4890
0
    }
4891
0
    if (2 * ref < max) {
4892
0
        if (abs(diff) <= ref) {
4893
0
            return diff > 0 ? (diff << 1) - 1 : ((-diff) << 1);
4894
0
        }
4895
0
        return x;
4896
0
    } else {
4897
0
        if (abs(diff) < (max - ref)) {
4898
0
            return diff > 0 ? (diff << 1) - 1 : ((-diff) << 1);
4899
0
        }
4900
0
        return (max - x) - 1;
4901
0
    }
4902
0
}
4903
4904
void svt_av1_update_segmentation_map(PictureControlSet* pcs, BlockSize bsize, uint32_t blk_org_x, uint32_t blk_org_y,
4905
0
                                     uint8_t segment_id) {
4906
0
    Av1Common* cm          = pcs->ppcs->av1_cm;
4907
0
    uint8_t*   segment_ids = pcs->segmentation_neighbor_map->data;
4908
0
    uint32_t   mi_col      = blk_org_x >> MI_SIZE_LOG2;
4909
0
    uint32_t   mi_row      = blk_org_y >> MI_SIZE_LOG2;
4910
0
    const int  mi_offset   = mi_row * cm->mi_cols + mi_col;
4911
0
    const int  bw          = mi_size_wide[bsize];
4912
0
    const int  bh          = mi_size_high[bsize];
4913
0
    const int  xmis        = AOMMIN((int)(cm->mi_cols - mi_col), bw);
4914
0
    const int  ymis        = AOMMIN((int)(cm->mi_rows - mi_row), bh);
4915
0
    int        x, y;
4916
4917
0
    for (y = 0; y < ymis; ++y) {
4918
0
        for (x = 0; x < xmis; ++x) {
4919
0
            segment_ids[mi_offset + y * cm->mi_cols + x] = segment_id;
4920
0
        }
4921
0
    }
4922
0
}
4923
4924
void write_segment_id(PictureControlSet* pcs, FRAME_CONTEXT* frame_context, AomWriter* ecWriter, BlockSize bsize,
4925
0
                      uint32_t blk_org_x, uint32_t blk_org_y, EcBlkStruct* blk_ptr, bool skip_coeff) {
4926
0
    SegmentationParams* segmentation_params = &pcs->ppcs->frm_hdr.segmentation_params;
4927
0
    if (!segmentation_params->segmentation_enabled) {
4928
0
        return;
4929
0
    }
4930
0
    MbModeInfo* mbmi = get_mbmi(pcs, blk_org_x, blk_org_y);
4931
0
    int         cdf_num;
4932
0
    const int   spatial_pred = svt_av1_get_spatial_seg_prediction(pcs, blk_ptr->av1xd, blk_org_x, blk_org_y, &cdf_num);
4933
0
    if (skip_coeff) {
4934
0
        svt_av1_update_segmentation_map(pcs, bsize, blk_org_x, blk_org_y, spatial_pred);
4935
0
        mbmi->segment_id = spatial_pred;
4936
0
        return;
4937
0
    }
4938
0
    const int coded_id = svt_av1_neg_interleave(
4939
0
        mbmi->segment_id, spatial_pred, segmentation_params->last_active_seg_id + 1);
4940
0
    struct segmentation_probs* segp     = &frame_context->seg;
4941
0
    AomCdfProb*                pred_cdf = segp->spatial_pred_seg_cdf[cdf_num];
4942
0
    aom_write_symbol(ecWriter, coded_id, pred_cdf, MAX_SEGMENTS);
4943
0
    svt_av1_update_segmentation_map(pcs, bsize, blk_org_x, blk_org_y, mbmi->segment_id);
4944
0
}
4945
4946
static void write_inter_segment_id(PictureControlSet* pcs, FRAME_CONTEXT* frame_context, AomWriter* ecWriter,
4947
                                   const BlockSize bsize, uint32_t blk_org_x, uint32_t blk_org_y, EcBlkStruct* blk_ptr,
4948
0
                                   bool skip, int pre_skip) {
4949
0
    SegmentationParams* segmentation_params = &pcs->ppcs->frm_hdr.segmentation_params;
4950
0
    if (!segmentation_params->segmentation_enabled) {
4951
0
        return;
4952
0
    }
4953
4954
0
    if (segmentation_params->segmentation_update_map) {
4955
0
        if (pre_skip) {
4956
0
            if (!segmentation_params->seg_id_pre_skip) {
4957
0
                return;
4958
0
            }
4959
0
        } else {
4960
0
            if (segmentation_params->seg_id_pre_skip) {
4961
0
                return;
4962
0
            }
4963
0
            if (skip) {
4964
0
                write_segment_id(pcs, frame_context, ecWriter, bsize, blk_org_x, blk_org_y, blk_ptr, 1);
4965
0
                if (segmentation_params->segmentation_temporal_update) {
4966
0
                    SVT_ERROR("Temporal update is not supported yet! \n");
4967
0
                    assert(0);
4968
                    //                    blk_ptr->seg_id_predicted = 0;
4969
0
                }
4970
0
                return;
4971
0
            }
4972
0
        }
4973
4974
0
        if (segmentation_params->segmentation_temporal_update) {
4975
0
            SVT_ERROR("Temporal update is not supported yet! \n");
4976
0
            assert(0);
4977
4978
0
        } else {
4979
0
            write_segment_id(pcs, frame_context, ecWriter, bsize, blk_org_x, blk_org_y, blk_ptr, 0);
4980
0
        }
4981
0
    }
4982
0
}
4983
4984
0
int svt_aom_is_interintra_allowed(const MbModeInfo* mbmi) {
4985
0
    return svt_aom_is_interintra_allowed_bsize(mbmi->bsize) &&
4986
0
        svt_aom_is_interintra_allowed_mode(mbmi->block_mi.mode) &&
4987
0
        svt_aom_is_interintra_allowed_ref(mbmi->block_mi.ref_frame);
4988
0
}
4989
4990
int svt_aom_is_interintra_wedge_used(BlockSize bsize);
4991
4992
static EbErrorType write_modes_b(PictureControlSet* pcs, EntropyCodingContext* ec_ctx, EntropyCoder* ec,
4993
                                 SuperBlock* sb_ptr, EcBlkStruct* blk_ptr, uint16_t tile_idx,
4994
146k
                                 EbPictureBufferDesc* coeff_ptr, const int mi_row, const int mi_col) {
4995
146k
    EbErrorType         return_error  = EB_ErrorNone;
4996
146k
    FRAME_CONTEXT*      frame_context = ec->fc;
4997
146k
    AomWriter*          ec_writer     = &ec->ec_writer;
4998
146k
    SequenceControlSet* scs           = pcs->scs;
4999
146k
    FrameHeader*        frm_hdr       = &pcs->ppcs->frm_hdr;
5000
5001
146k
    NeighborArrayUnit* luma_dc_sign_level_coeff_na = pcs->luma_dc_sign_level_coeff_na[tile_idx];
5002
146k
    NeighborArrayUnit* cr_dc_sign_level_coeff_na   = pcs->cr_dc_sign_level_coeff_na[tile_idx];
5003
146k
    NeighborArrayUnit* cb_dc_sign_level_coeff_na   = pcs->cb_dc_sign_level_coeff_na[tile_idx];
5004
146k
    NeighborArrayUnit* txfm_context_array          = pcs->txfm_context_array[tile_idx];
5005
146k
    const uint32_t     blk_org_x                   = mi_col << MI_SIZE_LOG2;
5006
146k
    const uint32_t     blk_org_y                   = mi_row << MI_SIZE_LOG2;
5007
146k
    MbModeInfo*        mbmi                        = get_mbmi(pcs, blk_org_x, blk_org_y);
5008
146k
    const BlockSize    bsize                       = mbmi->bsize;
5009
146k
    const int          bwidth                      = block_size_wide[bsize];
5010
146k
    const int          bheight                     = block_size_high[bsize];
5011
146k
    bool               skip_coeff                  = mbmi->block_mi.skip;
5012
146k
    const bool         has_uv                      = is_chroma_reference(blk_org_y >> 2, blk_org_x >> 2, bsize, 1, 1);
5013
146k
    ec_ctx->mbmi                                   = mbmi;
5014
5015
146k
    const uint8_t skip_mode = mbmi->block_mi.skip_mode;
5016
5017
146k
    assert(bsize < BLOCK_SIZES_ALL);
5018
146k
    int mi_stride                     = pcs->ppcs->av1_cm->mi_stride;
5019
146k
    blk_ptr->av1xd->tile.mi_col_start = sb_ptr->tile_info.mi_col_start;
5020
146k
    blk_ptr->av1xd->tile.mi_col_end   = sb_ptr->tile_info.mi_col_end;
5021
146k
    blk_ptr->av1xd->tile.mi_row_start = sb_ptr->tile_info.mi_row_start;
5022
146k
    blk_ptr->av1xd->tile.mi_row_end   = sb_ptr->tile_info.mi_row_end;
5023
146k
    blk_ptr->av1xd->tile_ctx          = frame_context;
5024
5025
146k
    const int32_t bw = mi_size_wide[bsize];
5026
146k
    const int32_t bh = mi_size_high[bsize];
5027
146k
    set_mi_row_col(pcs,
5028
146k
                   blk_ptr->av1xd,
5029
146k
                   &blk_ptr->av1xd->tile,
5030
146k
                   mi_row,
5031
146k
                   bh,
5032
146k
                   mi_col,
5033
146k
                   bw,
5034
146k
                   mi_stride,
5035
146k
                   pcs->ppcs->av1_cm->mi_rows,
5036
146k
                   pcs->ppcs->av1_cm->mi_cols);
5037
146k
    if (pcs->slice_type == I_SLICE) {
5038
        //const int32_t skip = write_skip(cm, xd, mbmi->segment_id, mi, w)
5039
5040
146k
        if (pcs->ppcs->frm_hdr.segmentation_params.segmentation_enabled &&
5041
0
            pcs->ppcs->frm_hdr.segmentation_params.seg_id_pre_skip) {
5042
0
            write_segment_id(pcs, frame_context, ec_writer, bsize, blk_org_x, blk_org_y, blk_ptr, skip_coeff);
5043
0
        }
5044
5045
146k
        encode_skip_coeff_av1(blk_ptr, frame_context, ec_writer, skip_coeff);
5046
5047
146k
        if (pcs->ppcs->frm_hdr.segmentation_params.segmentation_enabled &&
5048
0
            !pcs->ppcs->frm_hdr.segmentation_params.seg_id_pre_skip) {
5049
0
            write_segment_id(pcs, frame_context, ec_writer, bsize, blk_org_x, blk_org_y, blk_ptr, skip_coeff);
5050
0
        }
5051
5052
146k
        write_cdef(scs, pcs, ec_ctx, ec_writer, skip_coeff, blk_org_x >> MI_SIZE_LOG2, blk_org_y >> MI_SIZE_LOG2);
5053
146k
        if (pcs->ppcs->frm_hdr.delta_q_params.delta_q_present) {
5054
0
            int32_t current_q_index        = blk_ptr->qindex;
5055
0
            int32_t super_block_upper_left = (((blk_org_y >> 2) & (scs->seq_header.sb_mi_size - 1)) == 0) &&
5056
0
                (((blk_org_x >> 2) & (scs->seq_header.sb_mi_size - 1)) == 0);
5057
0
            if ((bsize != scs->seq_header.sb_size || skip_coeff == 0) && super_block_upper_left) {
5058
0
                assert(current_q_index > 0);
5059
0
                int32_t reduced_delta_qindex = (current_q_index - pcs->ppcs->prev_qindex[tile_idx]) /
5060
0
                    frm_hdr->delta_q_params.delta_q_res;
5061
5062
                //write_delta_qindex(xd, reduced_delta_qindex, w);
5063
0
                av1_write_delta_q_index(frame_context, reduced_delta_qindex, ec_writer);
5064
                /*if (pcs->picture_number == 0){
5065
                SVT_LOG("%d\t%d\t%d\t%d\n",
5066
                blk_org_x,
5067
                blk_org_y,
5068
                current_q_index,
5069
                pcs->ppcs->prev_qindex);
5070
                }*/
5071
0
                pcs->ppcs->prev_qindex[tile_idx] = current_q_index;
5072
0
            }
5073
0
        }
5074
5075
146k
        {
5076
146k
            const uint32_t intra_luma_mode   = mbmi->block_mi.mode;
5077
146k
            uint32_t       intra_chroma_mode = mbmi->block_mi.uv_mode;
5078
146k
            if (svt_aom_allow_intrabc(&pcs->ppcs->frm_hdr, pcs->ppcs->slice_type)) {
5079
0
                write_intrabc_info(frame_context, mbmi, blk_ptr, ec_writer);
5080
0
            }
5081
146k
            if (mbmi->block_mi.use_intrabc == 0) {
5082
146k
                encode_intra_luma_mode_kf_av1(frame_context, ec_writer, mbmi, blk_ptr, bsize, intra_luma_mode);
5083
146k
            }
5084
146k
            if (mbmi->block_mi.use_intrabc == 0) {
5085
146k
                if (has_uv) {
5086
146k
                    encode_intra_chroma_mode_av1(frame_context,
5087
146k
                                                 ec_writer,
5088
146k
                                                 mbmi,
5089
146k
                                                 bsize,
5090
146k
                                                 intra_luma_mode,
5091
146k
                                                 intra_chroma_mode,
5092
146k
                                                 bwidth <= 32 && bheight <= 32);
5093
146k
                }
5094
146k
            }
5095
146k
            if (mbmi->block_mi.use_intrabc == 0 && svt_aom_allow_palette(frm_hdr->allow_screen_content_tools, bsize)) {
5096
0
                write_palette_mode_info(
5097
5098
0
                    pcs->ppcs,
5099
0
                    frame_context,
5100
0
                    mbmi,
5101
0
                    blk_ptr,
5102
0
                    bsize,
5103
0
                    blk_org_y >> MI_SIZE_LOG2,
5104
0
                    blk_org_x >> MI_SIZE_LOG2,
5105
0
                    ec_writer);
5106
0
            }
5107
146k
            if (mbmi->block_mi.use_intrabc == 0 &&
5108
146k
                svt_aom_filter_intra_allowed(
5109
146k
                    scs->seq_header.filter_intra_level, bsize, blk_ptr->palette_size[0], intra_luma_mode)) {
5110
0
                aom_write_symbol(ec_writer,
5111
0
                                 mbmi->block_mi.filter_intra_mode != FILTER_INTRA_MODES,
5112
0
                                 frame_context->filter_intra_cdfs[bsize],
5113
0
                                 2);
5114
0
                if (mbmi->block_mi.filter_intra_mode != FILTER_INTRA_MODES) {
5115
0
                    aom_write_symbol(ec_writer,
5116
0
                                     mbmi->block_mi.filter_intra_mode,
5117
0
                                     frame_context->filter_intra_mode_cdf,
5118
0
                                     FILTER_INTRA_MODES);
5119
0
                }
5120
0
            }
5121
146k
            if (mbmi->block_mi.use_intrabc == 0) {
5122
146k
                assert(blk_ptr->palette_size[1] == 0);
5123
146k
                TOKENEXTRA* tok = ec_ctx->tok;
5124
440k
                for (int plane = 0; plane < 2; ++plane) {
5125
293k
                    const uint8_t palette_size_plane = blk_ptr->palette_size[plane];
5126
293k
                    if (palette_size_plane > 0) {
5127
0
                        const TxSize tx_size = tx_depth_to_tx_size[mbmi->block_mi.tx_depth][mbmi->bsize];
5128
0
                        svt_av1_tokenize_color_map(
5129
0
                            frame_context,
5130
0
                            blk_ptr,
5131
0
                            plane,
5132
0
                            &tok,
5133
0
                            bsize,
5134
0
                            tx_size,
5135
0
                            PALETTE_MAP,
5136
0
                            0); //NO CDF update in entropy, the update will take place in arithmetic encode
5137
0
                        assert(mbmi->block_mi.use_intrabc == 0);
5138
0
                        assert(svt_aom_allow_palette(pcs->ppcs->frm_hdr.allow_screen_content_tools, bsize));
5139
0
                        int rows, cols;
5140
0
                        svt_aom_get_block_dimensions(bsize, plane, blk_ptr->av1xd, NULL, NULL, &rows, &cols);
5141
0
                        pack_map_tokens(ec_writer, (const TOKENEXTRA**)(&ec_ctx->tok), palette_size_plane, rows * cols);
5142
                        // advance the pointer
5143
0
                        ec_ctx->tok = tok;
5144
0
                    }
5145
293k
                }
5146
146k
            }
5147
146k
            if (frm_hdr->tx_mode == TX_MODE_SELECT) {
5148
146k
                code_tx_size(pcs,
5149
146k
                             blk_org_x,
5150
146k
                             blk_org_y,
5151
146k
                             blk_ptr,
5152
146k
                             bsize,
5153
146k
                             txfm_context_array,
5154
146k
                             frame_context,
5155
146k
                             ec_writer,
5156
146k
                             skip_coeff);
5157
146k
            }
5158
146k
            if (!skip_coeff) {
5159
6.65k
                av1_encode_coeff_1d(pcs,
5160
6.65k
                                    ec_ctx,
5161
6.65k
                                    frame_context,
5162
6.65k
                                    ec_writer,
5163
6.65k
                                    blk_ptr,
5164
6.65k
                                    blk_org_x,
5165
6.65k
                                    blk_org_y,
5166
6.65k
                                    intra_luma_mode,
5167
6.65k
                                    bsize,
5168
6.65k
                                    coeff_ptr,
5169
6.65k
                                    luma_dc_sign_level_coeff_na,
5170
6.65k
                                    cr_dc_sign_level_coeff_na,
5171
6.65k
                                    cb_dc_sign_level_coeff_na);
5172
6.65k
            }
5173
146k
        }
5174
146k
    } else {
5175
0
        write_inter_segment_id(pcs, frame_context, ec_writer, bsize, blk_org_x, blk_org_y, blk_ptr, 0, 1);
5176
0
        if (frm_hdr->skip_mode_params.skip_mode_flag && is_comp_ref_allowed(bsize)) {
5177
0
            encode_skip_mode_av1(blk_ptr, frame_context, ec_writer, skip_mode);
5178
0
        }
5179
0
        if (!frm_hdr->skip_mode_params.skip_mode_flag && skip_mode) {
5180
0
            SVT_ERROR("SKIP not supported\n");
5181
0
        }
5182
0
        if (!skip_mode) {
5183
            // const int32_t skip = write_skip(cm, xd, mbmi->segment_id, mi, w);
5184
0
            encode_skip_coeff_av1(blk_ptr, frame_context, ec_writer, skip_coeff);
5185
0
        }
5186
5187
0
        write_inter_segment_id(pcs, frame_context, ec_writer, bsize, blk_org_x, blk_org_y, blk_ptr, skip_coeff, 0);
5188
0
        write_cdef(scs,
5189
0
                   pcs, /*cm,*/
5190
0
                   ec_ctx,
5191
0
                   ec_writer,
5192
0
                   skip_mode ? 1 : skip_coeff,
5193
0
                   blk_org_x >> MI_SIZE_LOG2,
5194
0
                   blk_org_y >> MI_SIZE_LOG2);
5195
0
        if (pcs->ppcs->frm_hdr.delta_q_params.delta_q_present) {
5196
0
            int32_t current_q_index        = blk_ptr->qindex;
5197
0
            int32_t super_block_upper_left = (((blk_org_y >> 2) & (scs->seq_header.sb_mi_size - 1)) == 0) &&
5198
0
                (((blk_org_x >> 2) & (scs->seq_header.sb_mi_size - 1)) == 0);
5199
0
            if ((bsize != scs->seq_header.sb_size || skip_coeff == 0) && super_block_upper_left) {
5200
0
                assert(current_q_index > 0);
5201
0
                int32_t reduced_delta_qindex = (current_q_index - pcs->ppcs->prev_qindex[tile_idx]) /
5202
0
                    frm_hdr->delta_q_params.delta_q_res;
5203
0
                av1_write_delta_q_index(frame_context, reduced_delta_qindex, ec_writer);
5204
0
                pcs->ppcs->prev_qindex[tile_idx] = current_q_index;
5205
0
            }
5206
0
        }
5207
0
        if (frm_hdr->tx_mode == TX_MODE_SELECT) {
5208
0
            if (skip_mode) {
5209
0
                code_tx_size(
5210
0
                    pcs, blk_org_x, blk_org_y, blk_ptr, bsize, txfm_context_array, frame_context, ec_writer, skip_mode);
5211
0
            }
5212
0
        }
5213
0
        if (!skip_mode) {
5214
0
            write_is_inter(blk_ptr, frame_context, ec_writer, (int32_t)is_inter_mode(ec_ctx->mbmi->block_mi.mode));
5215
0
            if (is_intra_mode(ec_ctx->mbmi->block_mi.mode)) {
5216
0
                uint32_t intra_luma_mode = mbmi->block_mi.mode;
5217
5218
0
                uint32_t intra_chroma_mode = mbmi->block_mi.uv_mode;
5219
5220
0
                encode_intra_luma_mode_nonkey_av1(frame_context, ec_writer, mbmi, bsize, intra_luma_mode);
5221
0
                if (has_uv) {
5222
0
                    encode_intra_chroma_mode_av1(frame_context,
5223
0
                                                 ec_writer,
5224
0
                                                 mbmi,
5225
0
                                                 bsize,
5226
0
                                                 intra_luma_mode,
5227
0
                                                 intra_chroma_mode,
5228
0
                                                 bwidth <= 32 && bheight <= 32);
5229
0
                }
5230
0
                if (svt_aom_allow_palette(pcs->ppcs->frm_hdr.allow_screen_content_tools, bsize)) {
5231
0
                    write_palette_mode_info(pcs->ppcs,
5232
0
                                            frame_context,
5233
0
                                            mbmi,
5234
0
                                            blk_ptr,
5235
0
                                            bsize,
5236
0
                                            blk_org_y >> MI_SIZE_LOG2,
5237
0
                                            blk_org_x >> MI_SIZE_LOG2,
5238
0
                                            ec_writer);
5239
0
                }
5240
0
                if (svt_aom_filter_intra_allowed(
5241
0
                        scs->seq_header.filter_intra_level, bsize, blk_ptr->palette_size[0], intra_luma_mode)) {
5242
0
                    aom_write_symbol(ec_writer,
5243
0
                                     mbmi->block_mi.filter_intra_mode != FILTER_INTRA_MODES,
5244
0
                                     frame_context->filter_intra_cdfs[bsize],
5245
0
                                     2);
5246
0
                    if (mbmi->block_mi.filter_intra_mode != FILTER_INTRA_MODES) {
5247
0
                        aom_write_symbol(ec_writer,
5248
0
                                         mbmi->block_mi.filter_intra_mode,
5249
0
                                         frame_context->filter_intra_mode_cdf,
5250
0
                                         FILTER_INTRA_MODES);
5251
0
                    }
5252
0
                }
5253
5254
0
            } else {
5255
0
                svt_aom_collect_neighbors_ref_counts_new(blk_ptr->av1xd);
5256
5257
0
                write_ref_frames(pcs->ppcs, blk_ptr->av1xd, ec_writer);
5258
5259
0
                MvReferenceFrame* rf          = mbmi->block_mi.ref_frame;
5260
0
                int16_t           mode_ctx    = svt_aom_mode_context_analyzer(blk_ptr->inter_mode_ctx, rf);
5261
0
                PredictionMode    inter_mode  = mbmi->block_mi.mode;
5262
0
                const int32_t     is_compound = is_inter_compound_mode(inter_mode);
5263
5264
                // If segment skip is not enabled code the mode.
5265
0
                if (is_inter_compound_mode(inter_mode)) {
5266
0
                    write_inter_compound_mode(frame_context, ec_writer, inter_mode, mode_ctx);
5267
0
                } else if (is_inter_singleref_mode(inter_mode)) {
5268
0
                    write_inter_mode(frame_context, ec_writer, inter_mode, mode_ctx, blk_org_x, blk_org_y);
5269
0
                }
5270
5271
0
                if (inter_mode == NEWMV || inter_mode == NEW_NEWMV || have_nearmv_in_inter_mode(inter_mode)) {
5272
0
                    write_drl_idx(frame_context, ec_writer, mbmi, blk_ptr);
5273
0
                }
5274
5275
0
                if (inter_mode == NEWMV || inter_mode == NEW_NEWMV) {
5276
0
                    Mv ref_mv;
5277
5278
0
                    for (uint8_t ref = 0; ref < 1 + is_compound; ++ref) {
5279
0
                        NmvContext* nmvc = &frame_context->nmvc;
5280
0
                        ref_mv           = blk_ptr->predmv[ref];
5281
5282
0
                        Mv mv = mbmi->block_mi.mv[ref];
5283
5284
0
                        svt_av1_encode_mv(pcs->ppcs, ec_writer, &mv, &ref_mv, nmvc, frm_hdr->allow_high_precision_mv);
5285
0
                    }
5286
0
                } else if (inter_mode == NEAREST_NEWMV || inter_mode == NEAR_NEWMV) {
5287
0
                    NmvContext* nmvc   = &frame_context->nmvc;
5288
0
                    Mv          ref_mv = blk_ptr->predmv[1];
5289
5290
0
                    Mv mv = mbmi->block_mi.mv[1];
5291
5292
0
                    svt_av1_encode_mv(pcs->ppcs, ec_writer, &mv, &ref_mv, nmvc, frm_hdr->allow_high_precision_mv);
5293
0
                } else if (inter_mode == NEW_NEARESTMV || inter_mode == NEW_NEARMV) {
5294
0
                    NmvContext* nmvc   = &frame_context->nmvc;
5295
0
                    Mv          ref_mv = blk_ptr->predmv[0];
5296
5297
0
                    Mv mv = mbmi->block_mi.mv[0];
5298
5299
0
                    svt_av1_encode_mv(pcs->ppcs, ec_writer, &mv, &ref_mv, nmvc, frm_hdr->allow_high_precision_mv);
5300
0
                }
5301
0
                if (scs->seq_header.enable_interintra_compound && svt_aom_is_interintra_allowed(mbmi)) {
5302
0
                    if (mbmi->block_mi.is_interintra_used) {
5303
0
                        rf[1]                       = INTRA_FRAME;
5304
0
                        mbmi->block_mi.ref_frame[1] = INTRA_FRAME;
5305
0
                    }
5306
5307
0
                    const int interintra  = mbmi->block_mi.is_interintra_used;
5308
0
                    const int bsize_group = eb_size_group_lookup[bsize];
5309
0
                    aom_write_symbol(
5310
0
                        ec_writer, mbmi->block_mi.is_interintra_used, frame_context->interintra_cdf[bsize_group], 2);
5311
0
                    if (interintra) {
5312
0
                        aom_write_symbol(ec_writer,
5313
0
                                         mbmi->block_mi.interintra_mode,
5314
0
                                         frame_context->interintra_mode_cdf[bsize_group],
5315
0
                                         INTERINTRA_MODES);
5316
0
                        if (svt_aom_is_interintra_wedge_used(bsize)) {
5317
0
                            aom_write_symbol(ec_writer,
5318
0
                                             mbmi->block_mi.use_wedge_interintra,
5319
0
                                             frame_context->wedge_interintra_cdf[bsize],
5320
0
                                             2);
5321
0
                            if (mbmi->block_mi.use_wedge_interintra) {
5322
0
                                aom_write_symbol(ec_writer,
5323
0
                                                 mbmi->block_mi.interintra_wedge_index,
5324
0
                                                 frame_context->wedge_idx_cdf[bsize],
5325
0
                                                 16);
5326
0
                            }
5327
0
                        }
5328
0
                    }
5329
0
                }
5330
5331
0
                if (frm_hdr->is_motion_mode_switchable && rf[1] != INTRA_FRAME) {
5332
0
                    write_motion_mode(
5333
0
                        frame_context, ec_writer, bsize, mbmi, mbmi->block_mi.motion_mode, rf[0], rf[1], blk_ptr, pcs);
5334
0
                }
5335
                // First write idx to indicate current compound inter prediction mode group
5336
                // Group A (0): dist_wtd_comp, compound_average
5337
                // Group b (1): interintra, compound_diffwtd, wedge
5338
0
                if (has_second_ref(&mbmi->block_mi)) {
5339
0
                    const int masked_compound_used = is_any_masked_compound_used(bsize) &&
5340
0
                        scs->seq_header.enable_masked_compound;
5341
5342
0
                    if (masked_compound_used) {
5343
0
                        const int ctx_comp_group_idx = svt_aom_get_comp_group_idx_context_enc(blk_ptr->av1xd);
5344
0
                        aom_write_symbol(ec_writer,
5345
0
                                         mbmi->block_mi.comp_group_idx,
5346
0
                                         frame_context->comp_group_idx_cdf[ctx_comp_group_idx],
5347
0
                                         2);
5348
0
                    } else {
5349
0
                        assert(mbmi->block_mi.comp_group_idx == 0);
5350
0
                    }
5351
5352
0
                    if (mbmi->block_mi.comp_group_idx == 0) {
5353
0
                        assert(IMPLIES(mbmi->block_mi.compound_idx,
5354
0
                                       mbmi->block_mi.interinter_comp.type == COMPOUND_AVERAGE));
5355
5356
0
                        if (scs->seq_header.order_hint_info.enable_jnt_comp) {
5357
0
                            const int comp_index_ctx = svt_aom_get_comp_index_context_enc(
5358
0
                                pcs->ppcs,
5359
0
                                pcs->ppcs->cur_order_hint, // cur_frame_index,
5360
0
                                pcs->ppcs->ref_order_hint[rf[0] - 1], // bck_frame_index,
5361
0
                                pcs->ppcs->ref_order_hint[rf[1] - 1], // fwd_frame_index,
5362
0
                                blk_ptr->av1xd);
5363
0
                            aom_write_symbol(ec_writer,
5364
0
                                             mbmi->block_mi.compound_idx,
5365
0
                                             frame_context->compound_index_cdf[comp_index_ctx],
5366
0
                                             2);
5367
0
                        } else {
5368
0
                            assert(mbmi->block_mi.compound_idx == 1);
5369
0
                        }
5370
0
                    } else {
5371
0
                        assert(pcs->ppcs->frm_hdr.reference_mode != SINGLE_REFERENCE &&
5372
0
                               is_inter_compound_mode(mbmi->block_mi.mode) &&
5373
0
                               mbmi->block_mi.motion_mode == SIMPLE_TRANSLATION);
5374
0
                        assert(masked_compound_used);
5375
                        // compound_diffwtd, wedge
5376
0
                        assert(mbmi->block_mi.interinter_comp.type == COMPOUND_WEDGE ||
5377
0
                               mbmi->block_mi.interinter_comp.type == COMPOUND_DIFFWTD);
5378
5379
0
                        if (is_interinter_compound_used(COMPOUND_WEDGE, bsize)) {
5380
0
                            aom_write_symbol(ec_writer,
5381
0
                                             mbmi->block_mi.interinter_comp.type - COMPOUND_WEDGE,
5382
0
                                             frame_context->compound_type_cdf[bsize],
5383
0
                                             MASKED_COMPOUND_TYPES);
5384
0
                        }
5385
5386
0
                        if (mbmi->block_mi.interinter_comp.type == COMPOUND_WEDGE) {
5387
0
                            assert(is_interinter_compound_used(COMPOUND_WEDGE, bsize));
5388
0
                            aom_write_symbol(ec_writer,
5389
0
                                             mbmi->block_mi.interinter_comp.wedge_index,
5390
0
                                             frame_context->wedge_idx_cdf[bsize],
5391
0
                                             16);
5392
0
                            aom_write_bit(ec_writer, mbmi->block_mi.interinter_comp.wedge_sign);
5393
0
                        } else {
5394
0
                            assert(mbmi->block_mi.interinter_comp.type == COMPOUND_DIFFWTD);
5395
0
                            aom_write_literal(
5396
0
                                ec_writer, mbmi->block_mi.interinter_comp.mask_type, MAX_DIFFWTD_MASK_BITS);
5397
0
                        }
5398
0
                    }
5399
0
                }
5400
0
                write_mb_interp_filter(bsize, rf[0], rf[1], pcs->ppcs, ec_writer, mbmi, blk_ptr, ec);
5401
0
            }
5402
0
            {
5403
0
                assert(blk_ptr->palette_size[1] == 0);
5404
0
                TOKENEXTRA* tok = ec_ctx->tok;
5405
0
                for (int plane = 0; plane < 2; ++plane) {
5406
0
                    const uint8_t palette_size_plane = blk_ptr->palette_size[plane];
5407
0
                    if (palette_size_plane > 0) {
5408
0
                        const TxSize tx_size = tx_depth_to_tx_size[mbmi->block_mi.tx_depth][mbmi->bsize];
5409
0
                        svt_av1_tokenize_color_map(
5410
0
                            frame_context,
5411
0
                            blk_ptr,
5412
0
                            plane,
5413
0
                            &tok,
5414
0
                            bsize,
5415
0
                            tx_size,
5416
0
                            PALETTE_MAP,
5417
0
                            0); //NO CDF update in entropy, the update will take place in arithmetic encode
5418
0
                        assert(mbmi->block_mi.use_intrabc == 0);
5419
0
                        assert(svt_aom_allow_palette(pcs->ppcs->frm_hdr.allow_screen_content_tools, bsize));
5420
0
                        int rows, cols;
5421
0
                        svt_aom_get_block_dimensions(bsize, plane, blk_ptr->av1xd, NULL, NULL, &rows, &cols);
5422
0
                        pack_map_tokens(ec_writer, (const TOKENEXTRA**)(&ec_ctx->tok), palette_size_plane, rows * cols);
5423
                        // advance the pointer
5424
0
                        ec_ctx->tok = tok;
5425
0
                    }
5426
0
                }
5427
0
            }
5428
5429
0
            if (frm_hdr->tx_mode == TX_MODE_SELECT) {
5430
0
                code_tx_size(pcs,
5431
0
                             blk_org_x,
5432
0
                             blk_org_y,
5433
0
                             blk_ptr,
5434
0
                             bsize,
5435
0
                             txfm_context_array,
5436
0
                             frame_context,
5437
0
                             ec_writer,
5438
0
                             skip_coeff);
5439
0
            }
5440
0
            if (!skip_coeff) {
5441
0
                uint32_t intra_luma_mode = DC_PRED;
5442
0
                if (is_intra_mode(ec_ctx->mbmi->block_mi.mode)) {
5443
0
                    intra_luma_mode = mbmi->block_mi.mode;
5444
0
                }
5445
5446
0
                {
5447
0
                    av1_encode_coeff_1d(pcs,
5448
0
                                        ec_ctx,
5449
0
                                        frame_context,
5450
0
                                        ec_writer,
5451
0
                                        blk_ptr,
5452
0
                                        blk_org_x,
5453
0
                                        blk_org_y,
5454
0
                                        intra_luma_mode,
5455
0
                                        bsize,
5456
0
                                        coeff_ptr,
5457
0
                                        luma_dc_sign_level_coeff_na,
5458
0
                                        cr_dc_sign_level_coeff_na,
5459
0
                                        cb_dc_sign_level_coeff_na);
5460
0
                }
5461
0
            }
5462
0
        }
5463
0
    }
5464
146k
#if OPT_STATS_MUTEX
5465
146k
    ec_ctx->tot_qindex += (uint64_t)blk_ptr->qindex * bwidth * bheight;
5466
146k
    ec_ctx->valid_area += bwidth * bheight;
5467
#else
5468
    svt_block_on_mutex(pcs->entropy_coding_pic_mutex);
5469
    pcs->ppcs->tot_qindex += blk_ptr->qindex * bwidth * bheight;
5470
    pcs->ppcs->valid_qindex_area += bwidth * bheight;
5471
    svt_release_mutex(pcs->entropy_coding_pic_mutex);
5472
#endif
5473
    // Update the neighbors
5474
146k
    ec_update_neighbors(pcs, ec_ctx, blk_org_x, blk_org_y, tile_idx, bsize);
5475
5476
146k
    if (svt_av1_allow_palette(pcs->ppcs->palette_level, bsize)) {
5477
        // free ENCDEC palette info buffer
5478
0
        assert(blk_ptr->palette_info->color_idx_map != NULL && "free palette:Null");
5479
0
        EB_FREE(blk_ptr->palette_info->color_idx_map);
5480
0
        blk_ptr->palette_info->color_idx_map = NULL;
5481
0
        EB_FREE(blk_ptr->palette_info);
5482
0
    }
5483
5484
146k
    return return_error;
5485
146k
}
5486
5487
/**********************************************
5488
 * Write sb
5489
 **********************************************/
5490
void svt_aom_write_modes_sb(EntropyCodingContext* ec_ctx, SuperBlock* sb_ptr, PictureControlSet* pcs, uint16_t tile_idx,
5491
                            EntropyCoder* ec, EbPictureBufferDesc* coeff_ptr, PARTITION_TREE* ptree, int mi_row,
5492
200k
                            int mi_col) {
5493
200k
    if (mi_row >= pcs->ppcs->av1_cm->mi_rows || mi_col >= pcs->ppcs->av1_cm->mi_cols) {
5494
0
        return;
5495
0
    }
5496
200k
    FRAME_CONTEXT*     frame_context        = ec->fc;
5497
200k
    AomWriter*         ec_writer            = &ec->ec_writer;
5498
200k
    NeighborArrayUnit* partition_context_na = pcs->partition_context_na[tile_idx];
5499
5500
200k
    const BlockSize bsize = ptree->bsize;
5501
200k
    assert(bsize < BLOCK_SIZES_ALL);
5502
200k
    const int           hbs          = mi_size_wide[bsize] >> 1;
5503
200k
    const int           quarter_step = mi_size_wide[bsize] >> 2;
5504
200k
    const PartitionType partition    = ptree->partition;
5505
200k
    Av1Common*          cm           = pcs->ppcs->av1_cm;
5506
5507
200k
    if (bsize >= BLOCK_8X8) {
5508
800k
        for (int32_t plane = 0; plane < 3; ++plane) {
5509
600k
            int32_t rcol0, rcol1, rrow0, rrow1, tile_tl_idx;
5510
600k
            if (svt_av1_loop_restoration_corners_in_sb(cm,
5511
600k
                                                       &pcs->scs->seq_header,
5512
600k
                                                       plane,
5513
600k
                                                       mi_row,
5514
600k
                                                       mi_col,
5515
600k
                                                       bsize,
5516
600k
                                                       &rcol0,
5517
600k
                                                       &rcol1,
5518
600k
                                                       &rrow0,
5519
600k
                                                       &rrow1,
5520
600k
                                                       &tile_tl_idx)) {
5521
0
                const int32_t rstride = pcs->rst_info[plane].horz_units_per_tile;
5522
0
                for (int32_t rrow = rrow0; rrow < rrow1; ++rrow) {
5523
0
                    for (int32_t rcol = rcol0; rcol < rcol1; ++rcol) {
5524
0
                        const int32_t              runit_idx = tile_tl_idx + rcol + rrow * rstride;
5525
0
                        const RestorationUnitInfo* rui       = &pcs->rst_info[plane].unit_info[runit_idx];
5526
0
                        loop_restoration_write_sb_coeffs(pcs, frame_context, ec_ctx, rui, ec_writer, plane);
5527
0
                    }
5528
0
                }
5529
0
            }
5530
600k
        }
5531
5532
200k
        encode_partition_av1(pcs,
5533
200k
                             frame_context,
5534
200k
                             ec_writer,
5535
200k
                             bsize,
5536
200k
                             partition,
5537
200k
                             mi_col << MI_SIZE_LOG2,
5538
200k
                             mi_row << MI_SIZE_LOG2,
5539
200k
                             partition_context_na);
5540
200k
    }
5541
5542
200k
    assert(IMPLIES(bsize == BLOCK_4X4, partition == PARTITION_NONE));
5543
200k
    assert(IMPLIES(partition != PARTITION_SPLIT, (mi_row + hbs < cm->mi_rows) || (mi_col + hbs < cm->mi_cols)));
5544
200k
    switch (partition) {
5545
146k
    case PARTITION_NONE:
5546
146k
        write_modes_b(pcs, ec_ctx, ec, sb_ptr, ptree->blk_data[0], tile_idx, coeff_ptr, mi_row, mi_col);
5547
146k
        break;
5548
0
    case PARTITION_HORZ:
5549
0
        write_modes_b(pcs, ec_ctx, ec, sb_ptr, ptree->blk_data[0], tile_idx, coeff_ptr, mi_row, mi_col);
5550
0
        if (mi_row + hbs < cm->mi_rows) {
5551
0
            write_modes_b(pcs, ec_ctx, ec, sb_ptr, ptree->blk_data[1], tile_idx, coeff_ptr, mi_row + hbs, mi_col);
5552
0
        }
5553
0
        break;
5554
0
    case PARTITION_VERT:
5555
0
        write_modes_b(pcs, ec_ctx, ec, sb_ptr, ptree->blk_data[0], tile_idx, coeff_ptr, mi_row, mi_col);
5556
0
        if (mi_col + hbs < cm->mi_cols) {
5557
0
            write_modes_b(pcs, ec_ctx, ec, sb_ptr, ptree->blk_data[1], tile_idx, coeff_ptr, mi_row, mi_col + hbs);
5558
0
        }
5559
0
        break;
5560
53.3k
    case PARTITION_SPLIT:
5561
266k
        for (int i = 0; i < SUB_PARTITIONS_SPLIT; ++i) {
5562
213k
            const int x_idx = (i & 1) * hbs;
5563
213k
            const int y_idx = (i >> 1) * hbs;
5564
213k
            if (mi_row + y_idx >= cm->mi_rows || mi_col + x_idx >= cm->mi_cols) {
5565
20.2k
                continue;
5566
20.2k
            }
5567
193k
            svt_aom_write_modes_sb(
5568
193k
                ec_ctx, sb_ptr, pcs, tile_idx, ec, coeff_ptr, ptree->sub_tree[i], mi_row + y_idx, mi_col + x_idx);
5569
193k
        }
5570
53.3k
        break;
5571
0
    case PARTITION_HORZ_A:
5572
0
        write_modes_b(pcs, ec_ctx, ec, sb_ptr, ptree->blk_data[0], tile_idx, coeff_ptr, mi_row, mi_col);
5573
0
        write_modes_b(pcs, ec_ctx, ec, sb_ptr, ptree->blk_data[1], tile_idx, coeff_ptr, mi_row, mi_col + hbs);
5574
0
        write_modes_b(pcs, ec_ctx, ec, sb_ptr, ptree->blk_data[2], tile_idx, coeff_ptr, mi_row + hbs, mi_col);
5575
0
        break;
5576
0
    case PARTITION_HORZ_B:
5577
0
        write_modes_b(pcs, ec_ctx, ec, sb_ptr, ptree->blk_data[0], tile_idx, coeff_ptr, mi_row, mi_col);
5578
0
        write_modes_b(pcs, ec_ctx, ec, sb_ptr, ptree->blk_data[1], tile_idx, coeff_ptr, mi_row + hbs, mi_col);
5579
0
        write_modes_b(pcs, ec_ctx, ec, sb_ptr, ptree->blk_data[2], tile_idx, coeff_ptr, mi_row + hbs, mi_col + hbs);
5580
0
        break;
5581
0
    case PARTITION_VERT_A:
5582
0
        write_modes_b(pcs, ec_ctx, ec, sb_ptr, ptree->blk_data[0], tile_idx, coeff_ptr, mi_row, mi_col);
5583
0
        write_modes_b(pcs, ec_ctx, ec, sb_ptr, ptree->blk_data[1], tile_idx, coeff_ptr, mi_row + hbs, mi_col);
5584
0
        write_modes_b(pcs, ec_ctx, ec, sb_ptr, ptree->blk_data[2], tile_idx, coeff_ptr, mi_row, mi_col + hbs);
5585
0
        break;
5586
0
    case PARTITION_VERT_B:
5587
0
        write_modes_b(pcs, ec_ctx, ec, sb_ptr, ptree->blk_data[0], tile_idx, coeff_ptr, mi_row, mi_col);
5588
0
        write_modes_b(pcs, ec_ctx, ec, sb_ptr, ptree->blk_data[1], tile_idx, coeff_ptr, mi_row, mi_col + hbs);
5589
0
        write_modes_b(pcs, ec_ctx, ec, sb_ptr, ptree->blk_data[2], tile_idx, coeff_ptr, mi_row + hbs, mi_col + hbs);
5590
0
        break;
5591
0
    case PARTITION_HORZ_4:
5592
0
        for (int i = 0; i < SUB_PARTITIONS_PART4; ++i) {
5593
0
            int this_mi_row = mi_row + i * quarter_step;
5594
0
            if (i > 0 && this_mi_row >= cm->mi_rows) {
5595
                // Only the last block is able to be outside the picture boundary. If one of the first
5596
                // 3 blocks is outside the boundary, H4 is not a valid partition (see AV1 spec 5.11.4)
5597
0
                assert(i == 3);
5598
0
                break;
5599
0
            }
5600
0
            write_modes_b(pcs, ec_ctx, ec, sb_ptr, ptree->blk_data[i], tile_idx, coeff_ptr, this_mi_row, mi_col);
5601
0
        }
5602
0
        break;
5603
0
    case PARTITION_VERT_4:
5604
0
        for (int i = 0; i < SUB_PARTITIONS_PART4; ++i) {
5605
0
            int this_mi_col = mi_col + i * quarter_step;
5606
0
            if (i > 0 && this_mi_col >= cm->mi_cols) {
5607
                // Only the last block is able to be outside the picture boundary. If one of the first
5608
                // 3 blocks is outside the boundary, H4 is not a valid partition (see AV1 spec 5.11.4)
5609
0
                assert(i == 3);
5610
0
                break;
5611
0
            }
5612
0
            write_modes_b(pcs, ec_ctx, ec, sb_ptr, ptree->blk_data[i], tile_idx, coeff_ptr, mi_row, this_mi_col);
5613
0
        }
5614
0
        break;
5615
0
    default:
5616
        assert(0);
5617
200k
    }
5618
200k
}