Coverage Report

Created: 2026-07-16 06:32

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