Coverage Report

Created: 2026-10-28 06:18

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