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/cdef_process.c
Line
Count
Source
1
/*
2
* Copyright(c) 2019 Intel Corporation
3
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
4
*
5
* This source code is subject to the terms of the BSD 2 Clause License and
6
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
7
* was not distributed with this source code in the LICENSE file, you can
8
* obtain it at https://www.aomedia.org/license/software-license. If the Alliance for Open
9
* Media Patent License 1.0 was not distributed with this source code in the
10
* PATENTS file, you can obtain it at https://www.aomedia.org/license/patent-license.
11
*/
12
13
#include <stdlib.h>
14
#include "aom_dsp_rtcd.h"
15
#include "definitions.h"
16
#include "enc_handle.h"
17
#include "cdef_process.h"
18
#include "cdef_copy.h"
19
#include "enc_dec_results.h"
20
#include "svt_threads.h"
21
#include "reference_object.h"
22
#include "enc_cdef.h"
23
#include "enc_dec_process.h"
24
#include "pic_buffer_desc.h"
25
#include "sequence_control_set.h"
26
#include "utility.h"
27
#include "pcs.h"
28
#include "resize.h"
29
#include "super_res.h"
30
31
0
static void set_unscaled_input_16bit(PictureControlSet* pcs) {
32
0
    EbPictureBufferDesc* input_pic  = pcs->ppcs->enhanced_unscaled_pic;
33
0
    EbPictureBufferDesc* output_pic = pcs->input_frame16bit;
34
0
    uint16_t             ss_x       = pcs->ppcs->scs->subsampling_x;
35
0
    uint16_t             ss_y       = pcs->ppcs->scs->subsampling_y;
36
0
    svt_aom_copy_buffer_info(input_pic, pcs->input_frame16bit);
37
0
    if (input_pic->bit_depth == EB_EIGHT_BIT) {
38
0
        svt_aom_convert_pic_8bit_to_16bit(input_pic, output_pic, ss_x, ss_y);
39
0
    } else {
40
0
        uint16_t* planes[3] = {
41
0
            (uint16_t*)output_pic->y_buffer, (uint16_t*)output_pic->u_buffer, (uint16_t*)output_pic->v_buffer};
42
0
        svt_aom_pack_2d_pic(input_pic, planes);
43
0
    }
44
0
}
45
46
static EbErrorType copy_recon_enc(SequenceControlSet* scs, EbPictureBufferDesc* recon_picture_src,
47
0
                                  EbPictureBufferDesc* recon_picture_dst, int num_planes, int skip_copy) {
48
0
    recon_picture_dst->border       = recon_picture_src->border;
49
0
    recon_picture_dst->width        = recon_picture_src->width;
50
0
    recon_picture_dst->height       = recon_picture_src->height;
51
0
    recon_picture_dst->max_width    = recon_picture_src->max_width;
52
0
    recon_picture_dst->max_height   = recon_picture_src->max_height;
53
0
    recon_picture_dst->bit_depth    = recon_picture_src->bit_depth;
54
0
    recon_picture_dst->color_format = recon_picture_src->color_format;
55
56
0
    recon_picture_dst->y_stride = recon_picture_src->y_stride;
57
0
    recon_picture_dst->u_stride = recon_picture_src->u_stride;
58
0
    recon_picture_dst->v_stride = recon_picture_src->v_stride;
59
60
0
    recon_picture_dst->luma_size   = recon_picture_src->luma_size;
61
0
    recon_picture_dst->chroma_size = recon_picture_src->chroma_size;
62
0
    recon_picture_dst->packed_flag = recon_picture_src->packed_flag;
63
64
0
    recon_picture_dst->y_stride_bit_inc = recon_picture_src->y_stride_bit_inc;
65
0
    recon_picture_dst->u_stride_bit_inc = recon_picture_src->u_stride_bit_inc;
66
0
    recon_picture_dst->v_stride_bit_inc = recon_picture_src->v_stride_bit_inc;
67
68
0
    recon_picture_dst->buffer_enable_mask = scs->seq_header.color_config.mono_chrome ? PICTURE_BUFFER_DESC_LUMA_MASK
69
0
                                                                                     : PICTURE_BUFFER_DESC_FULL_MASK;
70
71
0
    int      ss_x            = scs->subsampling_x;
72
0
    int      ss_y            = scs->subsampling_y;
73
0
    uint32_t bytes_per_pixel = SVT_EFFECTIVE_IS_16BIT_PIPELINE(scs->is_16bit_pipeline) ? 2 : 1;
74
75
    // Get frame size to alloc
76
0
    uint32_t alloc_sz       = 0;
77
0
    uint32_t buffer_size[3] = {0};
78
0
    if (recon_picture_dst->buffer_enable_mask & PICTURE_BUFFER_DESC_Y_FLAG) {
79
0
        alloc_sz += buffer_size[0] = recon_picture_dst->luma_size * bytes_per_pixel;
80
0
    }
81
82
0
    if (recon_picture_dst->buffer_enable_mask & PICTURE_BUFFER_DESC_Cb_FLAG) {
83
0
        alloc_sz += buffer_size[1] = recon_picture_dst->chroma_size * bytes_per_pixel;
84
0
    }
85
86
0
    if (recon_picture_dst->buffer_enable_mask & PICTURE_BUFFER_DESC_Cr_FLAG) {
87
0
        alloc_sz += buffer_size[2] = recon_picture_dst->chroma_size * bytes_per_pixel;
88
0
    }
89
90
    // Allocate the Picture Buffers (luma & chroma)
91
0
    EB_CALLOC_ALIGNED_ARRAY(recon_picture_dst->buffer_alloc, alloc_sz);
92
0
    recon_picture_dst->buffer_alloc_sz = alloc_sz;
93
0
    uint32_t assigned_space            = 0;
94
0
    if (recon_picture_dst->buffer_enable_mask & PICTURE_BUFFER_DESC_Y_FLAG) {
95
0
        recon_picture_dst->y_buffer = recon_picture_dst->buffer_alloc +
96
0
            (recon_picture_dst->border + (recon_picture_dst->y_stride * recon_picture_dst->border)) * bytes_per_pixel;
97
0
        assigned_space += buffer_size[0];
98
0
    } else {
99
0
        recon_picture_dst->y_buffer = NULL;
100
0
    }
101
102
0
    if (recon_picture_dst->buffer_enable_mask & PICTURE_BUFFER_DESC_Cb_FLAG) {
103
0
        recon_picture_dst->u_buffer = recon_picture_dst->buffer_alloc + assigned_space +
104
0
            ((recon_picture_dst->border >> ss_x) +
105
0
             (recon_picture_dst->u_stride * (recon_picture_dst->border >> ss_y))) *
106
0
                bytes_per_pixel;
107
0
        assigned_space += buffer_size[1];
108
0
    } else {
109
0
        recon_picture_dst->u_buffer = NULL;
110
0
    }
111
112
0
    if (recon_picture_dst->buffer_enable_mask & PICTURE_BUFFER_DESC_Cr_FLAG) {
113
0
        recon_picture_dst->v_buffer = recon_picture_dst->buffer_alloc + assigned_space +
114
0
            ((recon_picture_dst->border >> ss_x) +
115
0
             (recon_picture_dst->v_stride * (recon_picture_dst->border >> ss_y))) *
116
0
                bytes_per_pixel;
117
0
        assigned_space += buffer_size[2];
118
0
    } else {
119
0
        recon_picture_dst->v_buffer = NULL;
120
0
    }
121
0
    assert(assigned_space == alloc_sz);
122
123
0
    int use_highbd = SVT_EFFECTIVE_IS_16BIT_PIPELINE(scs->is_16bit_pipeline);
124
125
0
    if (!skip_copy) {
126
0
        assert(num_planes <= MAX_PLANES);
127
0
        for (int plane = 0; plane < num_planes; ++plane) {
128
0
            uint8_t *src_buf, *dst_buf;
129
0
            int32_t  src_stride, dst_stride;
130
131
0
            int sub_x = plane ? scs->subsampling_x : 0;
132
0
            int sub_y = plane ? scs->subsampling_y : 0;
133
134
0
            src_buf    = recon_picture_src->buffer[plane];
135
0
            src_stride = recon_picture_src->stride[plane];
136
0
            dst_buf    = recon_picture_dst->buffer[plane];
137
0
            dst_stride = recon_picture_dst->stride[plane];
138
139
0
            int height = ((recon_picture_src->height + sub_y) >> sub_y);
140
0
            for (int row = 0; row < height; ++row) {
141
0
                svt_memcpy(
142
0
                    dst_buf, src_buf, ((recon_picture_src->width + sub_x) >> sub_x) * sizeof(*src_buf) << use_highbd);
143
0
                src_buf += src_stride << use_highbd;
144
0
                dst_buf += dst_stride << use_highbd;
145
0
            }
146
0
        }
147
0
    }
148
149
0
    return EB_ErrorNone;
150
0
}
151
152
0
static void svt_av1_superres_upscale_frame(struct Av1Common* cm, PictureControlSet* pcs, SequenceControlSet* scs) {
153
    // Set these parameters for testing since they are not correctly populated yet
154
0
    EbPictureBufferDesc* recon_ptr;
155
156
0
    bool is_16bit = SVT_EFFECTIVE_IS_16BIT_PIPELINE(scs->is_16bit_pipeline);
157
158
0
    svt_aom_get_recon_pic(pcs, &recon_ptr, is_16bit);
159
160
0
    uint16_t  ss_x       = scs->subsampling_x;
161
0
    uint16_t  ss_y       = scs->subsampling_y;
162
0
    const int num_planes = scs->seq_header.color_config.mono_chrome ? 1 : MAX_PLANES;
163
164
0
    EbPictureBufferDesc  recon_pic_temp;
165
0
    EbPictureBufferDesc* ps_recon_pic_temp;
166
0
    ps_recon_pic_temp = &recon_pic_temp;
167
168
0
    EbErrorType return_error = copy_recon_enc(scs, recon_ptr, ps_recon_pic_temp, num_planes, 0);
169
170
0
    if (return_error != EB_ErrorNone) {
171
0
        ps_recon_pic_temp = NULL;
172
0
        assert(0);
173
0
    }
174
175
0
    EbPictureBufferDesc* src = ps_recon_pic_temp;
176
0
    EbPictureBufferDesc* dst = recon_ptr;
177
178
    // get the bit-depth from the encoder config instead of from the recon ptr
179
0
    int bit_depth = scs->static_config.encoder_bit_depth;
180
181
0
    assert(num_planes <= MAX_PLANES);
182
0
    for (int plane = 0; plane < num_planes; ++plane) {
183
0
        uint8_t *src_buf, *dst_buf;
184
0
        int32_t  src_stride, dst_stride;
185
186
0
        int sub_x  = plane ? ss_x : 0;
187
0
        int sub_y  = plane ? ss_y : 0;
188
0
        src_buf    = src->buffer[plane];
189
0
        src_stride = src->stride[plane];
190
0
        dst_buf    = dst->buffer[plane];
191
0
        dst_stride = dst->stride[plane];
192
193
0
        svt_av1_upscale_normative_rows(cm,
194
0
                                       (const uint8_t*)src_buf,
195
0
                                       src_stride,
196
0
                                       dst_buf,
197
0
                                       dst_stride,
198
0
                                       (src->height + sub_y) >> sub_y,
199
0
                                       sub_x,
200
0
                                       bit_depth,
201
0
                                       is_16bit);
202
0
    }
203
204
    // free the memory
205
0
    EB_FREE_ALIGNED_ARRAY(ps_recon_pic_temp->buffer_alloc);
206
0
}
207
208
/**************************************
209
 * Cdef Context
210
 **************************************/
