Coverage Report

Created: 2026-05-16 06:41

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