Coverage Report

Created: 2026-07-30 06:27

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