Coverage Report

Created: 2026-05-30 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/svt-av1/Source/Lib/Codec/ec_process.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 <stdio.h>
15
#include <string.h>
16
#include "enc_handle.h"
17
#include "entropy_coding.h"
18
#include "ec_process.h"
19
#include "enc_dec_results.h"
20
#include "ec_results.h"
21
#include "rc_tasks.h"
22
#include "cabac_context_model.h"
23
#include "svt_log.h"
24
#include "common_dsp_rtcd.h"
25
26
533
static void rest_context_dctor(EbPtr p) {
27
533
    EbThreadContext*      thread_ctx = (EbThreadContext*)p;
28
533
    EntropyCodingContext* obj        = (EntropyCodingContext*)thread_ctx->priv;
29
533
    EB_FREE_ARRAY(obj);
30
533
}
31
32
/******************************************************
33
 * Enc Dec Context Constructor
34
 ******************************************************/
35
EbErrorType svt_aom_entropy_coding_context_ctor(EbThreadContext* thread_ctx, const EbEncHandle* enc_handle_ptr,
36
533
                                                int index) {
37
533
    EntropyCodingContext* context_ptr;
38
533
    EB_CALLOC_ARRAY(context_ptr, 1);
39
533
    thread_ctx->priv  = context_ptr;
40
533
    thread_ctx->dctor = rest_context_dctor;
41
42
533
    context_ptr->is_16bit = enc_handle_ptr->scs_instance->scs->static_config.encoder_bit_depth > EB_EIGHT_BIT;
43
44
    // Zero levels_buf once; the tail (offset >= LEVELS_TAIL_OFFSET) serves as
45
    // bottom padding for all block sizes via offset-based placement in set_levels.
46
533
    memset(context_ptr->levels_buf + LEVELS_TAIL_OFFSET, 0, TX_PAD_2D - LEVELS_TAIL_OFFSET);
47
48
    // Input/Output System Resource Manager FIFOs
49
533
    context_ptr->enc_dec_input_fifo_ptr = svt_system_resource_get_consumer_fifo(
50
533
        enc_handle_ptr->rest_results_resource_ptr, index);
51
533
    context_ptr->entropy_coding_output_fifo_ptr = svt_system_resource_get_producer_fifo(
52
533
        enc_handle_ptr->entropy_coding_results_resource_ptr, index);
53
54
533
    return EB_ErrorNone;
55
533
}
56
57
/***********************************************
58
 * Entropy Coding Reset Neighbor Arrays
59
 ***********************************************/
60
5.67k
static void entropy_coding_reset_neighbor_arrays(PictureControlSet* pcs, uint16_t tile_idx) {
61
5.67k
    svt_aom_neighbor_array_unit_reset(pcs->partition_context_na[tile_idx]);
62
63
5.67k
    svt_aom_neighbor_array_unit_reset(pcs->luma_dc_sign_level_coeff_na[tile_idx]);
64
5.67k
    svt_aom_neighbor_array_unit_reset(pcs->cb_dc_sign_level_coeff_na[tile_idx]);
65
5.67k
    svt_aom_neighbor_array_unit_reset(pcs->cr_dc_sign_level_coeff_na[tile_idx]);
66
5.67k
    svt_aom_neighbor_array_unit_reset(pcs->txfm_context_array[tile_idx]);
67
5.67k
}
68
69
/**************************************************
70
 * Reset Entropy Coding Picture
71
 **************************************************/