211
typedef struct CdefContext {
212
    EbFifo* cdef_input_fifo_ptr;
213
    EbFifo* cdef_output_fifo_ptr;
214
    // Hoisted per-thread CDEF search scratch (were large on-stack arrays).
215
    uint16_t* tmp_dst; // 1 << (MAX_SB_SIZE_LOG2 * 2)
216
#if !CDEF_8BITS_PATH || CONFIG_ENABLE_HIGH_BIT_DEPTH
217
    uint16_t* inbuf; // CDEF_INBUF_SIZE (16-bit sentinel buffer)
218
#endif
219
#if CDEF_8BITS_PATH
220
    uint8_t* inbuf8; // CDEF_INBUF_SIZE (8-bit native interior path)
221
#endif
222
} CdefContext;
223
224
485
static void cdef_context_dctor(EbPtr p) {
225
485
    EbThreadContext* thread_ctx = (EbThreadContext*)p;
226
485
    CdefContext*     obj        = (CdefContext*)thread_ctx->priv;
227
485
    EB_FREE_ALIGNED_ARRAY(obj->tmp_dst);
228
485
#if !CDEF_8BITS_PATH || CONFIG_ENABLE_HIGH_BIT_DEPTH
229
485
    EB_FREE_ALIGNED_ARRAY(obj->inbuf);
230
485
#endif
231
#if CDEF_8BITS_PATH
232
    EB_FREE_ALIGNED_ARRAY(obj->inbuf8);
233
#endif
234
485
    EB_FREE_ARRAY(obj);
235
485
}
236
237
/******************************************************
238
 * Cdef Context Constructor
239
 ******************************************************/
