/work/svt-av1/Source/Lib/Codec/rest_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 www.aomedia.org/license/patent. |
11 | | */ |
12 | | |
13 | | #include <stdlib.h> |
14 | | |
15 | | #include "enc_handle.h" |
16 | | #include "rest_process.h" |
17 | | #include "enc_dec_results.h" |
18 | | #include "svt_threads.h" |
19 | | #include "pic_demux_results.h" |
20 | | #include "reference_object.h" |
21 | | #include "pcs.h" |
22 | | #include "resource_coordination_process.h" |
23 | | #include "resize.h" |
24 | | #include "enc_mode_config.h" |
25 | | |
26 | | /************************************** |
27 | | * Rest Context |
28 | | **************************************/ |
29 | | typedef struct RestContext { |
30 | | EbDctor dctor; |
31 | | EbFifo* rest_input_fifo_ptr; |
32 | | EbFifo* rest_output_fifo_ptr; |
33 | | EbFifo* picture_demux_fifo_ptr; |
34 | | |
35 | | EbPictureBufferDesc* trial_frame_rst; |
36 | | |
37 | | EbPictureBufferDesc* org_rec_frame; |
38 | | // while doing the filtering recon gets updated using setup/restore processing_stripe_bounadaries |
39 | | // many threads doing the above will result in race condition. |
40 | | // each thread will hence have his own copy of recon to work on. |
41 | | // later we can have a search version that does not need the exact right recon |
42 | | int32_t* rst_tmpbuf; |
43 | | } RestContext; |
44 | | |
45 | | void svt_aom_recon_output(PictureControlSet* pcs, SequenceControlSet* scs); |
46 | | void svt_av1_loop_restoration_filter_frame(int32_t* rst_tmpbuf, Yv12BufferConfig* frame, Av1Common* cm, |
47 | | int32_t optimized_lr); |
48 | | EbErrorType psnr_calculations(PictureControlSet* pcs, SequenceControlSet* scs, bool free_memory); |
49 | | EbErrorType svt_aom_ssim_calculations(PictureControlSet* pcs, SequenceControlSet* scs, bool free_memory); |
50 | | void pad_ref_and_set_flags(PictureControlSet* pcs, SequenceControlSet* scs); |
51 | | void restoration_seg_search(int32_t* rst_tmpbuf, Yv12BufferConfig* org_fts, const Yv12BufferConfig* src, |
52 | | Yv12BufferConfig* trial_frame_rst, PictureControlSet* pcs, uint32_t segment_index); |
53 | | void rest_finish_search(PictureControlSet* pcs); |
54 | | |
55 | 533 | static void rest_context_dctor(EbPtr p) { |
56 | 533 | EbThreadContext* thread_ctx = (EbThreadContext*)p; |
57 | 533 | RestContext* obj = (RestContext*)thread_ctx->priv; |
58 | 533 | EB_DELETE(obj->trial_frame_rst); |
59 | | // buffer only malloc'd if boundaries are used in rest. search. |
60 | | // see scs->seq_header.use_boundaries_in_rest_search |
61 | 533 | if (obj->org_rec_frame) { |
62 | 0 | EB_DELETE(obj->org_rec_frame); |
63 | 0 | } |
64 | 533 | EB_FREE_ALIGNED(obj->rst_tmpbuf); |
65 | 533 | EB_FREE_ARRAY(obj); |
66 | 533 | } |
67 | | |
68 | | /****************************************************** |
69 | | * Rest Context Constructor |
70 | | ******************************************************/ |
71 | | EbErrorType svt_aom_rest_context_ctor(EbThreadContext* thread_ctx, const EbEncHandle* enc_handle_ptr, int index, |
72 | 533 | int demux_index) { |
73 | 533 | const SequenceControlSet* scs = enc_handle_ptr->scs_instance->scs; |
74 | 533 | const EbSvtAv1EncConfiguration* config = &scs->static_config; |
75 | 533 | RestContext* context_ptr; |
76 | 533 | const bool allintra = scs->allintra; |
77 | 533 | const bool rtc_tune = scs->static_config.rtc; |
78 | 533 | EB_CALLOC_ARRAY(context_ptr, 1); |
79 | 533 | thread_ctx->priv = context_ptr; |
80 | 533 | thread_ctx->dctor = rest_context_dctor; |
81 | | |
82 | | // Input/Output System Resource Manager FIFOs |
83 | 533 | context_ptr->rest_input_fifo_ptr = svt_system_resource_get_consumer_fifo(enc_handle_ptr->cdef_results_resource_ptr, |
84 | 533 | index); |
85 | 533 | context_ptr->rest_output_fifo_ptr = svt_system_resource_get_producer_fifo(enc_handle_ptr->rest_results_resource_ptr, |
86 | 533 | index); |
87 | 533 | context_ptr->picture_demux_fifo_ptr = svt_system_resource_get_producer_fifo( |
88 | 533 | enc_handle_ptr->picture_demux_results_resource_ptr, demux_index); |
89 | | |
90 | 533 | bool is_16bit = scs->is_16bit_pipeline; |
91 | 533 | uint8_t enable_restoration = allintra |
92 | 533 | ? svt_aom_get_enable_restoration_allintra(config->enc_mode, config->enable_restoration_filtering) |
93 | 533 | : rtc_tune |
94 | 0 | #if TUNE_SIMPLIFY_SETTINGS |
95 | 0 | ? svt_aom_get_enable_restoration_rtc( |
96 | 0 | config->enable_restoration_filtering, scs->input_resolution, config->fast_decode) |
97 | | #else |
98 | | ? svt_aom_get_enable_restoration_rtc( |
99 | | config->enc_mode, config->enable_restoration_filtering, scs->input_resolution, config->fast_decode) |
100 | | #endif |
101 | 0 | : svt_aom_get_enable_restoration_default( |
102 | 0 | config->enc_mode, config->enable_restoration_filtering, scs->input_resolution, config->fast_decode); |
103 | | |
104 | 533 | #if FIX_MR_STILL_IMAGE |
105 | 533 | uint8_t enable_sg = allintra ? svt_aom_get_enable_sg_allintra(config->enc_mode) |
106 | | #else |
107 | | uint8_t enable_sg = allintra ? svt_aom_get_enable_sg_allintra() |
108 | | #endif |
109 | 533 | #if TUNE_SIMPLIFY_SETTINGS |
110 | 533 | : rtc_tune ? svt_aom_get_enable_sg_rtc(scs->input_resolution, config->fast_decode) |
111 | | #else |
112 | | : rtc_tune ? svt_aom_get_enable_sg_rtc(config->enc_mode, scs->input_resolution, config->fast_decode) |
113 | | #endif |
114 | 0 | : svt_aom_get_enable_sg_default(config->enc_mode, scs->input_resolution, config->fast_decode); |
115 | | |
116 | 533 | if (enable_restoration) { |
117 | 0 | EbPictureBufferDescInitData init_data; |
118 | |
|
119 | 0 | init_data.buffer_enable_mask = PICTURE_BUFFER_DESC_FULL_MASK; |
120 | 0 | init_data.max_width = (uint16_t)scs->max_input_luma_width; |
121 | 0 | init_data.max_height = (uint16_t)scs->max_input_luma_height; |
122 | 0 | init_data.bit_depth = is_16bit ? EB_SIXTEEN_BIT : EB_EIGHT_BIT; |
123 | 0 | init_data.color_format = config->encoder_color_format; |
124 | 0 | init_data.border = AOM_RESTORATION_FRAME_BORDER; |
125 | 0 | init_data.split_mode = false; |
126 | 0 | init_data.is_16bit_pipeline = is_16bit; |
127 | |
|
128 | 0 | EB_NEW(context_ptr->trial_frame_rst, svt_picture_buffer_desc_ctor, (EbPtr)&init_data); |
129 | 0 | if (scs->use_boundaries_in_rest_search) { |
130 | 0 | EB_NEW(context_ptr->org_rec_frame, svt_picture_buffer_desc_ctor, (EbPtr)&init_data); |
131 | 0 | } else { |
132 | 0 | context_ptr->org_rec_frame = NULL; |
133 | 0 | } |
134 | 0 | if (!is_16bit) { |
135 | 0 | context_ptr->trial_frame_rst->bit_depth = EB_EIGHT_BIT; |
136 | 0 | if (scs->use_boundaries_in_rest_search) { |
137 | 0 | context_ptr->org_rec_frame->bit_depth = EB_EIGHT_BIT; |
138 | 0 | } |
139 | 0 | } |
140 | 0 | context_ptr->rst_tmpbuf = NULL; |
141 | |
|
142 | 0 | if (enable_sg) { |
143 | 0 | EB_MALLOC_ALIGNED(context_ptr->rst_tmpbuf, RESTORATION_TMPBUF_SIZE); |
144 | 0 | } |
145 | 0 | } |
146 | | |
147 | 533 | return EB_ErrorNone; |
148 | 533 | } |
149 | | |
150 | | // If using boundaries during the filter search, copy the recon pic to a new buffer (to |
151 | | // avoid race conidition from many threads modifying the same recon pic). |
152 | | // |
153 | | // If not using boundaries during the filter search, return the input recon picture location |
154 | | // to be used in restoration search (save cycles/memory of copying pic to a new buffer). |
155 | | // The recon pic should not be modified during the search, otherwise there will be a race |
156 | | // condition between threads. |
157 | | // |
158 | | // Return a pointer to the recon pic to be used during the restoration search. |
159 | | static EbPictureBufferDesc* get_own_recon(SequenceControlSet* scs, PictureControlSet* pcs, RestContext* context_ptr, |
160 | 0 | bool is_16bit) { |
161 | 0 | EbPictureBufferDesc* recon_pic; |
162 | 0 | svt_aom_get_recon_pic(pcs, &recon_pic, is_16bit); |
163 | | // if boundaries are not used, don't need to copy pic to new buffer, as the |
164 | | // search will not modify the pic |
165 | 0 | if (!scs->use_boundaries_in_rest_search) { |
166 | 0 | return recon_pic; |
167 | 0 | } |
168 | | |
169 | 0 | const uint32_t ss_x = scs->subsampling_x; |
170 | 0 | const uint32_t ss_y = scs->subsampling_y; |
171 | |
|
172 | 0 | EbPictureBufferDesc* org_rec = context_ptr->org_rec_frame; |
173 | |
|
174 | 0 | int org_stride_y = org_rec->y_stride << is_16bit; |
175 | 0 | int org_stride_cb = org_rec->u_stride << is_16bit; |
176 | 0 | int org_stride_cr = org_rec->v_stride << is_16bit; |
177 | |
|
178 | 0 | int rec_stride_y = recon_pic->y_stride << is_16bit; |
179 | 0 | int rec_stride_cb = recon_pic->u_stride << is_16bit; |
180 | 0 | int rec_stride_cr = recon_pic->v_stride << is_16bit; |
181 | |
|
182 | 0 | uint8_t* org_ptr = org_rec->y_buffer; |
183 | 0 | uint8_t* org_ptr_cb = org_rec->u_buffer; |
184 | 0 | uint8_t* org_ptr_cr = org_rec->v_buffer; |
185 | |
|
186 | 0 | uint8_t* rec_ptr = recon_pic->y_buffer; |
187 | 0 | uint8_t* rec_ptr_cb = recon_pic->u_buffer; |
188 | 0 | uint8_t* rec_ptr_cr = recon_pic->v_buffer; |
189 | |
|
190 | 0 | int rec_width = recon_pic->width << is_16bit; |
191 | |
|
192 | 0 | for (int r = 0; r < recon_pic->height; ++r) { |
193 | 0 | svt_memcpy(org_ptr + r * org_stride_y, rec_ptr + r * rec_stride_y, rec_width); |
194 | 0 | } |
195 | |
|
196 | 0 | for (int r = 0; r < (recon_pic->height >> ss_y); ++r) { |
197 | 0 | svt_memcpy(org_ptr_cb + r * org_stride_cb, rec_ptr_cb + r * rec_stride_cb, rec_width >> ss_x); |
198 | 0 | svt_memcpy(org_ptr_cr + r * org_stride_cr, rec_ptr_cr + r * rec_stride_cr, rec_width >> ss_x); |
199 | 0 | } |
200 | 0 | return org_rec; |
201 | 0 | } |
202 | | |
203 | 0 | static void copy_statistics_to_ref_obj_ect(PictureControlSet* pcs, SequenceControlSet* scs) { |
204 | 0 | PictureParentControlSet* ppcs = pcs->ppcs; |
205 | 0 | FrameHeader* frm_hdr = &ppcs->frm_hdr; |
206 | 0 | EbReferenceObject* obj = (EbReferenceObject*)ppcs->ref_pic_wrapper->object_ptr; |
207 | |
|
208 | 0 | obj->intra_coded_area = (uint8_t)pcs->intra_coded_area; |
209 | 0 | obj->skip_coded_area = (uint8_t)pcs->skip_coded_area; |
210 | 0 | obj->hp_coded_area = (uint8_t)pcs->hp_coded_area; |
211 | 0 | obj->is_mfmv_used = frm_hdr->use_ref_frame_mvs; |
212 | |
|
213 | 0 | obj->filter_level[0] = frm_hdr->loop_filter_params.filter_level[0]; |
214 | 0 | obj->filter_level[1] = frm_hdr->loop_filter_params.filter_level[1]; |
215 | 0 | obj->filter_level_u = frm_hdr->loop_filter_params.filter_level_u; |
216 | 0 | obj->filter_level_v = frm_hdr->loop_filter_params.filter_level_v; |
217 | 0 | obj->dlf_dist_dev = pcs->dlf_dist_dev; |
218 | 0 | obj->cdef_dist_dev = pcs->cdef_dist_dev; |
219 | |
|
220 | 0 | obj->ref_cdef_strengths_num = ppcs->nb_cdef_strengths; |
221 | 0 | for (int i = 0; i < ppcs->nb_cdef_strengths; i++) { |
222 | 0 | obj->ref_cdef_strengths[0][i] = frm_hdr->cdef_params.cdef_y_strength[i]; |
223 | 0 | obj->ref_cdef_strengths[1][i] = frm_hdr->cdef_params.cdef_uv_strength[i]; |
224 | 0 | } |
225 | 0 | uint32_t sb_index; |
226 | 0 | for (sb_index = 0; sb_index < pcs->b64_total_count; ++sb_index) { |
227 | 0 | obj->sb_intra[sb_index] = pcs->sb_intra[sb_index]; |
228 | 0 | obj->sb_skip[sb_index] = pcs->sb_skip[sb_index]; |
229 | 0 | obj->sb_64x64_mvp[sb_index] = pcs->sb_64x64_mvp[sb_index]; |
230 | 0 | obj->sb_me_64x64_dist[sb_index] = ppcs->me_64x64_distortion[sb_index]; |
231 | 0 | obj->sb_me_8x8_cost_var[sb_index] = ppcs->me_8x8_cost_variance[sb_index]; |
232 | 0 | obj->sb_min_sq_size[sb_index] = pcs->sb_min_sq_size[sb_index]; |
233 | 0 | obj->sb_max_sq_size[sb_index] = pcs->sb_max_sq_size[sb_index]; |
234 | 0 | } |
235 | 0 | obj->tmp_layer_idx = pcs->temporal_layer_index; |
236 | 0 | obj->is_scene_change = ppcs->scene_change_flag; |
237 | |
|
238 | 0 | Av1Common* cm = ppcs->av1_cm; |
239 | 0 | if (scs->mfmv_enabled || !ppcs->is_not_scaled) { |
240 | 0 | obj->frame_type = frm_hdr->frame_type; |
241 | 0 | obj->order_hint = ppcs->cur_order_hint; |
242 | 0 | svt_memcpy(obj->ref_order_hint, ppcs->ref_order_hint, sizeof(obj->ref_order_hint)); |
243 | 0 | } |
244 | | // Copy the prev frame wn filter coeffs |
245 | 0 | if (cm->wn_filter_ctrls.enabled && cm->wn_filter_ctrls.use_prev_frame_coeffs) { |
246 | 0 | for (int32_t plane = 0; plane < MAX_PLANES; ++plane) { |
247 | 0 | int32_t ntiles = pcs->rst_info[plane].units_per_tile; |
248 | 0 | for (int32_t u = 0; u < ntiles; ++u) { |
249 | 0 | obj->unit_info[plane][u].restoration_type = pcs->rst_info[plane].unit_info[u].restoration_type; |
250 | 0 | if (pcs->rst_info[plane].unit_info[u].restoration_type == RESTORE_WIENER) { |
251 | 0 | obj->unit_info[plane][u].wiener_info = pcs->rst_info[plane].unit_info[u].wiener_info; |
252 | 0 | } |
253 | 0 | } |
254 | 0 | } |
255 | 0 | } |
256 | 0 | } |
257 | | |
258 | | /****************************************************** |
259 | | * Rest Kernel |
260 | | ******************************************************/ |
261 | 1.06k | EbErrorType svt_aom_rest_kernel_iter(void* context) { |
262 | 1.06k | RestContext* context_ptr = (RestContext*)context; |
263 | | |
264 | | // Get Cdef Results |
265 | 1.06k | EbObjectWrapper* cdef_results_wrapper; |
266 | 1.06k | EB_GET_FULL_OBJECT(context_ptr->rest_input_fifo_ptr, &cdef_results_wrapper); |
267 | | |
268 | 533 | CdefResults* cdef_results = (CdefResults*)cdef_results_wrapper->object_ptr; |
269 | 533 | PictureControlSet* pcs = (PictureControlSet*)cdef_results->pcs_wrapper->object_ptr; |
270 | 533 | PictureParentControlSet* ppcs = pcs->ppcs; |
271 | 533 | SequenceControlSet* scs = pcs->scs; |
272 | 533 | FrameHeader* frm_hdr = &ppcs->frm_hdr; |
273 | 533 | bool is_16bit = scs->is_16bit_pipeline; |
274 | 533 | Av1Common* cm = ppcs->av1_cm; |
275 | 533 | if (ppcs->enable_restoration && frm_hdr->allow_intrabc == 0) { |
276 | | // If using boundaries during the filter search, copy the recon pic to a new buffer (to |
277 | | // avoid race condition from many threads modifying the same recon pic). |
278 | | // |
279 | | // If not using boundaries during the filter search, copy the input recon picture |
280 | | // location to be used in restoration search (save cycles/memory of copying pic to a new |
281 | | // buffer). The recon pic should not be modified during the search, otherwise there will |
282 | | // be a race condition between threads. |
283 | 0 | EbPictureBufferDesc* recon_pic = get_own_recon(scs, pcs, context_ptr, is_16bit); |
284 | 0 | EbPictureBufferDesc* input_pic = is_16bit ? pcs->input_frame16bit : ppcs->enhanced_unscaled_pic; |
285 | | |
286 | | // downscale input picture if recon is resized |
287 | 0 | bool is_resized = recon_pic->width != input_pic->width || recon_pic->height != input_pic->height; |
288 | 0 | if (is_resized) { |
289 | 0 | input_pic = pcs->scaled_input_pic; |
290 | 0 | } |
291 | | |
292 | | // there are padding pixels if input pics are not 8 pixel aligned |
293 | | // but there is no extra padding after input pics are resized for |
294 | | // reference scaling |
295 | 0 | Yv12BufferConfig cpi_source; |
296 | 0 | svt_aom_link_eb_to_aom_buffer_desc(input_pic, |
297 | 0 | &cpi_source, |
298 | 0 | is_resized ? 0 : scs->max_input_pad_right, |
299 | 0 | is_resized ? 0 : scs->max_input_pad_bottom, |
300 | 0 | is_16bit); |
301 | |
|
302 | 0 | Yv12BufferConfig trial_frame_rst; |
303 | 0 | svt_aom_link_eb_to_aom_buffer_desc(context_ptr->trial_frame_rst, |
304 | 0 | &trial_frame_rst, |
305 | 0 | is_resized ? 0 : scs->max_input_pad_right, |
306 | 0 | is_resized ? 0 : scs->max_input_pad_bottom, |
307 | 0 | is_16bit); |
308 | |
|
309 | 0 | Yv12BufferConfig org_fts; |
310 | 0 | svt_aom_link_eb_to_aom_buffer_desc(recon_pic, |
311 | 0 | &org_fts, |
312 | 0 | is_resized ? 0 : scs->max_input_pad_right, |
313 | 0 | is_resized ? 0 : scs->max_input_pad_bottom, |
314 | 0 | is_16bit); |
315 | |
|
316 | 0 | if (ppcs->slice_type != I_SLICE && cm->wn_filter_ctrls.enabled && cm->wn_filter_ctrls.use_prev_frame_coeffs) { |
317 | 0 | EbReferenceObject* ref_obj_l0 = (EbReferenceObject*)pcs->ref_pic_ptr_array[REF_LIST_0][0]->object_ptr; |
318 | 0 | for (int32_t plane = 0; plane < MAX_PLANES; ++plane) { |
319 | 0 | int32_t ntiles = pcs->rst_info[plane].units_per_tile; |
320 | 0 | for (int32_t u = 0; u < ntiles; ++u) { |
321 | 0 | pcs->rst_info[plane].unit_info[u].restoration_type = |
322 | 0 | ref_obj_l0->unit_info[plane][u].restoration_type; |
323 | 0 | if (ref_obj_l0->unit_info[plane][u].restoration_type == RESTORE_WIENER) { |
324 | 0 | pcs->rst_info[plane].unit_info[u].wiener_info = ref_obj_l0->unit_info[plane][u].wiener_info; |
325 | 0 | } |
326 | 0 | } |
327 | 0 | } |
328 | 0 | } |
329 | 0 | restoration_seg_search( |
330 | 0 | context_ptr->rst_tmpbuf, &org_fts, &cpi_source, &trial_frame_rst, pcs, cdef_results->segment_index); |
331 | 0 | } |
332 | | |
333 | | //all seg based search is done. update total processed segments. if all done, finish the search and perfrom application. |
334 | 533 | svt_block_on_mutex(pcs->rest_search_mutex); |
335 | | |
336 | 533 | pcs->tot_seg_searched_rest++; |
337 | 533 | if (pcs->tot_seg_searched_rest == pcs->rest_segments_total_count) { |
338 | 533 | if (ppcs->enable_restoration && frm_hdr->allow_intrabc == 0) { |
339 | 0 | rest_finish_search(pcs); |
340 | | |
341 | | // Only need recon if REF pic or recon is output |
342 | 0 | if (ppcs->is_ref || scs->static_config.recon_enabled) { |
343 | 0 | if (pcs->rst_info[0].frame_restoration_type != RESTORE_NONE || |
344 | 0 | pcs->rst_info[1].frame_restoration_type != RESTORE_NONE || |
345 | 0 | pcs->rst_info[2].frame_restoration_type != RESTORE_NONE) { |
346 | 0 | svt_av1_loop_restoration_filter_frame(context_ptr->rst_tmpbuf, cm->frame_to_show, cm, 0); |
347 | 0 | } |
348 | 0 | } |
349 | 533 | } else { |
350 | 533 | pcs->rst_info[0].frame_restoration_type = RESTORE_NONE; |
351 | 533 | pcs->rst_info[1].frame_restoration_type = RESTORE_NONE; |
352 | 533 | pcs->rst_info[2].frame_restoration_type = RESTORE_NONE; |
353 | 533 | } |
354 | | |
355 | | // delete scaled_input_pic after lr finished |
356 | 533 | EB_DELETE(pcs->scaled_input_pic); |
357 | | |
358 | | // normalize stats - RC uses these even for non-ref frames |
359 | 533 | int num_pixels = ppcs->aligned_width * ppcs->aligned_height; |
360 | 533 | pcs->intra_coded_area = (pcs->slice_type == I_SLICE) ? 0 : 100 * pcs->intra_coded_area / num_pixels; |
361 | 533 | pcs->skip_coded_area = 100 * pcs->skip_coded_area / num_pixels; |
362 | 533 | pcs->hp_coded_area = 100 * pcs->hp_coded_area / num_pixels; |
363 | 533 | pcs->avg_cnt_zeromv = 100 * pcs->avg_cnt_zeromv / num_pixels; |
364 | | |
365 | 533 | if (ppcs->ref_pic_wrapper != NULL) { |
366 | | // copy stat to ref object (intra_coded_area, Luminance, Scene change detection |
367 | | // flags) |
368 | 0 | copy_statistics_to_ref_obj_ect(pcs, scs); |
369 | 0 | } |
370 | | |
371 | 533 | bool superres_recode = ppcs->superres_total_recode_loop > 0 ? true : false; |
372 | | |
373 | | // Pad the reference picture and set ref POC |
374 | 533 | { |
375 | 533 | if (ppcs->is_ref == true) { |
376 | 0 | pad_ref_and_set_flags(pcs, scs); |
377 | 533 | } else { |
378 | | // convert non-reference frame buffer from 16-bit to 8-bit, to export recon and |
379 | | // psnr/ssim calculation |
380 | 533 | if (is_16bit && scs->static_config.encoder_bit_depth == EB_EIGHT_BIT) { |
381 | 0 | EbPictureBufferDesc* ref_pic_ptr = ppcs->enc_dec_ptr->recon_pic; |
382 | 0 | EbPictureBufferDesc* ref_pic_16bit_ptr = ppcs->enc_dec_ptr->recon_pic_16bit; |
383 | | // Y |
384 | 0 | uint16_t* buf_16bit = (uint16_t*)(ref_pic_16bit_ptr->y_buffer) - |
385 | 0 | (ref_pic_16bit_ptr->border + (ref_pic_16bit_ptr->border * ref_pic_16bit_ptr->y_stride)); |
386 | 0 | uint8_t* buf_8bit = ref_pic_ptr->y_buffer - |
387 | 0 | (ref_pic_ptr->border + (ref_pic_ptr->border * ref_pic_ptr->y_stride)); |
388 | 0 | svt_convert_16bit_to_8bit(buf_16bit, |
389 | 0 | ref_pic_16bit_ptr->y_stride, |
390 | 0 | buf_8bit, |
391 | 0 | ref_pic_ptr->y_stride, |
392 | 0 | ref_pic_16bit_ptr->width + (ref_pic_ptr->border << 1), |
393 | 0 | ref_pic_16bit_ptr->height + (ref_pic_ptr->border << 1)); |
394 | | |
395 | | //CB |
396 | 0 | buf_16bit = (uint16_t*)(ref_pic_16bit_ptr->u_buffer) - |
397 | 0 | ((ref_pic_16bit_ptr->border >> scs->subsampling_x) + |
398 | 0 | ((ref_pic_16bit_ptr->border >> scs->subsampling_y) * ref_pic_16bit_ptr->u_stride)); |
399 | 0 | buf_8bit = ref_pic_ptr->u_buffer - |
400 | 0 | ((ref_pic_ptr->border >> scs->subsampling_x) + |
401 | 0 | ((ref_pic_ptr->border >> scs->subsampling_y) * ref_pic_ptr->u_stride)); |
402 | 0 | svt_convert_16bit_to_8bit( |
403 | 0 | buf_16bit, |
404 | 0 | ref_pic_16bit_ptr->u_stride, |
405 | 0 | buf_8bit, |
406 | 0 | ref_pic_ptr->u_stride, |
407 | 0 | (ref_pic_16bit_ptr->width + (ref_pic_ptr->border << 1)) >> scs->subsampling_x, |
408 | 0 | (ref_pic_16bit_ptr->height + (ref_pic_ptr->border << 1)) >> scs->subsampling_y); |
409 | | |
410 | | //CR |
411 | 0 | buf_16bit = (uint16_t*)(ref_pic_16bit_ptr->v_buffer) - |
412 | 0 | ((ref_pic_16bit_ptr->border >> scs->subsampling_x) + |
413 | 0 | ((ref_pic_16bit_ptr->border >> scs->subsampling_y) * ref_pic_16bit_ptr->v_stride)); |
414 | 0 | buf_8bit = ref_pic_ptr->v_buffer - |
415 | 0 | ((ref_pic_ptr->border >> scs->subsampling_x) + |
416 | 0 | ((ref_pic_ptr->border >> scs->subsampling_y) * ref_pic_ptr->v_stride)); |
417 | 0 | svt_convert_16bit_to_8bit( |
418 | 0 | buf_16bit, |
419 | 0 | ref_pic_16bit_ptr->v_stride, |
420 | 0 | buf_8bit, |
421 | 0 | ref_pic_ptr->v_stride, |
422 | 0 | (ref_pic_16bit_ptr->width + (ref_pic_ptr->border << 1)) >> scs->subsampling_x, |
423 | 0 | (ref_pic_16bit_ptr->height + (ref_pic_ptr->border << 1)) >> scs->subsampling_y); |
424 | 0 | } |
425 | 533 | } |
426 | 533 | } |
427 | | |
428 | | // PSNR and SSIM Calculation. |
429 | 533 | if (superres_recode) { // superres needs psnr to compute rdcost |
430 | | // Note: if superres recode is actived, memory needs to be freed in packetization process by calling free_temporal_filtering_buffer() |
431 | 0 | EbErrorType return_error = psnr_calculations(pcs, scs, false); |
432 | 0 | if (return_error != EB_ErrorNone) { |
433 | 0 | svt_aom_assert_err(0, |
434 | 0 | "Couldn't allocate memory for uncompressed 10bit buffers for PSNR " |
435 | 0 | "calculations"); |
436 | 0 | } |
437 | 533 | } else { |
438 | 533 | EbErrorType return_error; |
439 | 533 | if (pcs->ppcs->compute_psnr) { |
440 | | // Note: if temporal_filtering is used, memory needs to be freed in the last of these calls |
441 | 0 | return_error = psnr_calculations(pcs, scs, !pcs->ppcs->compute_ssim); |
442 | 0 | if (return_error != EB_ErrorNone) { |
443 | 0 | svt_aom_assert_err(0, |
444 | 0 | "Couldn't allocate memory for uncompressed 10bit buffers for PSNR " |
445 | 0 | "calculations"); |
446 | 0 | } |
447 | 0 | } |
448 | 533 | if (pcs->ppcs->compute_ssim) { |
449 | 0 | return_error = svt_aom_ssim_calculations(pcs, scs, true /* free memory here */); |
450 | 0 | if (return_error != EB_ErrorNone) { |
451 | 0 | svt_aom_assert_err(0, |
452 | 0 | "Couldn't allocate memory for uncompressed 10bit buffers for SSIM " |
453 | 0 | "calculations"); |
454 | 0 | } |
455 | 0 | } |
456 | 533 | } |
457 | | |
458 | 533 | if (!superres_recode) { |
459 | 533 | if (scs->static_config.recon_enabled) { |
460 | 0 | svt_aom_recon_output(pcs, scs); |
461 | 0 | } |
462 | | // post reference picture task in packetization process if it's superres_recode |
463 | 533 | if (ppcs->is_ref) { |
464 | | // Get Empty PicMgr Results |
465 | 0 | EbObjectWrapper* picture_demux_results_wrapper_ptr; |
466 | 0 | svt_get_empty_object(context_ptr->picture_demux_fifo_ptr, &picture_demux_results_wrapper_ptr); |
467 | |
|
468 | 0 | PictureDemuxResults* picture_demux_results_rtr = (PictureDemuxResults*) |
469 | 0 | picture_demux_results_wrapper_ptr->object_ptr; |
470 | 0 | picture_demux_results_rtr->ref_pic_wrapper = ppcs->ref_pic_wrapper; |
471 | 0 | picture_demux_results_rtr->scs = pcs->scs; |
472 | 0 | picture_demux_results_rtr->picture_number = pcs->picture_number; |
473 | 0 | picture_demux_results_rtr->picture_type = EB_PIC_REFERENCE; |
474 | | |
475 | | // Post Reference Picture |
476 | 0 | svt_post_full_object(picture_demux_results_wrapper_ptr); |
477 | 0 | } |
478 | 533 | } |
479 | | |
480 | 533 | int tile_cols = ppcs->av1_cm->tiles_info.tile_cols; |
481 | 533 | int tile_rows = ppcs->av1_cm->tiles_info.tile_rows; |
482 | | |
483 | 2.22k | for (int tile_row_idx = 0; tile_row_idx < tile_rows; tile_row_idx++) { |
484 | 7.36k | for (int tile_col_idx = 0; tile_col_idx < tile_cols; tile_col_idx++) { |
485 | 5.67k | const int tile_idx = tile_row_idx * tile_cols + tile_col_idx; |
486 | 5.67k | EbObjectWrapper* rest_results_wrapper; |
487 | 5.67k | svt_get_empty_object(context_ptr->rest_output_fifo_ptr, &rest_results_wrapper); |
488 | 5.67k | RestResults* rest_results = (RestResults*)rest_results_wrapper->object_ptr; |
489 | 5.67k | rest_results->pcs_wrapper = cdef_results->pcs_wrapper; |
490 | 5.67k | rest_results->tile_index = tile_idx; |
491 | | // Post Rest Results |
492 | 5.67k | svt_post_full_object(rest_results_wrapper); |
493 | 5.67k | } |
494 | 1.68k | } |
495 | 533 | } |
496 | 533 | svt_release_mutex(pcs->rest_search_mutex); |
497 | | |
498 | | // Release input Results |
499 | 533 | svt_release_object(cdef_results_wrapper); |
500 | 533 | return EB_ErrorNone; |
501 | 1.06k | } |
502 | | |
503 | 533 | void* svt_aom_rest_kernel(void* input_ptr) { |
504 | 533 | EbThreadContext* thread_ctx = (EbThreadContext*)input_ptr; |
505 | 1.06k | for (;;) { |
506 | 1.06k | EbErrorType err = svt_aom_rest_kernel_iter(thread_ctx->priv); |
507 | 1.06k | if (err == EB_NoErrorFifoShutdown) { |
508 | 533 | return NULL; |
509 | 533 | } |
510 | 1.06k | } |
511 | 0 | return NULL; |
512 | 533 | } |