72
533
static void reset_entropy_coding_picture(EntropyCodingContext* ctx, PictureControlSet* pcs, SequenceControlSet* scs) {
73
533
    PictureParentControlSet* ppcs     = pcs->ppcs;
74
533
    const uint16_t           tile_cnt = ppcs->av1_cm->tiles_info.tile_rows * ppcs->av1_cm->tiles_info.tile_cols;
75
533
    ctx->is_16bit                     = scs->static_config.encoder_bit_depth > EB_EIGHT_BIT;
76
533
    const FrameHeader* frm_hdr        = &ppcs->frm_hdr;
77
    // Asuming cb and cr offset to be the same for chroma QP in both slice and pps for lambda computation
78
533
    const uint32_t entropy_coding_qp = frm_hdr->quantization_params.base_q_idx;
79
80
6.20k
    for (uint16_t tile_idx = 0; tile_idx < tile_cnt; tile_idx++) {
81
5.67k
        ppcs->prev_qindex[tile_idx] = entropy_coding_qp;
82
5.67k
    }
83
533
    if (frm_hdr->allow_intrabc) {
84
0
        assert(frm_hdr->delta_lf_params.delta_lf_present == 0);
85
0
    }
86
533
    if (frm_hdr->delta_lf_params.delta_lf_present) {
87
0
        ppcs->prev_delta_lf_from_base = 0;
88
89
0
        const int frame_lf_count = ppcs->monochrome == 0 ? FRAME_LF_COUNT : FRAME_LF_COUNT - 2;
90
0
        for (int lf_id = 0; lf_id < frame_lf_count; ++lf_id) {
91
0
            ppcs->prev_delta_lf[lf_id] = 0;
92
0
        }
93
0
    }
94
95
    // pass the ent
96
6.20k
    for (uint16_t tile_idx = 0; tile_idx < tile_cnt; tile_idx++) {
97
5.67k
        EntropyCoder*        ec                   = pcs->ec_info[tile_idx]->ec;
98
5.67k
        OutputBitstreamUnit* output_bitstream_ptr = ec->ec_output_bitstream_ptr;
99
        //****************************************************************//
100
5.67k
        ec->ec_writer.allow_update_cdf = !ppcs->large_scale_tile && !frm_hdr->disable_cdf_update;
101
5.67k
        aom_start_encode(&ec->ec_writer, output_bitstream_ptr);
102
        // ADD Reset here
103
5.67k
        const uint8_t primary_ref_frame = frm_hdr->primary_ref_frame;
104
5.67k
        if (primary_ref_frame != PRIMARY_REF_NONE) {
105
            // primary ref stored as REF_FRAME_MINUS1, while get_list_idx/get_ref_frame_idx take arg of ref frame
106
            // Therefore, add 1 to the primary ref frame (e.g. LAST --> LAST_FRAME)
107
0
            const uint8_t      list_idx = get_list_idx(primary_ref_frame + 1);
108
0
            const uint8_t      ref_idx  = get_ref_frame_idx(primary_ref_frame + 1);
109
0
            EbReferenceObject* ref      = (EbReferenceObject*)pcs->ref_pic_ptr_array[list_idx][ref_idx]->object_ptr;
110
0
            svt_memcpy(ec->fc, &ref->frame_context, sizeof(FRAME_CONTEXT));
111
5.67k
        } else {
112
5.67k
            svt_aom_reset_entropy_coder(scs->enc_ctx, ec, entropy_coding_qp, pcs->slice_type);
113
5.67k
        }
114
115
5.67k
        entropy_coding_reset_neighbor_arrays(pcs, tile_idx);
116
5.67k
    }
117
533
}
118
119
/* Entropy Coding */
120
121
/*********************************************************************************
122
 *
123
 * @brief
124
 *  The Entropy Coding process is responsible for producing an AV1 conformant bitstream for each
125
 *frame.
126
 *
127
 * @par Description:
128
 *  The entropy coder is a frame-based process and is based on multi-symbol arithmetic range coding.
129
 *  It takes as input the coding decisions and information for each block and produces as output the
130
 *bitstream for each frame.
131
 *
132
 * @param[in] Coding Decisions
133
 *  Coding decisions and information for each block.
134
 *
135
 * @param[out] bitstream
136
 *  Bitstream for each block
137
 *
138
 ********************************************************************************/