240
485
EbErrorType svt_aom_cdef_context_ctor(EbThreadContext* thread_ctx, const EbEncHandle* enc_handle_ptr, int index) {
241
485
    CdefContext* cdef_ctx;
242
485
    EB_CALLOC_ARRAY(cdef_ctx, 1);
243
485
    thread_ctx->priv  = cdef_ctx;
244
485
    thread_ctx->dctor = cdef_context_dctor;
245
246
    // Input/Output System Resource Manager FIFOs
247
485
    cdef_ctx->cdef_input_fifo_ptr  = svt_system_resource_get_consumer_fifo(enc_handle_ptr->dlf_results_resource_ptr,
248
485
                                                                          index);
249
485
    cdef_ctx->cdef_output_fifo_ptr = svt_system_resource_get_producer_fifo(enc_handle_ptr->cdef_results_resource_ptr,
250
485
                                                                           index);
251
252
    // Hoisted per-thread CDEF search scratch (previously large on-stack arrays).
253
485
    EB_MALLOC_ALIGNED_ARRAY(cdef_ctx->tmp_dst, 1 << (MAX_SB_SIZE_LOG2 * 2));
254
485
#if !CDEF_8BITS_PATH || CONFIG_ENABLE_HIGH_BIT_DEPTH
255
485
    EB_MALLOC_ALIGNED_ARRAY(cdef_ctx->inbuf, CDEF_INBUF_SIZE);
256
485
#endif
257
#if CDEF_8BITS_PATH
258
    EB_MALLOC_ALIGNED_ARRAY(cdef_ctx->inbuf8, CDEF_INBUF_SIZE);
259
#endif
260
261
485
    return EB_ErrorNone;
262
485
}
263
264
0
#define default_mse_uv 1040400
265
266
static uint64_t compute_cdef_dist(const EbByte dst, int32_t doffset, int32_t dstride, const uint8_t* src,
267
                                  const CdefList* dlist, int32_t cdef_count, BlockSize bsize, int32_t coeff_shift,
268
0
                                  uint8_t subsampling_factor, bool is_16bit) {
269
0
    uint64_t curr_mse = 0;
270
0
    if (is_16bit) {
271
0
        curr_mse = svt_compute_cdef_dist_16bit(((uint16_t*)dst) + doffset,
272
0
                                               dstride,
273
0
                                               (uint16_t*)src,
274
0
                                               dlist,
275
0
                                               cdef_count,
276
0
                                               bsize,
277
0
                                               coeff_shift,
278
0
                                               subsampling_factor);
279
280
0
    } else {
281
0
        curr_mse = svt_compute_cdef_dist_8bit(
282
0
            dst + doffset, dstride, src, dlist, cdef_count, bsize, coeff_shift, subsampling_factor);
283
0
    }
284
0
    return curr_mse;
285
0
}
286
287
/* Search for the best filter strength pair for each 64x64 filter block.
288
 *
289
 * For each 64x64 filter block and each plane, search the allowable filter strength pairs.
290
 * Call cdef_filter_fb() to perform filtering, then compute the MSE for each pair.
291
*/
292
0
static void cdef_seg_search(CdefContext* ctx, PictureControlSet* pcs, SequenceControlSet* scs, uint32_t segment_index) {
293
0
    PictureParentControlSet* ppcs    = pcs->ppcs;
294
0
    FrameHeader*             frm_hdr = &ppcs->frm_hdr;
295
0
    Av1Common*               cm      = ppcs->av1_cm;
296
0
    uint32_t                 x_seg_idx;
297
0
    uint32_t                 y_seg_idx;
298
0
    const uint32_t           b64_pic_width  = (ppcs->aligned_width + 64 - 1) / 64;
299
0
    const uint32_t           b64_pic_height = (ppcs->aligned_height + 64 - 1) / 64;
300
0
    SEGMENT_CONVERT_IDX_TO_XY(segment_index, x_seg_idx, y_seg_idx, pcs->cdef_segments_column_count);
301
0
    const uint32_t x_b64_start_idx = SEGMENT_START_IDX(x_seg_idx, b64_pic_width, pcs->cdef_segments_column_count);
302
0
    const uint32_t x_b64_end_idx   = SEGMENT_END_IDX(x_seg_idx, b64_pic_width, pcs->cdef_segments_column_count);
303
0
    const uint32_t y_b64_start_idx = SEGMENT_START_IDX(y_seg_idx, b64_pic_height, pcs->cdef_segments_row_count);
304
0
    const uint32_t y_b64_end_idx   = SEGMENT_END_IDX(y_seg_idx, b64_pic_height, pcs->cdef_segments_row_count);
305
306
0
    const int32_t       mi_rows                    = cm->mi_rows;
307
0
    const int32_t       mi_cols                    = cm->mi_cols;
308
0
    CdefSearchControls* cdef_ctrls                 = &ppcs->cdef_search_ctrls;
309
0
    const int           first_pass_fs_num          = cdef_ctrls->first_pass_fs_num;
310
0
    const int           default_second_pass_fs_num = cdef_ctrls->default_second_pass_fs_num;
311
0
    EbByte              src[3];
312
0
    EbByte              ref[3];
313
0
    int32_t             stride_src[3];
314
0
    int32_t             stride_ref[3];
315
0
    int32_t             plane_bsize[3];
316
0
    int32_t             mi_wide_l2[3];
317
0
    int32_t             mi_high_l2[3];
318
0
    int32_t             xdec[3];
319
0
    int32_t             ydec[3];
320
0
    int32_t             cdef_count;
321
0
    const int32_t       coeff_shift = AOMMAX(scs->static_config.encoder_bit_depth - 8, 0);
322
0
    const int32_t       nvfb        = (mi_rows + MI_SIZE_64X64 - 1) / MI_SIZE_64X64;
323
0
    const int32_t       nhfb        = (mi_cols + MI_SIZE_64X64 - 1) / MI_SIZE_64X64;
324
0
    const int32_t       damping     = 3 + (frm_hdr->quantization_params.base_q_idx >> 6);
325
0
    const int32_t       num_planes  = 3;
326
0
    const bool          sb64        = scs->seq_header.sb_size == BLOCK_64X64;
327
0
    CdefList            dlist_local[MI_SIZE_128X128 * MI_SIZE_128X128];
328
0
    CdefList*           dlist;
329
330
0
#if CONFIG_ENABLE_HIGH_BIT_DEPTH
331
0
    const bool is_16bit = SVT_EFFECTIVE_IS_16BIT_PIPELINE(scs->is_16bit_pipeline);
332
#else
333
    const bool is_16bit = false;
334
#endif
335
336
0
#if !CDEF_8BITS_PATH || CONFIG_ENABLE_HIGH_BIT_DEPTH
337
0
    int32_t   toff_prev  = CDEF_VBORDER;
338
0
    int32_t   loff_prev  = CDEF_HBORDER;
339
0
    int32_t   ysize_prev = (1 << MAX_SB_SIZE_LOG2) + 2 * CDEF_VBORDER;
340
0
    int32_t   xsize_prev = (1 << MAX_SB_SIZE_LOG2) + 2 * CDEF_HBORDER;
341
0
    uint16_t* inbuf      = ctx->inbuf; // 16-bit sentinel buffer (HBD / non-8bit path only)
342
0
    uint16_t* in         = inbuf + CDEF_VBORDER * CDEF_BSTRIDE + CDEF_HBORDER;
343
0
#endif
344
#if CDEF_8BITS_PATH
345
    // 8-bit padded buffer for the native interior path (replaces the 8->16 widen
346
    // for fully-interior 8-bit fbs). Same CDEF_BSTRIDE layout as `in`.
347
    uint8_t* inbuf8 = ctx->inbuf8;
348
    uint8_t* in8    = inbuf8 + CDEF_VBORDER * CDEF_BSTRIDE + CDEF_HBORDER;
349
#endif
350
    // tmp_dst is uint16_t to accommodate high bit depth content; 8bit will treat it as a uint8_t
351
    // buffer and will not use half of the buffer
352
0
    uint16_t* tmp_dst = ctx->tmp_dst;
353
354
0
    EbPictureBufferDesc* input_pic = is_16bit ? pcs->input_frame16bit : ppcs->enhanced_pic;
355
0
    EbPictureBufferDesc* recon_pic;
356
0
    svt_aom_get_recon_pic(pcs, &recon_pic, is_16bit);
357
358
0
    for (int pli = 0; pli < num_planes; pli++) {
359
0
        const int subsampling_x = (pli == 0) ? 0 : 1;
360
0
        const int subsampling_y = (pli == 0) ? 0 : 1;
361
0
        xdec[pli]               = subsampling_x;
362
0
        ydec[pli]               = subsampling_y;
363
        // The checks are stubs for 4:2:2 and 4:4:4 support
364
        // cppcheck-suppress knownConditionTrueFalse
365
0
        plane_bsize[pli] = subsampling_y ? (subsampling_x ? BLOCK_4X4 : BLOCK_8X4)
366
0
                                         : (subsampling_x ? BLOCK_4X8 : BLOCK_8X8);
367
0
        mi_wide_l2[pli]  = MI_SIZE_LOG2 - subsampling_x;
368
0
        mi_high_l2[pli]  = MI_SIZE_LOG2 - subsampling_y;
369
0
        src[pli]         = pcs->cdef_input_recon[pli];
370
0
        ref[pli]         = pcs->cdef_input_source[pli];
371
0
        stride_src[pli]  = pli == 0 ? recon_pic->y_stride : (pli == 1 ? recon_pic->u_stride : recon_pic->v_stride);
372
0
        stride_ref[pli]  = pli == 0 ? input_pic->y_stride : (pli == 1 ? input_pic->u_stride : input_pic->v_stride);
373
0
    }
374
375
    // Loop over all filter blocks (64x64)
376
0
    for (uint32_t fbr = y_b64_start_idx; fbr < y_b64_end_idx; ++fbr) {
377
0
        for (uint32_t fbc = x_b64_start_idx; fbc < x_b64_end_idx; ++fbc) {
378
0
            int32_t           dirinit = 0;
379
0
            const uint32_t    lc      = MI_SIZE_64X64 * fbc;
380
0
            const uint32_t    lr      = MI_SIZE_64X64 * fbr;
381
0
            int               nhb     = AOMMIN(MI_SIZE_64X64, mi_cols - lc);
382
0
            int               nvb     = AOMMIN(MI_SIZE_64X64, mi_rows - lr);
383
0
            int               hb_step = 1; //these should be all time with 64x64 SBs
384
0
            int               vb_step = 1;
385
0
            BlockSize         bs      = BLOCK_64X64;
386
0
            const MbModeInfo* mbmi    = pcs->mi_grid_base[lr * cm->mi_stride + lc];
387
0
            const BlockSize   bsize   = mbmi->bsize;
388
0
            if (((fbc & 1) && (bsize == BLOCK_128X128 || bsize == BLOCK_128X64)) ||
389
0
                ((fbr & 1) && (bsize == BLOCK_128X128 || bsize == BLOCK_64X128))) {
390
0
                continue;
391
0
            }
392
0
            if (bsize == BLOCK_128X128 || bsize == BLOCK_128X64 || bsize == BLOCK_64X128) {
393
0
                bs = bsize;
394
0
            }
395
396
0
            if (bs == BLOCK_128X128 || bs == BLOCK_128X64) {
397
0
                nhb     = AOMMIN(MI_SIZE_128X128, cm->mi_cols - lc);
398
0
                hb_step = 2;
399
0
            }
400
0
            if (bs == BLOCK_128X128 || bs == BLOCK_64X128) {
401
0
                nvb     = AOMMIN(MI_SIZE_128X128, cm->mi_rows - lr);
402
0
                vb_step = 2;
403
0
            }
404
0
            const uint32_t fb_idx = fbr * nhfb + fbc;
405
            // For SB=64, compute the dlist straight into the per-fb cache so the apply can reuse it
406
            // (skips a second svt_sb_compute_cdef_list scan); otherwise use the local scratch.
407
0
            dlist      = sb64 ? pcs->cdef_fb_list[fb_idx].dlist : dlist_local;
408
0
            cdef_count = svt_sb_compute_cdef_list(pcs, cm, lr, lc, dlist, bs);
409
0
            if (sb64) {
410
0
                pcs->cdef_fb_list[fb_idx].cdef_count = cdef_count;
411
0
            }
412
0
            if (cdef_count == 0) {
413
0
                pcs->skip_cdef_seg[fb_idx] = 1;
414
0
                continue;
415
0
            }
416
0
            pcs->skip_cdef_seg[fb_idx] = 0;
417
418
0
            int32_t toff = CDEF_VBORDER * (fbr != 0);
419
0
            int32_t loff = CDEF_HBORDER * (fbc != 0);
420
0
            int32_t boff = CDEF_VBORDER * ((int32_t)fbr + vb_step < nvfb);
421
0
            int32_t roff = CDEF_HBORDER * ((int32_t)fbc + hb_step < nhfb);
422
423
0
            uint8_t (*dir)[CDEF_NBLOCKS][CDEF_NBLOCKS] = &pcs->cdef_dir_data[fb_idx].dir;
424
0
            int32_t (*var)[CDEF_NBLOCKS][CDEF_NBLOCKS] = &pcs->cdef_dir_data[fb_idx].var;
425
0
            for (int pli = 0; pli < num_planes; pli++) {
426
0
#if !CDEF_8BITS_PATH || CONFIG_ENABLE_HIGH_BIT_DEPTH
427
0
                int32_t ysize = (nvb << mi_high_l2[pli]) + boff + toff;
428
0
                int32_t xsize = (nhb << mi_wide_l2[pli]) + roff + loff;
429
0
#endif
430
#if CDEF_8BITS_PATH
431
                // 8-bit content (RTC): filter via the boundary-aware hybrid. Build the 8-bit in8
432
                // buffer DIRECTLY from recon (interior AND frame-edge fbs); off-frame halo is left
433
                // as garbage and masked geometrically by the bounded kernel -- no 16-bit sentinel.
434
                const bool native_8bit = !is_16bit;
435
#else
436
0
                const bool native_8bit = false;
437
0
#endif
438
0
#if !CDEF_8BITS_PATH || CONFIG_ENABLE_HIGH_BIT_DEPTH
439
0
                if (!native_8bit) {
440
                    /* We avoid filtering the pixels for which some of the pixels to
441
                   average are outside the frame. We could change the filter instead,
442
                   but it would add special cases for any future vectorization.
443
                   Avoid memset'ting when dirty rect is inside the new one.
444
                   TODO: this could be further optimized - fill out only borders, separate buffers for Y & UV */
445
0
                    bool need_to_reset = toff_prev > toff || loff_prev > loff || ysize < ysize_prev ||
446
0
                        xsize < xsize_prev;
447
0
                    if (need_to_reset) {
448
0
                        uint16_t* p = &in[(-toff_prev * CDEF_BSTRIDE - loff_prev)];
449
0
                        for (int r = 0; r < ysize_prev; r++) {
450
0
                            svt_memset(p, (uint8_t)CDEF_VERY_LARGE, sizeof(p[0]) * xsize_prev);
451
0
                            p += CDEF_BSTRIDE;
452
0
                        }
453
0
                    }
454
0
                    toff_prev  = toff;
455
0
                    loff_prev  = loff;
456
0
                    ysize_prev = ysize;
457
0
                    xsize_prev = xsize;
458
459
0
                    svt_aom_copy_sb8_16(&in[(-toff * CDEF_BSTRIDE - loff)],
460
0
                                        CDEF_BSTRIDE,
461
0
                                        src[pli],
462
0
                                        (lr << mi_high_l2[pli]) - toff,
463
0
                                        (lc << mi_wide_l2[pli]) - loff,
464
0
                                        stride_src[pli],
465
0
                                        ysize,
466
0
                                        xsize,
467
0
                                        is_16bit);
468
0
                }
469
0
#endif
470
#if CDEF_8BITS_PATH
471
                if (native_8bit) {
472
                    // The bounded 8-bit kernel reads only +/-CDEF_HALO around the body, so copy just a
473
                    // HALO-wide halo (not the HBORDER/VBORDER SIMD padding). Off-frame sides have 0 halo;
474
                    // those taps are masked geometrically. svt_cdef_copy_rect8 dispatches on the (now
475
                    // apply-matching) width to a constant-size memcpy.
476
                    const int32_t toff8  = CDEF_HALO * (fbr != 0);
477
                    const int32_t loff8  = CDEF_HALO * (fbc != 0);
478
                    const int32_t boff8  = CDEF_HALO * ((int32_t)fbr + vb_step < nvfb);
479
                    const int32_t roff8  = CDEF_HALO * ((int32_t)fbc + hb_step < nhfb);
480
                    const int32_t ysize8 = (nvb << mi_high_l2[pli]) + boff8 + toff8;
481
                    const int32_t xsize8 = (nhb << mi_wide_l2[pli]) + roff8 + loff8;
482
                    svt_cdef_copy_rect8(&in8[(-toff8 * CDEF_BSTRIDE - loff8)],
483
                                        CDEF_BSTRIDE,
484
                                        src[pli],
485
                                        (lr << mi_high_l2[pli]) - toff8,
486
                                        (lc << mi_wide_l2[pli]) - loff8,
487
                                        stride_src[pli],
488
                                        ysize8,
489
                                        xsize8);
490
                }
491
#endif
492
493
0
                uint8_t subsampling_factor = cdef_ctrls->subsampling_factor;
494
                /*
495
                Cap the subsampling for certain block sizes.
496
497
                The intrinsics process several lines simultaneously, so blocks can only be subsampled
498
                a finite amount before there is no more speed gain.  If the space between processed lines
499
                is too large, the intrinsics will begin accessing memory outside the block.
500
                */
501
0
                switch (plane_bsize[pli]) {
502
0
                case BLOCK_8X8:
503
0
                    subsampling_factor = MIN(subsampling_factor, 4);
504
0
                    break;
505
0
                case BLOCK_8X4:
506
0
                case BLOCK_4X8:
507
0
                    subsampling_factor = MIN(subsampling_factor, 2);
508
0
                    break;
509
0
                case BLOCK_4X4:
510
0
                    subsampling_factor = MIN(subsampling_factor, 1);
511
0
                    break;
512
0
                }
513
514
                /* first cdef stage
515
                 * Perform the pri_filter strength search for the current sub_block
516
                 */
517
0
                for (int gi = 0; gi < first_pass_fs_num; gi++) {
518
                    // Check if chroma filter is set to be tested
519
0
                    if (pli && (cdef_ctrls->default_first_pass_fs_uv[gi] == -1)) {
520
0
                        pcs->mse_seg[1][fb_idx][gi] = default_mse_uv * 64;
521
0
                        continue;
522
0
                    }
523
524
#if CDEF_8BITS_PATH
525
                    if (native_8bit) {
526
                        svt_cdef_filter_fb_lbd((uint8_t*)tmp_dst,
527
                                               0,
528
                                               in8,
529
                                               toff == 0,
530
                                               loff == 0,
531
                                               boff == 0,
532
                                               roff == 0,
533
                                               nvb << mi_high_l2[pli],
534
                                               nhb << mi_wide_l2[pli],
535
                                               xdec[pli],
536
                                               ydec[pli],
537
                                               *dir,
538
                                               &dirinit,
539
                                               *var,
540
                                               pli,
541
                                               dlist,
542
                                               cdef_count,
543
                                               cdef_ctrls->default_first_pass_fs[gi],
544
                                               damping,
545
                                               coeff_shift,
546
                                               subsampling_factor);
547
                    } // native_8bit
548
#if !CDEF_8BITS_PATH || CONFIG_ENABLE_HIGH_BIT_DEPTH
549
                    else
550
#endif
551
#endif
552
0
#if !CDEF_8BITS_PATH || CONFIG_ENABLE_HIGH_BIT_DEPTH
553
0
                        svt_cdef_filter_fb(is_16bit ? NULL : (uint8_t*)tmp_dst,
554
0
                                           is_16bit ? tmp_dst : NULL,
555
0
                                           0,
556
0
                                           in,
557
0
                                           xdec[pli],
558
0
                                           ydec[pli],
559
0
                                           *dir,
560
0
                                           &dirinit,
561
0
                                           *var,
562
0
                                           pli,
563
0
                                           dlist,
564
0
                                           cdef_count,
565
0
                                           cdef_ctrls->default_first_pass_fs[gi],
566
0
                                           damping,
567
0
                                           coeff_shift,
568
0
                                           subsampling_factor);
569
0
#endif
570
0
                    uint64_t curr_mse = compute_cdef_dist(
571
0
                        ref[pli],
572
0
                        (lr << mi_high_l2[pli]) * stride_ref[pli] + (lc << mi_wide_l2[pli]),
573
0
                        stride_ref[pli],
574
0
                        (uint8_t*)tmp_dst,
575
0
                        dlist,
576
0
                        cdef_count,
577
0
                        (BlockSize)plane_bsize[pli],
578
0
                        coeff_shift,
579
0
                        subsampling_factor,
580
0
                        is_16bit);
581
582
0
                    if (pli < 2) {
583
0
                        pcs->mse_seg[pli][fb_idx][gi] = curr_mse * subsampling_factor;
584
0
                    } else {
585
0
                        pcs->mse_seg[1][fb_idx][gi] += (curr_mse * subsampling_factor);
586
0
                    }
587
0
                }
588
589
                /* second cdef stage
590
                 * Perform the sec_filter strength search for the current sub_block
591
                 */
592
0
                for (int gi = first_pass_fs_num; gi < first_pass_fs_num + default_second_pass_fs_num; gi++) {
593
                    // Check if chroma filter is set to be tested
594
0
                    if (pli && (cdef_ctrls->default_second_pass_fs_uv[gi - first_pass_fs_num] == -1)) {
595
0
                        pcs->mse_seg[1][fb_idx][gi] = default_mse_uv * 64;
596
0
                        continue;
597
0
                    }
598
599
#if CDEF_8BITS_PATH
600
                    if (native_8bit) {
601
                        svt_cdef_filter_fb_lbd((uint8_t*)tmp_dst,
602
                                               0,
603
                                               in8,
604
                                               toff == 0,
605
                                               loff == 0,
606
                                               boff == 0,
607
                                               roff == 0,
608
                                               nvb << mi_high_l2[pli],
609
                                               nhb << mi_wide_l2[pli],
610
                                               xdec[pli],
611
                                               ydec[pli],
612
                                               *dir,
613
                                               &dirinit,
614
                                               *var,
615
                                               pli,
616
                                               dlist,
617
                                               cdef_count,
618
                                               cdef_ctrls->default_second_pass_fs[gi - first_pass_fs_num],
619
                                               damping,
620
                                               coeff_shift,
621
                                               subsampling_factor);
622
                    } // native_8bit
623
#if !CDEF_8BITS_PATH || CONFIG_ENABLE_HIGH_BIT_DEPTH
624
                    else
625
#endif
626
#endif
627
0
#if !CDEF_8BITS_PATH || CONFIG_ENABLE_HIGH_BIT_DEPTH
628
0
                        svt_cdef_filter_fb(is_16bit ? NULL : (uint8_t*)tmp_dst,
629
0
                                           is_16bit ? tmp_dst : NULL,
630
0
                                           0,
631
0
                                           in,
632
0
                                           xdec[pli],
633
0
                                           ydec[pli],
634
0
                                           *dir,
635
0
                                           &dirinit,
636
0
                                           *var,
637
0
                                           pli,
638
0
                                           dlist,
639
0
                                           cdef_count,
640
0
                                           cdef_ctrls->default_second_pass_fs[gi - first_pass_fs_num],
641
0
                                           damping,
642
0
                                           coeff_shift,
643
0
                                           subsampling_factor);
644
0
#endif
645
0
                    uint64_t curr_mse = compute_cdef_dist(
646
0
                        ref[pli],
647
0
                        (lr << mi_high_l2[pli]) * stride_ref[pli] + (lc << mi_wide_l2[pli]),
648
0
                        stride_ref[pli],
649
0
                        (uint8_t*)tmp_dst,
650
0
                        dlist,
651
0
                        cdef_count,
652
0
                        (BlockSize)plane_bsize[pli],
653
0
                        coeff_shift,
654
0
                        subsampling_factor,
655
0
                        is_16bit);
656
657
0
                    if (pli < 2) {
658
0
                        pcs->mse_seg[pli][fb_idx][gi] = curr_mse * subsampling_factor;
659
0
                    } else {
660
0
                        pcs->mse_seg[1][fb_idx][gi] += (curr_mse * subsampling_factor);
661
0
                    }
662
0
                }
663
0
            }
664
0
        }
665
0
    }
666
0
}
667
668
/******************************************************
669
 * CDEF Kernel
670
 ******************************************************/
