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