139
6.20k
EbErrorType svt_aom_entropy_coding_kernel_iter(void* context) {
140
6.20k
    EntropyCodingContext* context_ptr = (EntropyCodingContext*)context;
141
142
    // Input
143
6.20k
    EbObjectWrapper* rest_results_wrapper;
144
145
    // Output
146
6.20k
    EbObjectWrapper* entropy_coding_results_wrapper_ptr;
147
148
    // Get Mode Decision Results
149
6.20k
    EB_GET_FULL_OBJECT(context_ptr->enc_dec_input_fifo_ptr, &rest_results_wrapper);
150
151
5.67k
    RestResults*        rest_results = (RestResults*)rest_results_wrapper->object_ptr;
152
5.67k
    PictureControlSet*  pcs          = (PictureControlSet*)rest_results->pcs_wrapper->object_ptr;
153
5.67k
    SequenceControlSet* scs          = pcs->scs;
154
    // SB Constants
155
156
5.67k
    uint32_t sb_size = scs->sb_size;
157
158
5.67k
    uint8_t          sb_size_log2    = (uint8_t)svt_log2f(sb_size);
159
5.67k
    uint32_t         pic_width_in_sb = (pcs->ppcs->aligned_width + sb_size - 1) >> sb_size_log2;
160
5.67k
    uint16_t         tile_idx        = rest_results->tile_index;
161
5.67k
    Av1Common* const cm              = pcs->ppcs->av1_cm;
162
5.67k
    const uint16_t   tile_cnt        = cm->tiles_info.tile_rows * cm->tiles_info.tile_cols;
163
5.67k
    const uint16_t   tile_col        = tile_idx % cm->tiles_info.tile_cols;
164
5.67k
    const uint16_t   tile_row        = tile_idx / cm->tiles_info.tile_cols;
165
5.67k
    const uint16_t   tile_sb_start_x = cm->tiles_info.tile_col_start_mi[tile_col] >> scs->seq_header.sb_size_log2;
166
5.67k
    const uint16_t   tile_sb_start_y = cm->tiles_info.tile_row_start_mi[tile_row] >> scs->seq_header.sb_size_log2;
167
168
5.67k
    uint16_t tile_width_in_sb = (cm->tiles_info.tile_col_start_mi[tile_col + 1] -
169
5.67k
                                 cm->tiles_info.tile_col_start_mi[tile_col]) >>
170
5.67k
        scs->seq_header.sb_size_log2;
171
5.67k
    uint16_t tile_height_in_sb = (cm->tiles_info.tile_row_start_mi[tile_row + 1] -
172
5.67k
                                  cm->tiles_info.tile_row_start_mi[tile_row]) >>
173
5.67k
        scs->seq_header.sb_size_log2;
174
175
5.67k
    bool frame_entropy_done = false;
176
177
5.67k
    svt_block_on_mutex(pcs->entropy_coding_pic_mutex);
178
5.67k
    if (pcs->entropy_coding_pic_reset_flag) {
179
533
        pcs->entropy_coding_pic_reset_flag = false;
180
181
533
        reset_entropy_coding_picture(context_ptr, pcs, scs);
182
533
    }
183
5.67k
    svt_release_mutex(pcs->entropy_coding_pic_mutex);
184
185
5.67k
    if (!svt_aom_is_pic_skipped(pcs->ppcs)) {
186
5.67k
#if OPT_STATS_MUTEX
187
5.67k
        context_ptr->tot_qindex = 0;
188
5.67k
        context_ptr->valid_area = 0;
189
5.67k
#endif
190
11.6k
        for (uint32_t y_sb_index = 0; y_sb_index < tile_height_in_sb; ++y_sb_index) {
191
12.9k
            for (uint32_t x_sb_index = 0; x_sb_index < tile_width_in_sb; ++x_sb_index) {
192
6.90k
                uint16_t    sb_index = (uint16_t)((x_sb_index + tile_sb_start_x) +
193
6.90k
                                               (y_sb_index + tile_sb_start_y) * pic_width_in_sb);
194
6.90k
                SuperBlock* sb_ptr   = pcs->sb_ptr_array[sb_index];
195
196
6.90k
                const uint32_t sb_origin_x = (x_sb_index + tile_sb_start_x) << sb_size_log2;
197
6.90k
                const uint32_t sb_origin_y = (y_sb_index + tile_sb_start_y) << sb_size_log2;
198
6.90k
                if (x_sb_index == 0 && y_sb_index == 0) {
199
5.67k
                    svt_av1_reset_loop_restoration(context_ptr);
200
5.67k
                    context_ptr->tok = pcs->tile_tok[tile_row][tile_col];
201
5.67k
                }
202
203
6.90k
                EbPictureBufferDesc* coeff_picture_ptr = pcs->ppcs->enc_dec_ptr->quantized_coeff[sb_index];
204
6.90k
                context_ptr->coded_area_sb             = 0;
205
6.90k
                context_ptr->coded_area_sb_uv          = 0;
206
                // Ensure EC buffer has room for worst-case SB output (4 bytes/pixel)
207
6.90k
                EbErrorType ret = svt_aom_ec_ensure_capacity(&pcs->ec_info[tile_idx]->ec->ec_writer,
208
6.90k
                                                             sb_size * sb_size * 4);
209
6.90k
                if (ret != EB_ErrorNone) {
210
0
                    return ret;
211
0
                }
212
6.90k
                svt_aom_write_modes_sb(context_ptr,
213
6.90k
                                       sb_ptr,
214
6.90k
                                       pcs,
215
6.90k
                                       tile_idx,
216
6.90k
                                       pcs->ec_info[tile_idx]->ec,
217
6.90k
                                       coeff_picture_ptr,
218
6.90k
                                       sb_ptr->ptree,
219
6.90k
                                       sb_origin_y >> MI_SIZE_LOG2,
220
6.90k
                                       sb_origin_x >> MI_SIZE_LOG2);
221
6.90k
            }
222
6.02k
        }
223
5.67k
    }
224
5.67k
    bool pic_ready = true;
225
226
    // Current tile ready
227
5.67k
    svt_aom_encode_slice_finish(pcs->ec_info[tile_idx]->ec);
228
229
5.67k
    svt_block_on_mutex(pcs->entropy_coding_pic_mutex);
230
5.67k
#if OPT_STATS_MUTEX
231
    // Flush locally-accumulated qindex stats (avoids per-block mutex)
232
5.67k
    pcs->ppcs->tot_qindex += context_ptr->tot_qindex;
233
5.67k
    pcs->ppcs->valid_qindex_area += context_ptr->valid_area;
234
5.67k
#endif
235
5.67k
    pcs->ec_info[tile_idx]->entropy_coding_tile_done = true;
236
43.9k
    for (uint16_t i = 0; i < tile_cnt; i++) {
237
43.4k
        if (pcs->ec_info[i]->entropy_coding_tile_done == false) {
238
5.14k
            pic_ready = false;
239
5.14k
            break;
240
5.14k
        }
241
43.4k
    }
242
5.67k
    svt_release_mutex(pcs->entropy_coding_pic_mutex);
243
5.67k
    if (pic_ready) {
244
533
        if (pcs->ppcs->superres_total_recode_loop == 0) {
245
            // Release the reference Pictures from both lists
246
4.26k
            for (REF_FRAME_MINUS1 ref = LAST; ref < ALT + 1; ref++) {
247
3.73k
                const uint8_t list_idx = get_list_idx(ref + 1);
248
3.73k
                const uint8_t ref_idx  = get_ref_frame_idx(ref + 1);
249
3.73k
                if (pcs->ref_pic_ptr_array[list_idx][ref_idx] != NULL) {
250
0
                    svt_release_object(pcs->ref_pic_ptr_array[list_idx][ref_idx]);
251
0
                }
252
3.73k
            }
253
254
            //free palette data
255
533
            if (pcs->tile_tok[0][0]) {
256
0
                EB_FREE_ARRAY(pcs->tile_tok[0][0]);
257
0
            }
258
533
        }
259
533
        frame_entropy_done = true;
260
533
    }
261
262
5.67k
    if (frame_entropy_done) {
263
533
        if (pcs->ppcs->valid_qindex_area) {
264
533
            pcs->ppcs->avg_qp = ((pcs->ppcs->tot_qindex / pcs->ppcs->valid_qindex_area) + 2) >> 2;
265
533
        }
266
        // Get Empty Entropy Coding Results
267
533
        svt_get_empty_object(context_ptr->entropy_coding_output_fifo_ptr, &entropy_coding_results_wrapper_ptr);
268
533
        EntropyCodingResults* entropy_coding_results_ptr = (EntropyCodingResults*)
269
533
                                                               entropy_coding_results_wrapper_ptr->object_ptr;
270
533
        entropy_coding_results_ptr->pcs_wrapper = rest_results->pcs_wrapper;
271
272
        // Post EntropyCoding Results
273
533
        svt_post_full_object(entropy_coding_results_wrapper_ptr);
274
533
    }
275
276
    // Release Mode Decision Results
277
5.67k
    svt_release_object(rest_results_wrapper);
278
5.67k
    return EB_ErrorNone;
279
5.67k
}
280
281
533
void* svt_aom_entropy_coding_kernel(void* input_ptr) {
282
533
    EbThreadContext* thread_ctx = (EbThreadContext*)input_ptr;
283
6.20k
    for (;;) {
284
6.20k
        EbErrorType err = svt_aom_entropy_coding_kernel_iter(thread_ctx->priv);
285
6.20k
        if (err == EB_NoErrorFifoShutdown) {
286
533
            return NULL;
287
533
        }
288
6.20k
    }
289
0
    return NULL;
290
533
}