/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 | } |