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 "EbEncHandle.h"
16 #include "EbRestProcess.h"
17 #include "EbEncDecResults.h"
18 #include "EbThreads.h"
19 #include "EbPictureDemuxResults.h"
20 #include "EbReferenceObject.h"
21 #include "EbPictureControlSet.h"
22
23
24
25 /**************************************
26 * Rest Context
27 **************************************/
28 typedef struct RestContext {
29 EbDctor dctor;
30 EbFifo *rest_input_fifo_ptr;
31 EbFifo *rest_output_fifo_ptr;
32 EbFifo *picture_demux_fifo_ptr;
33
34 EbPictureBufferDesc *trial_frame_rst;
35
36 EbPictureBufferDesc *
37 org_rec_frame; // while doing the filtering recon gets updated uisng setup/restore processing_stripe_bounadaries
38 // many threads doing the above will result in race condition.
39 // each thread will hence have his own copy of recon to work on.
40 // later we can have a search version that does not need the exact right recon
41 int32_t *rst_tmpbuf;
42 } RestContext;
43
44 void pack_highbd_pic(const EbPictureBufferDesc *pic_ptr, uint16_t *buffer_16bit[3], uint32_t ss_x,
45 uint32_t ss_y, EbBool include_padding);
46 void copy_buffer_info(EbPictureBufferDesc *src_ptr, EbPictureBufferDesc *dst_ptr);
47 void recon_output(PictureControlSet *pcs_ptr, SequenceControlSet *scs_ptr);
48 void svt_av1_loop_restoration_filter_frame(Yv12BufferConfig *frame, Av1Common *cm,
49 int32_t optimized_lr);
50 void copy_statistics_to_ref_obj_ect(PictureControlSet *pcs_ptr, SequenceControlSet *scs_ptr);
51 void psnr_calculations(PictureControlSet *pcs_ptr, SequenceControlSet *scs_ptr, EbBool free_memory);
52 void ssim_calculations(PictureControlSet *pcs_ptr, SequenceControlSet *scs_ptr, EbBool free_memory);
53 void pad_ref_and_set_flags(PictureControlSet *pcs_ptr, SequenceControlSet *scs_ptr);
54 void generate_padding(EbByte src_pic, uint32_t src_stride, uint32_t original_src_width,
55 uint32_t original_src_height, uint32_t padding_width,
56 uint32_t padding_height);
57 void restoration_seg_search(int32_t *rst_tmpbuf, Yv12BufferConfig *org_fts,
58 const Yv12BufferConfig *src, Yv12BufferConfig *trial_frame_rst,
59 PictureControlSet *pcs_ptr, uint32_t segment_index);
60 void rest_finish_search(PictureControlSet *pcs_ptr);
61 void svt_av1_upscale_normative_rows(const Av1Common *cm, const uint8_t *src, int src_stride,
62 uint8_t *dst, int dst_stride, int rows, int sub_x, int bd,
63 EbBool is_16bit_pipeline);
64
65 #if DEBUG_UPSCALING
66 void save_YUV_to_file(char *filename, EbByte buffer_y, EbByte buffer_u, EbByte buffer_v,
67 uint16_t width, uint16_t height, uint16_t stride_y, uint16_t stride_u,
68 uint16_t stride_v, uint16_t origin_y, uint16_t origin_x, uint32_t ss_x,
69 uint32_t ss_y);
70 #endif
71
rest_context_dctor(EbPtr p)72 static void rest_context_dctor(EbPtr p) {
73 EbThreadContext *thread_context_ptr = (EbThreadContext *)p;
74 RestContext * obj = (RestContext *)thread_context_ptr->priv;
75 EB_DELETE(obj->trial_frame_rst);
76 // buffer only malloc'd if boundaries are used in rest. search.
77 // see scs_ptr->seq_header.use_boundaries_in_rest_search
78 if (obj->org_rec_frame)
79 EB_DELETE(obj->org_rec_frame);
80 EB_FREE_ALIGNED(obj->rst_tmpbuf);
81 EB_FREE_ARRAY(obj);
82 }
83
84 /******************************************************
85 * Rest Context Constructor
86 ******************************************************/
rest_context_ctor(EbThreadContext * thread_context_ptr,const EbEncHandle * enc_handle_ptr,int index,int demux_index)87 EbErrorType rest_context_ctor(EbThreadContext * thread_context_ptr,
88 const EbEncHandle *enc_handle_ptr, int index, int demux_index) {
89 const SequenceControlSet * scs_ptr = enc_handle_ptr->scs_instance_array[0]->scs_ptr;
90 const EbSvtAv1EncConfiguration *config = &scs_ptr->static_config;
91 EbBool is_16bit = (EbBool)(config->encoder_bit_depth > EB_8BIT);
92 EbColorFormat color_format = config->encoder_color_format;
93
94 RestContext *context_ptr;
95 EB_CALLOC_ARRAY(context_ptr, 1);
96 thread_context_ptr->priv = context_ptr;
97 thread_context_ptr->dctor = rest_context_dctor;
98
99 // Input/Output System Resource Manager FIFOs
100 context_ptr->rest_input_fifo_ptr = svt_system_resource_get_consumer_fifo(
101 enc_handle_ptr->cdef_results_resource_ptr, index);
102 context_ptr->rest_output_fifo_ptr = svt_system_resource_get_producer_fifo(
103 enc_handle_ptr->rest_results_resource_ptr, index);
104 context_ptr->picture_demux_fifo_ptr = svt_system_resource_get_producer_fifo(
105 enc_handle_ptr->picture_demux_results_resource_ptr, demux_index);
106
107 {
108 EbPictureBufferDescInitData init_data;
109
110 init_data.buffer_enable_mask = PICTURE_BUFFER_DESC_FULL_MASK;
111 init_data.max_width = (uint16_t)scs_ptr->max_input_luma_width;
112 init_data.max_height = (uint16_t)scs_ptr->max_input_luma_height;
113 init_data.bit_depth = config->is_16bit_pipeline || is_16bit ? EB_16BIT : EB_8BIT;
114 init_data.color_format = color_format;
115 init_data.left_padding = AOM_BORDER_IN_PIXELS;
116 init_data.right_padding = AOM_BORDER_IN_PIXELS;
117 init_data.top_padding = AOM_BORDER_IN_PIXELS;
118 init_data.bot_padding = AOM_BORDER_IN_PIXELS;
119 init_data.split_mode = EB_FALSE;
120 init_data.is_16bit_pipeline = config->is_16bit_pipeline;
121
122 EB_NEW(context_ptr->trial_frame_rst, svt_picture_buffer_desc_ctor, (EbPtr)&init_data);
123 if (scs_ptr->use_boundaries_in_rest_search)
124 EB_NEW(context_ptr->org_rec_frame, svt_picture_buffer_desc_ctor, (EbPtr)&init_data);
125 else
126 context_ptr->org_rec_frame = NULL;
127 if (!is_16bit) {
128 context_ptr->trial_frame_rst->bit_depth = EB_8BIT;
129 if (scs_ptr->use_boundaries_in_rest_search)
130 context_ptr->org_rec_frame->bit_depth = EB_8BIT;
131 }
132
133 EB_MALLOC_ALIGNED(context_ptr->rst_tmpbuf, RESTORATION_TMPBUF_SIZE);
134 }
135
136 return EB_ErrorNone;
137 }
138 // If using boundaries during the filter search, copy the recon pic to a new buffer (to
139 // avoid race conidition from many threads modifying the same recon pic).
140 //
141 // If not using boundaries during the filter search, return the input recon picture location
142 // to be used in restoration search (save cycles/memory of copying pic to a new buffer).
143 // The recon pic should not be modified during the search, otherwise there will be a race
144 // condition between threads.
145 //
146 // Return a pointer to the recon pic to be used during the restoration search.
get_own_recon(SequenceControlSet * scs_ptr,PictureControlSet * pcs_ptr,RestContext * context_ptr,EbBool is_16bit)147 EbPictureBufferDesc* get_own_recon(SequenceControlSet *scs_ptr, PictureControlSet *pcs_ptr,
148 RestContext *context_ptr, EbBool is_16bit) {
149
150 Av1Common* cm = pcs_ptr->parent_pcs_ptr->av1_cm;
151 cm->use_boundaries_in_rest_search = scs_ptr->use_boundaries_in_rest_search;
152 const uint32_t ss_x = scs_ptr->subsampling_x;
153 const uint32_t ss_y = scs_ptr->subsampling_y;
154
155 EbPictureBufferDesc *recon_picture_ptr;
156 if (is_16bit) {
157 if (pcs_ptr->parent_pcs_ptr->is_used_as_reference_flag == EB_TRUE)
158 recon_picture_ptr = ((EbReferenceObject *)pcs_ptr->parent_pcs_ptr
159 ->reference_picture_wrapper_ptr->object_ptr)
160 ->reference_picture16bit;
161 else
162 recon_picture_ptr = pcs_ptr->parent_pcs_ptr->enc_dec_ptr->recon_picture16bit_ptr;
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 if (!scs_ptr->use_boundaries_in_rest_search) {
166 return recon_picture_ptr;
167 }
168 uint16_t *rec_ptr = (uint16_t *)recon_picture_ptr->buffer_y + recon_picture_ptr->origin_x +
169 recon_picture_ptr->origin_y * recon_picture_ptr->stride_y;
170 uint16_t *rec_ptr_cb = (uint16_t *)recon_picture_ptr->buffer_cb +
171 recon_picture_ptr->origin_x / 2 +
172 recon_picture_ptr->origin_y / 2 * recon_picture_ptr->stride_cb;
173 uint16_t *rec_ptr_cr = (uint16_t *)recon_picture_ptr->buffer_cr +
174 recon_picture_ptr->origin_x / 2 +
175 recon_picture_ptr->origin_y / 2 * recon_picture_ptr->stride_cr;
176
177 EbPictureBufferDesc *org_rec = context_ptr->org_rec_frame;
178 uint16_t * org_ptr = (uint16_t *)org_rec->buffer_y + org_rec->origin_x +
179 org_rec->origin_y * org_rec->stride_y;
180 uint16_t *org_ptr_cb = (uint16_t *)org_rec->buffer_cb + org_rec->origin_x / 2 +
181 org_rec->origin_y / 2 * org_rec->stride_cb;
182 uint16_t *org_ptr_cr = (uint16_t *)org_rec->buffer_cr + org_rec->origin_x / 2 +
183 org_rec->origin_y / 2 * org_rec->stride_cr;
184
185 for (int r = 0; r < recon_picture_ptr->height; ++r)
186 svt_memcpy(org_ptr + r * org_rec->stride_y,
187 rec_ptr + r * recon_picture_ptr->stride_y,
188 recon_picture_ptr->width << 1);
189
190 for (int r = 0; r < (recon_picture_ptr->height >> ss_y); ++r) {
191 svt_memcpy(org_ptr_cb + r * org_rec->stride_cb,
192 rec_ptr_cb + r * recon_picture_ptr->stride_cb,
193 (recon_picture_ptr->width >> ss_x) << 1);
194 svt_memcpy(org_ptr_cr + r * org_rec->stride_cr,
195 rec_ptr_cr + r * recon_picture_ptr->stride_cr,
196 (recon_picture_ptr->width >> ss_x) << 1);
197 }
198 } else {
199 if (pcs_ptr->parent_pcs_ptr->is_used_as_reference_flag == EB_TRUE)
200 recon_picture_ptr = ((EbReferenceObject *)pcs_ptr->parent_pcs_ptr
201 ->reference_picture_wrapper_ptr->object_ptr)
202 ->reference_picture;
203 else
204 recon_picture_ptr = pcs_ptr->parent_pcs_ptr->enc_dec_ptr->recon_picture_ptr; //OMK
205 // if boundaries are not used, don't need to copy pic to new buffer, as the
206 // search will not modify the pic
207 if (!scs_ptr->use_boundaries_in_rest_search) {
208 return recon_picture_ptr;
209 }
210 uint8_t *rec_ptr = &((recon_picture_ptr->buffer_y)[recon_picture_ptr->origin_x +
211 recon_picture_ptr->origin_y *
212 recon_picture_ptr->stride_y]);
213 uint8_t *rec_ptr_cb = &((recon_picture_ptr->buffer_cb)[recon_picture_ptr->origin_x / 2 +
214 recon_picture_ptr->origin_y / 2 *
215 recon_picture_ptr->stride_cb]);
216 uint8_t *rec_ptr_cr = &((recon_picture_ptr->buffer_cr)[recon_picture_ptr->origin_x / 2 +
217 recon_picture_ptr->origin_y / 2 *
218 recon_picture_ptr->stride_cr]);
219
220 EbPictureBufferDesc *org_rec = context_ptr->org_rec_frame;
221 uint8_t * org_ptr = &(
222 (org_rec->buffer_y)[org_rec->origin_x + org_rec->origin_y * org_rec->stride_y]);
223 uint8_t *org_ptr_cb = &((org_rec->buffer_cb)[org_rec->origin_x / 2 +
224 org_rec->origin_y / 2 * org_rec->stride_cb]);
225 uint8_t *org_ptr_cr = &((org_rec->buffer_cr)[org_rec->origin_x / 2 +
226 org_rec->origin_y / 2 * org_rec->stride_cr]);
227
228 for (int r = 0; r < recon_picture_ptr->height; ++r)
229 svt_memcpy(org_ptr + r * org_rec->stride_y,
230 rec_ptr + r * recon_picture_ptr->stride_y,
231 recon_picture_ptr->width);
232
233 for (int r = 0; r < (recon_picture_ptr->height >> ss_y); ++r) {
234 svt_memcpy(org_ptr_cb + r * org_rec->stride_cb,
235 rec_ptr_cb + r * recon_picture_ptr->stride_cb,
236 (recon_picture_ptr->width >> ss_x));
237 svt_memcpy(org_ptr_cr + r * org_rec->stride_cr,
238 rec_ptr_cr + r * recon_picture_ptr->stride_cr,
239 (recon_picture_ptr->width >> ss_x));
240 }
241 }
242 return context_ptr->org_rec_frame;
243 }
244
set_unscaled_input_16bit(PictureControlSet * pcs_ptr)245 void set_unscaled_input_16bit(PictureControlSet *pcs_ptr) {
246 uint16_t *unscaled_input_frame16bit[MAX_MB_PLANE];
247 unscaled_input_frame16bit[0] = (uint16_t *)pcs_ptr->input_frame16bit->buffer_y;
248 unscaled_input_frame16bit[1] = (uint16_t *)pcs_ptr->input_frame16bit->buffer_cb;
249 unscaled_input_frame16bit[2] = (uint16_t *)pcs_ptr->input_frame16bit->buffer_cr;
250
251 pack_highbd_pic(pcs_ptr->parent_pcs_ptr->enhanced_unscaled_picture_ptr,
252 unscaled_input_frame16bit,
253 1,
254 1,
255 EB_TRUE);
256 copy_buffer_info(pcs_ptr->parent_pcs_ptr->enhanced_unscaled_picture_ptr,
257 pcs_ptr->input_frame16bit);
258 }
259
derive_blk_pointers_enc(EbPictureBufferDesc * recon_picture_buf,int32_t plane,int32_t blk_col_px,int32_t blk_row_px,void ** pp_blk_recon_buf,int32_t * recon_stride,int32_t sub_x,int32_t sub_y)260 void derive_blk_pointers_enc(EbPictureBufferDesc *recon_picture_buf, int32_t plane,
261 int32_t blk_col_px, int32_t blk_row_px, void **pp_blk_recon_buf,
262 int32_t *recon_stride, int32_t sub_x, int32_t sub_y) {
263 int32_t block_offset;
264
265 if (plane == 0) {
266 block_offset = (recon_picture_buf->origin_y + blk_row_px) * recon_picture_buf->stride_y +
267 (recon_picture_buf->origin_x + blk_col_px);
268 *recon_stride = recon_picture_buf->stride_y;
269 } else if (plane == 1) {
270 block_offset = ((recon_picture_buf->origin_y >> sub_y) + blk_row_px) *
271 recon_picture_buf->stride_cb +
272 ((recon_picture_buf->origin_x >> sub_x) + blk_col_px);
273 *recon_stride = recon_picture_buf->stride_cb;
274 } else {
275 block_offset = ((recon_picture_buf->origin_y >> sub_y) + blk_row_px) *
276 recon_picture_buf->stride_cr +
277 ((recon_picture_buf->origin_x >> sub_x) + blk_col_px);
278 *recon_stride = recon_picture_buf->stride_cr;
279 }
280
281 if (recon_picture_buf->bit_depth != EB_8BIT) { //16bit
282 if (plane == 0)
283 *pp_blk_recon_buf = (void *)((uint16_t *)recon_picture_buf->buffer_y + block_offset);
284 else if (plane == 1)
285 *pp_blk_recon_buf = (void *)((uint16_t *)recon_picture_buf->buffer_cb + block_offset);
286 else
287 *pp_blk_recon_buf = (void *)((uint16_t *)recon_picture_buf->buffer_cr + block_offset);
288 } else {
289 if (plane == 0)
290 *pp_blk_recon_buf = (void *)((uint8_t *)recon_picture_buf->buffer_y + block_offset);
291 else if (plane == 1)
292 *pp_blk_recon_buf = (void *)((uint8_t *)recon_picture_buf->buffer_cb + block_offset);
293 else
294 *pp_blk_recon_buf = (void *)((uint8_t *)recon_picture_buf->buffer_cr + block_offset);
295 }
296 }
297
copy_recon_enc(SequenceControlSet * scs_ptr,EbPictureBufferDesc * recon_picture_src,EbPictureBufferDesc * recon_picture_dst,int num_planes,int skip_copy)298 EbErrorType copy_recon_enc(SequenceControlSet *scs_ptr, EbPictureBufferDesc *recon_picture_src,
299 EbPictureBufferDesc *recon_picture_dst, int num_planes, int skip_copy) {
300 recon_picture_dst->origin_x = recon_picture_src->origin_x;
301 recon_picture_dst->origin_y = recon_picture_src->origin_y;
302 recon_picture_dst->width = recon_picture_src->width;
303 recon_picture_dst->height = recon_picture_src->height;
304 recon_picture_dst->max_width = recon_picture_src->max_width;
305 recon_picture_dst->max_height = recon_picture_src->max_height;
306 recon_picture_dst->bit_depth = recon_picture_src->bit_depth;
307 recon_picture_dst->color_format = recon_picture_src->color_format;
308
309 recon_picture_dst->stride_y = recon_picture_src->stride_y;
310 recon_picture_dst->stride_cb = recon_picture_src->stride_cb;
311 recon_picture_dst->stride_cr = recon_picture_src->stride_cr;
312
313 recon_picture_dst->luma_size = recon_picture_src->luma_size;
314 recon_picture_dst->chroma_size = recon_picture_src->chroma_size;
315 recon_picture_dst->packed_flag = recon_picture_src->packed_flag;
316
317 recon_picture_dst->stride_bit_inc_y = recon_picture_src->stride_bit_inc_y;
318 recon_picture_dst->stride_bit_inc_cb = recon_picture_src->stride_bit_inc_cb;
319 recon_picture_dst->stride_bit_inc_cr = recon_picture_src->stride_bit_inc_cr;
320
321 recon_picture_dst->buffer_enable_mask = scs_ptr->seq_header.color_config.mono_chrome
322 ? PICTURE_BUFFER_DESC_LUMA_MASK
323 : PICTURE_BUFFER_DESC_FULL_MASK;
324
325 uint32_t bytesPerPixel = (recon_picture_dst->bit_depth == EB_8BIT) ? 1 : 2;
326
327 // Allocate the Picture Buffers (luma & chroma)
328 if (recon_picture_dst->buffer_enable_mask & PICTURE_BUFFER_DESC_Y_FLAG) {
329 EB_MALLOC_ALIGNED(recon_picture_dst->buffer_y,
330 recon_picture_dst->luma_size * bytesPerPixel);
331 memset(recon_picture_dst->buffer_y, 0, recon_picture_dst->luma_size * bytesPerPixel);
332 } else
333 recon_picture_dst->buffer_y = 0;
334 if (recon_picture_dst->buffer_enable_mask & PICTURE_BUFFER_DESC_Cb_FLAG) {
335 EB_MALLOC_ALIGNED(recon_picture_dst->buffer_cb,
336 recon_picture_dst->chroma_size * bytesPerPixel);
337 memset(recon_picture_dst->buffer_cb, 0, recon_picture_dst->chroma_size * bytesPerPixel);
338 } else
339 recon_picture_dst->buffer_cb = 0;
340 if (recon_picture_dst->buffer_enable_mask & PICTURE_BUFFER_DESC_Cr_FLAG) {
341 EB_MALLOC_ALIGNED(recon_picture_dst->buffer_cr,
342 recon_picture_dst->chroma_size * bytesPerPixel);
343 memset(recon_picture_dst->buffer_cr, 0, recon_picture_dst->chroma_size * bytesPerPixel);
344 } else
345 recon_picture_dst->buffer_cr = 0;
346
347 int use_highbd = (scs_ptr->static_config.encoder_bit_depth > 8);
348
349 if (!skip_copy) {
350 for (int plane = 0; plane < num_planes; ++plane) {
351 uint8_t *src_buf, *dst_buf;
352 int32_t src_stride, dst_stride;
353
354 int sub_x = plane ? scs_ptr->subsampling_x : 0;
355 int sub_y = plane ? scs_ptr->subsampling_y : 0;
356
357 derive_blk_pointers_enc(
358 recon_picture_src, plane, 0, 0, (void *)&src_buf, &src_stride, sub_x, sub_y);
359 derive_blk_pointers_enc(
360 recon_picture_dst, plane, 0, 0, (void *)&dst_buf, &dst_stride, sub_x, sub_y);
361
362 int height = (recon_picture_src->height >> sub_y);
363 for (int row = 0; row < height; ++row) {
364 svt_memcpy(dst_buf,
365 src_buf,
366 (recon_picture_src->width >> sub_x) * sizeof(*src_buf) << use_highbd);
367 src_buf += src_stride << use_highbd;
368 dst_buf += dst_stride << use_highbd;
369 }
370 }
371 }
372
373 return EB_ErrorNone;
374 }
375
get_recon_pic(PictureControlSet * pcs_ptr,EbPictureBufferDesc ** recon_ptr,EbBool is_highbd)376 void get_recon_pic(PictureControlSet *pcs_ptr, EbPictureBufferDesc **recon_ptr, EbBool is_highbd) {
377 if (!is_highbd) {
378 if (pcs_ptr->parent_pcs_ptr->is_used_as_reference_flag == EB_TRUE)
379 *recon_ptr = ((EbReferenceObject *)
380 pcs_ptr->parent_pcs_ptr->reference_picture_wrapper_ptr->object_ptr)
381 ->reference_picture;
382 else
383 *recon_ptr = pcs_ptr->parent_pcs_ptr->enc_dec_ptr->recon_picture_ptr; //OMK
384 } else {
385 if (pcs_ptr->parent_pcs_ptr->is_used_as_reference_flag == EB_TRUE)
386 *recon_ptr = ((EbReferenceObject *)
387 pcs_ptr->parent_pcs_ptr->reference_picture_wrapper_ptr->object_ptr)
388 ->reference_picture16bit;
389 else
390 *recon_ptr = pcs_ptr->parent_pcs_ptr->enc_dec_ptr->recon_picture16bit_ptr;
391 }
392 }
393
svt_av1_superres_upscale_frame(struct Av1Common * cm,PictureControlSet * pcs_ptr,SequenceControlSet * scs_ptr)394 void svt_av1_superres_upscale_frame(struct Av1Common *cm, PictureControlSet *pcs_ptr,
395 SequenceControlSet *scs_ptr) {
396 // Set these parameters for testing since they are not correctly populated yet
397 EbPictureBufferDesc *recon_ptr;
398
399 EbBool is_16bit = (EbBool)(scs_ptr->static_config.encoder_bit_depth > EB_8BIT) ||
400 (scs_ptr->static_config.is_16bit_pipeline);
401
402 get_recon_pic(pcs_ptr, &recon_ptr, is_16bit);
403
404 uint16_t ss_x = scs_ptr->subsampling_x;
405 uint16_t ss_y = scs_ptr->subsampling_y;
406 const int num_planes = scs_ptr->seq_header.color_config.mono_chrome ? 1 : MAX_MB_PLANE;
407
408 EbPictureBufferDesc recon_pic_temp;
409 EbPictureBufferDesc *ps_recon_pic_temp;
410 ps_recon_pic_temp = &recon_pic_temp;
411
412 EbErrorType return_error = copy_recon_enc(scs_ptr, recon_ptr, ps_recon_pic_temp, num_planes, 0);
413
414 if (return_error != EB_ErrorNone) {
415 ps_recon_pic_temp = NULL;
416 assert(0);
417 }
418
419 EbPictureBufferDesc *src = ps_recon_pic_temp;
420 EbPictureBufferDesc *dst = recon_ptr;
421
422 // get the bit-depth from the encoder config instead of from the recon ptr
423 int bit_depth = scs_ptr->static_config.encoder_bit_depth;
424
425 for (int plane = 0; plane < num_planes; ++plane) {
426 uint8_t *src_buf, *dst_buf;
427 int32_t src_stride, dst_stride;
428
429 int sub_x = plane ? ss_x : 0;
430 int sub_y = plane ? ss_y : 0;
431 derive_blk_pointers_enc(src, plane, 0, 0, (void *)&src_buf, &src_stride, sub_x, sub_y);
432 derive_blk_pointers_enc(dst, plane, 0, 0, (void *)&dst_buf, &dst_stride, sub_x, sub_y);
433
434 svt_av1_upscale_normative_rows(cm,
435 (const uint8_t *)src_buf,
436 src_stride,
437 dst_buf,
438 dst_stride,
439 src->height >> sub_x,
440 sub_x,
441 bit_depth,
442 is_16bit);
443 }
444
445 // free the memory
446 EB_FREE_ALIGNED_ARRAY(ps_recon_pic_temp->buffer_y);
447 EB_FREE_ALIGNED_ARRAY(ps_recon_pic_temp->buffer_cb);
448 EB_FREE_ALIGNED_ARRAY(ps_recon_pic_temp->buffer_cr);
449 }
450
451 /******************************************************
452 * Rest Kernel
453 ******************************************************/
rest_kernel(void * input_ptr)454 void *rest_kernel(void *input_ptr) {
455 // Context & SCS & PCS
456 EbThreadContext * thread_context_ptr = (EbThreadContext *)input_ptr;
457 RestContext * context_ptr = (RestContext *)thread_context_ptr->priv;
458 PictureControlSet * pcs_ptr;
459 SequenceControlSet *scs_ptr;
460
461 //// Input
462 EbObjectWrapper *cdef_results_wrapper_ptr;
463 CdefResults * cdef_results_ptr;
464
465 //// Output
466 EbObjectWrapper * rest_results_wrapper_ptr;
467 RestResults * rest_results_ptr;
468 EbObjectWrapper * picture_demux_results_wrapper_ptr;
469 PictureDemuxResults *picture_demux_results_rtr;
470 // SB Loop variables
471 uint8_t tile_cols;
472 uint8_t tile_rows;
473
474 for (;;) {
475 // Get Cdef Results
476 EB_GET_FULL_OBJECT(context_ptr->rest_input_fifo_ptr, &cdef_results_wrapper_ptr);
477
478 cdef_results_ptr = (CdefResults *)cdef_results_wrapper_ptr->object_ptr;
479 pcs_ptr = (PictureControlSet *)cdef_results_ptr->pcs_wrapper_ptr->object_ptr;
480 scs_ptr = (SequenceControlSet *)pcs_ptr->scs_wrapper_ptr->object_ptr;
481 FrameHeader *frm_hdr = &pcs_ptr->parent_pcs_ptr->frm_hdr;
482 EbBool is_16bit = (EbBool)(scs_ptr->static_config.encoder_bit_depth > EB_8BIT);
483 Av1Common * cm = pcs_ptr->parent_pcs_ptr->av1_cm;
484
485 if (scs_ptr->seq_header.enable_restoration && frm_hdr->allow_intrabc == 0) {
486 // ------- start: Normative upscaling - super-resolution tool
487 if (!av1_superres_unscaled(&cm->frm_size)) {
488 svt_av1_superres_upscale_frame(cm, pcs_ptr, scs_ptr);
489
490 if (scs_ptr->static_config.is_16bit_pipeline || is_16bit) {
491 set_unscaled_input_16bit(pcs_ptr);
492 }
493 }
494 // ------- end: Normative upscaling - super-resolution tool
495 Yv12BufferConfig cpi_source;
496 pcs_ptr->parent_pcs_ptr->enhanced_unscaled_picture_ptr->is_16bit_pipeline =
497 scs_ptr->static_config.is_16bit_pipeline;
498 link_eb_to_aom_buffer_desc(scs_ptr->static_config.is_16bit_pipeline || is_16bit
499 ? pcs_ptr->input_frame16bit
500 : pcs_ptr->parent_pcs_ptr->enhanced_unscaled_picture_ptr,
501 &cpi_source,
502 scs_ptr->max_input_pad_right,
503 scs_ptr->max_input_pad_bottom,
504 scs_ptr->static_config.is_16bit_pipeline || is_16bit);
505
506 Yv12BufferConfig trial_frame_rst;
507 link_eb_to_aom_buffer_desc(context_ptr->trial_frame_rst,
508 &trial_frame_rst,
509 scs_ptr->max_input_pad_right,
510 scs_ptr->max_input_pad_bottom,
511 scs_ptr->static_config.is_16bit_pipeline || is_16bit);
512 // If using boundaries during the filter search, copy the recon pic to a new buffer (to
513 // avoid race conidition from many threads modifying the same recon pic).
514 //
515 // If not using boundaries during the filter search, copy the input recon picture location
516 // to be used in restoration search (save cycles/memory of copying pic to a new buffer).
517 // The recon pic should not be modified during the search, otherwise there will be a race
518 // condition between threads.
519 EbPictureBufferDesc *recon_picture_ptr =
520 get_own_recon(scs_ptr,
521 pcs_ptr,
522 context_ptr,
523 scs_ptr->static_config.is_16bit_pipeline || is_16bit);
524 Yv12BufferConfig org_fts;
525 link_eb_to_aom_buffer_desc(recon_picture_ptr,
526 &org_fts,
527 scs_ptr->max_input_pad_right,
528 scs_ptr->max_input_pad_bottom,
529 scs_ptr->static_config.is_16bit_pipeline || is_16bit);
530 restoration_seg_search(context_ptr->rst_tmpbuf,
531 &org_fts,
532 &cpi_source,
533 &trial_frame_rst,
534 pcs_ptr,
535 cdef_results_ptr->segment_index);
536 }
537
538 //all seg based search is done. update total processed segments. if all done, finish the search and perfrom application.
539 svt_block_on_mutex(pcs_ptr->rest_search_mutex);
540
541 pcs_ptr->tot_seg_searched_rest++;
542 if (pcs_ptr->tot_seg_searched_rest == pcs_ptr->rest_segments_total_count) {
543 if (scs_ptr->seq_header.enable_restoration && frm_hdr->allow_intrabc == 0) {
544 rest_finish_search(pcs_ptr);
545 if (pcs_ptr->rst_info[0].frame_restoration_type != RESTORE_NONE ||
546 pcs_ptr->rst_info[1].frame_restoration_type != RESTORE_NONE ||
547 pcs_ptr->rst_info[2].frame_restoration_type != RESTORE_NONE) {
548 svt_av1_loop_restoration_filter_frame(cm->frame_to_show, cm, 0);
549 }
550 } else {
551 pcs_ptr->rst_info[0].frame_restoration_type = RESTORE_NONE;
552 pcs_ptr->rst_info[1].frame_restoration_type = RESTORE_NONE;
553 pcs_ptr->rst_info[2].frame_restoration_type = RESTORE_NONE;
554 }
555
556 uint8_t best_ep_cnt = 0;
557 uint8_t best_ep = 0;
558 for (uint8_t i = 0; i < SGRPROJ_PARAMS; i++) {
559 if (cm->sg_frame_ep_cnt[i] > best_ep_cnt) {
560 best_ep = i;
561 best_ep_cnt = cm->sg_frame_ep_cnt[i];
562 }
563 }
564 cm->sg_frame_ep = best_ep;
565
566 if (pcs_ptr->parent_pcs_ptr->reference_picture_wrapper_ptr != NULL) {
567 // copy stat to ref object (intra_coded_area, Luminance, Scene change detection flags)
568 copy_statistics_to_ref_obj_ect(pcs_ptr, scs_ptr);
569 }
570
571 // PSNR and SSIM Calculation.
572 // Note: if temporal_filtering is used, memory needs to be freed in the last of these calls
573 if (scs_ptr->static_config.stat_report) {
574 psnr_calculations(pcs_ptr, scs_ptr, EB_FALSE);
575 ssim_calculations(pcs_ptr, scs_ptr, EB_TRUE /* free memory here */);
576 }
577
578 // Pad the reference picture and set ref POC
579 if (!use_output_stat(scs_ptr))
580 if (pcs_ptr->parent_pcs_ptr->is_used_as_reference_flag == EB_TRUE)
581 pad_ref_and_set_flags(pcs_ptr, scs_ptr);
582 if (scs_ptr->static_config.recon_enabled) {
583 recon_output(pcs_ptr, scs_ptr);
584 }
585
586 tile_cols = pcs_ptr->parent_pcs_ptr->av1_cm->tiles_info.tile_cols;
587 tile_rows = pcs_ptr->parent_pcs_ptr->av1_cm->tiles_info.tile_rows;
588
589 if (pcs_ptr->parent_pcs_ptr->is_used_as_reference_flag) {
590 // Get Empty PicMgr Results
591 svt_get_empty_object(context_ptr->picture_demux_fifo_ptr,
592 &picture_demux_results_wrapper_ptr);
593
594 picture_demux_results_rtr = (PictureDemuxResults *)
595 picture_demux_results_wrapper_ptr->object_ptr;
596 picture_demux_results_rtr->reference_picture_wrapper_ptr =
597 pcs_ptr->parent_pcs_ptr->reference_picture_wrapper_ptr;
598 picture_demux_results_rtr->scs_wrapper_ptr = pcs_ptr->scs_wrapper_ptr;
599 picture_demux_results_rtr->picture_number = pcs_ptr->picture_number;
600 picture_demux_results_rtr->picture_type = EB_PIC_REFERENCE;
601
602 // Post Reference Picture
603 svt_post_full_object(picture_demux_results_wrapper_ptr);
604 }
605
606 //Jing: TODO
607 //Consider to add parallelism here, sending line by line, not waiting for a full frame
608 int sb_size_log2 = scs_ptr->seq_header.sb_size_log2;
609 for (int tile_row_idx = 0; tile_row_idx < tile_rows; tile_row_idx++) {
610 uint16_t tile_height_in_sb = (cm->tiles_info.tile_row_start_mi[tile_row_idx + 1] -
611 cm->tiles_info.tile_row_start_mi[tile_row_idx] +
612 (1 << sb_size_log2) - 1) >>
613 sb_size_log2;
614 for (int tile_col_idx = 0; tile_col_idx < tile_cols; tile_col_idx++) {
615 const int tile_idx = tile_row_idx * tile_cols + tile_col_idx;
616 svt_get_empty_object(context_ptr->rest_output_fifo_ptr,
617 &rest_results_wrapper_ptr);
618 rest_results_ptr = (struct RestResults *)rest_results_wrapper_ptr->object_ptr;
619 rest_results_ptr->pcs_wrapper_ptr = cdef_results_ptr->pcs_wrapper_ptr;
620 rest_results_ptr->completed_sb_row_index_start = 0;
621 // Set to tile rows
622 rest_results_ptr->completed_sb_row_count = tile_height_in_sb;
623 rest_results_ptr->tile_index = tile_idx;
624 // Post Rest Results
625 svt_post_full_object(rest_results_wrapper_ptr);
626 }
627 }
628 }
629 svt_release_mutex(pcs_ptr->rest_search_mutex);
630
631 // Release input Results
632 svt_release_object(cdef_results_wrapper_ptr);
633 }
634
635 return NULL;
636 }
637