671
970
EbErrorType svt_aom_cdef_kernel_iter(void* context) {
672
    // Context & SCS & PCS
673
970
    CdefContext*        context_ptr = (CdefContext*)context;
674
970
    PictureControlSet*  pcs;
675
970
    SequenceControlSet* scs;
676
677
    //// Input
678
970
    EbObjectWrapper* dlf_results_wrapper;
679
970
    DlfResults*      dlf_results;
680
681
    //// Output
682
970
    EbObjectWrapper* cdef_results_wrapper;
683
684
970
    FrameHeader* frm_hdr;
685
686
    // Get DLF Results
687
970
    EB_GET_FULL_OBJECT(context_ptr->cdef_input_fifo_ptr, &dlf_results_wrapper);
688
689
485
    dlf_results                   = (DlfResults*)dlf_results_wrapper->object_ptr;
690
485
    pcs                           = (PictureControlSet*)dlf_results->pcs_wrapper->object_ptr;
691
485
    PictureParentControlSet* ppcs = pcs->ppcs;
692
485
    scs                           = pcs->scs;
693
694
485
    bool       is_16bit                   = SVT_EFFECTIVE_IS_16BIT_PIPELINE(scs->is_16bit_pipeline);
695
485
    Av1Common* cm                         = pcs->ppcs->av1_cm;
696
485
    frm_hdr                               = &pcs->ppcs->frm_hdr;
697
485
    CdefSearchControls* cdef_search_ctrls = &pcs->ppcs->cdef_search_ctrls;
698
485
    if (!cdef_search_ctrls->use_reference_cdef_fs && !cdef_search_ctrls->use_qp_strength) {
699
0
        if (scs->seq_header.cdef_level && pcs->ppcs->cdef_level) {
700
0
            cdef_seg_search(context_ptr, pcs, scs, dlf_results->segment_index);
701
0
        }
702
0
    }
703
    //all seg based search is done. update total processed segments. if all done, finish the search and perfrom application.
704
485
    svt_block_on_mutex(pcs->cdef_search_mutex);
705
706
485
    pcs->tot_seg_searched_cdef++;
707
485
    if (pcs->tot_seg_searched_cdef == pcs->cdef_segments_total_count) {
708
485
        pcs->cdef_dist_dev = -1;
709
485
        if (scs->seq_header.cdef_level && pcs->ppcs->cdef_level) {
710
278
            finish_cdef_search(pcs);
711
278
            if (ppcs->enable_restoration || pcs->ppcs->is_ref || scs->static_config.recon_enabled ||
712
278
                scs->static_config.stat_report) {
713
                // Do application iff there are non-zero filters
714
0
                if (frm_hdr->cdef_params.cdef_y_strength[0] != 0 || frm_hdr->cdef_params.cdef_uv_strength[0] != 0 ||
715
0
                    pcs->ppcs->nb_cdef_strengths != 1) {
716
0
                    svt_av1_cdef_frame(scs, pcs);
717
0
                }
718
0
            }
719
278
        } else {
720
207
            frm_hdr->cdef_params.cdef_bits           = 0;
721
207
            frm_hdr->cdef_params.cdef_y_strength[0]  = 0;
722
207
            pcs->ppcs->nb_cdef_strengths             = 1;
723
207
            frm_hdr->cdef_params.cdef_uv_strength[0] = 0;
724
207
        }
725
726
485
        if (pcs->ppcs->nb_cdef_strengths == 1 && frm_hdr->cdef_params.cdef_y_strength[0] == 0 &&
727
237
            frm_hdr->cdef_params.cdef_uv_strength[0] == 0) {
728
232
            pcs->cdef_dist_dev = 0;
729
232
        }
730
731
        //restoration prep
732
485
        bool is_lr = ppcs->enable_restoration && frm_hdr->allow_intrabc == 0;
733
485
        if (is_lr) {
734
0
            svt_av1_loop_restoration_save_boundary_lines(cm->frame_to_show, cm, 1);
735
0
            if (is_16bit) {
736
0
                set_unscaled_input_16bit(pcs);
737
0
            }
738
0
        }
739
740
        // ------- start: Normative upscaling - super-resolution tool
741
485
        if (frm_hdr->allow_intrabc == 0 && pcs->ppcs->frame_superres_enabled) {
742
0
            svt_av1_superres_upscale_frame(cm, pcs, scs);
743
0
        }
744
485
        if (scs->static_config.resize_mode != RESIZE_NONE) {
745
0
            EbPictureBufferDesc* recon = NULL;
746
0
            svt_aom_get_recon_pic(pcs, &recon, is_16bit);
747
0
            recon->width  = pcs->ppcs->render_width;
748
0
            recon->height = pcs->ppcs->render_height;
749
0
            if (is_lr) {
750
0
                EbPictureBufferDesc* input_pic = is_16bit ? pcs->input_frame16bit : pcs->ppcs->enhanced_unscaled_pic;
751
752
0
                svt_aom_assert_err(pcs->scaled_input_pic == NULL, "pcs_ptr->scaled_input_pic is not desctoried!");
753
0
                EbPictureBufferDesc* scaled_input_pic = NULL;
754
                // downscale input picture if recon is resized
755
0
                bool is_resized = recon->width != input_pic->width || recon->height != input_pic->height;
756
0
                if (is_resized) {
757
0
                    superres_params_type spr_params = {recon->width, recon->height, 0};
758
0
                    svt_aom_downscaled_source_buffer_desc_ctor(&scaled_input_pic, input_pic, spr_params);
759
0
                    svt_aom_resize_frame(input_pic,
760
0
                                         scaled_input_pic,
761
0
                                         scs->static_config.encoder_bit_depth,
762
0
                                         av1_num_planes(&scs->seq_header.color_config),
763
0
                                         scs->subsampling_x,
764
0
                                         scs->subsampling_y,
765
0
                                         input_pic->packed_flag,
766
0
                                         PICTURE_BUFFER_DESC_FULL_MASK,
767
0
                                         0); // is_2bcompress
768
0
                    pcs->scaled_input_pic = scaled_input_pic;
769
0
                }
770
0
            }
771
0
        }
772
        // ------- end: Normative upscaling - super-resolution tool
773
774
485
        pcs->rest_segments_column_count = scs->rest_segment_column_count;
775
485
        pcs->rest_segments_row_count    = scs->rest_segment_row_count;
776
485
        pcs->rest_segments_total_count  = (uint16_t)(pcs->rest_segments_column_count * pcs->rest_segments_row_count);
777
485
        pcs->tot_seg_searched_rest      = 0;
778
485
        pcs->ppcs->av1_cm->use_boundaries_in_rest_search = scs->use_boundaries_in_rest_search;
779
485
        pcs->rest_extend_flag[0]                         = false;
780
485
        pcs->rest_extend_flag[1]                         = false;
781
485
        pcs->rest_extend_flag[2]                         = false;
782
783
485
        uint32_t segment_index;
784
970
        for (segment_index = 0; segment_index < pcs->rest_segments_total_count; ++segment_index) {
785
            // Get Empty Cdef Results to Rest
786
485
            svt_get_empty_object(context_ptr->cdef_output_fifo_ptr, &cdef_results_wrapper);
787
485
            CdefResults* cdef_results   = (struct CdefResults*)cdef_results_wrapper->object_ptr;
788
485
            cdef_results->pcs_wrapper   = dlf_results->pcs_wrapper;
789
485
            cdef_results->segment_index = segment_index;
790
            // Post Cdef Results
791
485
            svt_post_full_object(cdef_results_wrapper);
792
485
        }
793
485
    }
794
485
    svt_release_mutex(pcs->cdef_search_mutex);
795
796
    // Release Dlf Results
797
485
    svt_release_object(dlf_results_wrapper);
798
799
485
    return EB_ErrorNone;
800
970
}
801
802
485
void* svt_aom_cdef_kernel(void* input_ptr) {
803
485
    EbThreadContext* thread_ctx = (EbThreadContext*)input_ptr;
804
970
    for (;;) {
805
970
        EbErrorType err = svt_aom_cdef_kernel_iter(thread_ctx->priv);
806
970
        if (err == EB_NoErrorFifoShutdown) {
807
485
            return NULL;
808
485
        }
809
970
    }
810
0
    return NULL;
811
485
}