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