Coverage Report

Created: 2026-07-16 06:32

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 = 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 = 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 = 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
448
static void cdef_context_dctor(EbPtr p) {
225
448
    EbThreadContext* thread_ctx = (EbThreadContext*)p;
226
448
    CdefContext*     obj        = (CdefContext*)thread_ctx->priv;
227
448
    EB_FREE_ALIGNED_ARRAY(obj->tmp_dst);
228
448
#if !CDEF_8BITS_PATH || CONFIG_ENABLE_HIGH_BIT_DEPTH
229
448
    EB_FREE_ALIGNED_ARRAY(obj->inbuf);
230
448
#endif
231
#if CDEF_8BITS_PATH
232
    EB_FREE_ALIGNED_ARRAY(obj->inbuf8);
233
#endif
234
448
    EB_FREE_ARRAY(obj);
235
448
}
236
237
/******************************************************
238
 * Cdef Context Constructor
239
 ******************************************************/
240
448
EbErrorType svt_aom_cdef_context_ctor(EbThreadContext* thread_ctx, const EbEncHandle* enc_handle_ptr, int index) {
241
448
    CdefContext* cdef_ctx;
242
448
    EB_CALLOC_ARRAY(cdef_ctx, 1);
243
448
    thread_ctx->priv  = cdef_ctx;
244
448
    thread_ctx->dctor = cdef_context_dctor;
245
246
    // Input/Output System Resource Manager FIFOs
247
448
    cdef_ctx->cdef_input_fifo_ptr  = svt_system_resource_get_consumer_fifo(enc_handle_ptr->dlf_results_resource_ptr,
248
448
                                                                          index);
249
448
    cdef_ctx->cdef_output_fifo_ptr = svt_system_resource_get_producer_fifo(enc_handle_ptr->cdef_results_resource_ptr,
250
448
                                                                           index);
251
252
    // Hoisted per-thread CDEF search scratch (previously large on-stack arrays).
253
448
    EB_MALLOC_ALIGNED_ARRAY(cdef_ctx->tmp_dst, 1 << (MAX_SB_SIZE_LOG2 * 2));
254
448
#if !CDEF_8BITS_PATH || CONFIG_ENABLE_HIGH_BIT_DEPTH
255
448
    EB_MALLOC_ALIGNED_ARRAY(cdef_ctx->inbuf, CDEF_INBUF_SIZE);
256
448
#endif
257
#if CDEF_8BITS_PATH
258
    EB_MALLOC_ALIGNED_ARRAY(cdef_ctx->inbuf8, CDEF_INBUF_SIZE);
259
#endif
260
261
448
    return EB_ErrorNone;
262
448
}
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 = 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
                int32_t ysize = (nvb << mi_high_l2[pli]) + boff + toff;
427
0
                int32_t xsize = (nhb << mi_wide_l2[pli]) + roff + loff;
428
#if CDEF_8BITS_PATH
429
                // 8-bit content (RTC): filter via the boundary-aware hybrid. Build the 8-bit in8
430
                // buffer DIRECTLY from recon (interior AND frame-edge fbs); off-frame halo is left
431
                // as garbage and masked geometrically by the bounded kernel -- no 16-bit sentinel.
432
                const bool native_8bit = !is_16bit;
433
#else
434
0
                const bool native_8bit = false;
435
0
#endif
436
0
#if !CDEF_8BITS_PATH || CONFIG_ENABLE_HIGH_BIT_DEPTH
437
0
                if (!native_8bit) {
438
                    /* We avoid filtering the pixels for which some of the pixels to
439
                   average are outside the frame. We could change the filter instead,
440
                   but it would add special cases for any future vectorization.
441
                   Avoid memset'ting when dirty rect is inside the new one.
442
                   TODO: this could be further optimized - fill out only borders, separate buffers for Y & UV */
443
0
                    bool need_to_reset = toff_prev > toff || loff_prev > loff || ysize < ysize_prev ||
444
0
                        xsize < xsize_prev;
445
0
                    if (need_to_reset) {
446
0
                        uint16_t* p = &in[(-toff_prev * CDEF_BSTRIDE - loff_prev)];
447
0
                        for (int r = 0; r < ysize_prev; r++) {
448
0
                            svt_memset(p, (uint8_t)CDEF_VERY_LARGE, sizeof(p[0]) * xsize_prev);
449
0
                            p += CDEF_BSTRIDE;
450
0
                        }
451
0
                    }
452
0
                    toff_prev  = toff;
453
0
                    loff_prev  = loff;
454
0
                    ysize_prev = ysize;
455
0
                    xsize_prev = xsize;
456
457
0
                    svt_aom_copy_sb8_16(&in[(-toff * CDEF_BSTRIDE - loff)],
458
0
                                        CDEF_BSTRIDE,
459
0
                                        src[pli],
460
0
                                        (lr << mi_high_l2[pli]) - toff,
461
0
                                        (lc << mi_wide_l2[pli]) - loff,
462
0
                                        stride_src[pli],
463
0
                                        ysize,
464
0
                                        xsize,
465
0
                                        is_16bit);
466
0
                }
467
0
#endif
468
#if CDEF_8BITS_PATH
469
                if (native_8bit) {
470
                    // The bounded 8-bit kernel reads only +/-CDEF_HALO around the body, so copy just a
471
                    // HALO-wide halo (not the HBORDER/VBORDER SIMD padding). Off-frame sides have 0 halo;
472
                    // those taps are masked geometrically. svt_cdef_copy_rect8 dispatches on the (now
473
                    // apply-matching) width to a constant-size memcpy.
474
                    const int32_t toff8  = CDEF_HALO * (fbr != 0);
475
                    const int32_t loff8  = CDEF_HALO * (fbc != 0);
476
                    const int32_t boff8  = CDEF_HALO * ((int32_t)fbr + vb_step < nvfb);
477
                    const int32_t roff8  = CDEF_HALO * ((int32_t)fbc + hb_step < nhfb);
478
                    const int32_t ysize8 = (nvb << mi_high_l2[pli]) + boff8 + toff8;
479
                    const int32_t xsize8 = (nhb << mi_wide_l2[pli]) + roff8 + loff8;
480
                    svt_cdef_copy_rect8(&in8[(-toff8 * CDEF_BSTRIDE - loff8)],
481
                                        CDEF_BSTRIDE,
482
                                        src[pli],
483
                                        (lr << mi_high_l2[pli]) - toff8,
484
                                        (lc << mi_wide_l2[pli]) - loff8,
485
                                        stride_src[pli],
486
                                        ysize8,
487
                                        xsize8);
488
                }
489
#endif
490
491
0
                uint8_t subsampling_factor = cdef_ctrls->subsampling_factor;
492
                /*
493
                Cap the subsampling for certain block sizes.
494
495
                The intrinsics process several lines simultaneously, so blocks can only be subsampled
496
                a finite amount before there is no more speed gain.  If the space between processed lines
497
                is too large, the intrinsics will begin accessing memory outside the block.
498
                */
499
0
                switch (plane_bsize[pli]) {
500
0
                case BLOCK_8X8:
501
0
                    subsampling_factor = MIN(subsampling_factor, 4);
502
0
                    break;
503
0
                case BLOCK_8X4:
504
0
                case BLOCK_4X8:
505
0
                    subsampling_factor = MIN(subsampling_factor, 2);
506
0
                    break;
507
0
                case BLOCK_4X4:
508
0
                    subsampling_factor = MIN(subsampling_factor, 1);
509
0
                    break;
510
0
                }
511
512
                /* first cdef stage
513
                 * Perform the pri_filter strength search for the current sub_block
514
                 */
515
0
                for (int gi = 0; gi < first_pass_fs_num; gi++) {
516
                    // Check if chroma filter is set to be tested
517
0
                    if (pli && (cdef_ctrls->default_first_pass_fs_uv[gi] == -1)) {
518
0
                        pcs->mse_seg[1][fb_idx][gi] = default_mse_uv * 64;
519
0
                        continue;
520
0
                    }
521
522
#if CDEF_8BITS_PATH
523
                    if (native_8bit) {
524
                        svt_cdef_filter_fb_lbd((uint8_t*)tmp_dst,
525
                                               0,
526
                                               in8,
527
                                               toff == 0,
528
                                               loff == 0,
529
                                               boff == 0,
530
                                               roff == 0,
531
                                               nvb << mi_high_l2[pli],
532
                                               nhb << mi_wide_l2[pli],
533
                                               xdec[pli],
534
                                               ydec[pli],
535
                                               *dir,
536
                                               &dirinit,
537
                                               *var,
538
                                               pli,
539
                                               dlist,
540
                                               cdef_count,
541
                                               cdef_ctrls->default_first_pass_fs[gi],
542
                                               damping,
543
                                               coeff_shift,
544
                                               subsampling_factor);
545
                    } // native_8bit
546
#if !CDEF_8BITS_PATH || CONFIG_ENABLE_HIGH_BIT_DEPTH
547
                    else
548
#endif
549
#endif
550
0
#if !CDEF_8BITS_PATH || CONFIG_ENABLE_HIGH_BIT_DEPTH
551
0
                        svt_cdef_filter_fb(is_16bit ? NULL : (uint8_t*)tmp_dst,
552
0
                                           is_16bit ? tmp_dst : NULL,
553
0
                                           0,
554
0
                                           in,
555
0
                                           xdec[pli],
556
0
                                           ydec[pli],
557
0
                                           *dir,
558
0
                                           &dirinit,
559
0
                                           *var,
560
0
                                           pli,
561
0
                                           dlist,
562
0
                                           cdef_count,
563
0
                                           cdef_ctrls->default_first_pass_fs[gi],
564
0
                                           damping,
565
0
                                           coeff_shift,
566
0
                                           subsampling_factor);
567
0
#endif
568
0
                    uint64_t curr_mse = compute_cdef_dist(
569
0
                        ref[pli],
570
0
                        (lr << mi_high_l2[pli]) * stride_ref[pli] + (lc << mi_wide_l2[pli]),
571
0
                        stride_ref[pli],
572
0
                        (uint8_t*)tmp_dst,
573
0
                        dlist,
574
0
                        cdef_count,
575
0
                        (BlockSize)plane_bsize[pli],
576
0
                        coeff_shift,
577
0
                        subsampling_factor,
578
0
                        is_16bit);
579
580
0
                    if (pli < 2) {
581
0
                        pcs->mse_seg[pli][fb_idx][gi] = curr_mse * subsampling_factor;
582
0
                    } else {
583
0
                        pcs->mse_seg[1][fb_idx][gi] += (curr_mse * subsampling_factor);
584
0
                    }
585
0
                }
586
587
                /* second cdef stage
588
                 * Perform the sec_filter strength search for the current sub_block
589
                 */
590
0
                for (int gi = first_pass_fs_num; gi < first_pass_fs_num + default_second_pass_fs_num; gi++) {
591
                    // Check if chroma filter is set to be tested
592
0
                    if (pli && (cdef_ctrls->default_second_pass_fs_uv[gi - first_pass_fs_num] == -1)) {
593
0
                        pcs->mse_seg[1][fb_idx][gi] = default_mse_uv * 64;
594
0
                        continue;
595
0
                    }
596
597
#if CDEF_8BITS_PATH
598
                    if (native_8bit) {
599
                        svt_cdef_filter_fb_lbd((uint8_t*)tmp_dst,
600
                                               0,
601
                                               in8,
602
                                               toff == 0,
603
                                               loff == 0,
604
                                               boff == 0,
605
                                               roff == 0,
606
                                               nvb << mi_high_l2[pli],
607
                                               nhb << mi_wide_l2[pli],
608
                                               xdec[pli],
609
                                               ydec[pli],
610
                                               *dir,
611
                                               &dirinit,
612
                                               *var,
613
                                               pli,
614
                                               dlist,
615
                                               cdef_count,
616
                                               cdef_ctrls->default_second_pass_fs[gi - first_pass_fs_num],
617
                                               damping,
618
                                               coeff_shift,
619
                                               subsampling_factor);
620
                    } // native_8bit
621
#if !CDEF_8BITS_PATH || CONFIG_ENABLE_HIGH_BIT_DEPTH
622
                    else
623
#endif
624
#endif
625
0
#if !CDEF_8BITS_PATH || CONFIG_ENABLE_HIGH_BIT_DEPTH
626
0
                        svt_cdef_filter_fb(is_16bit ? NULL : (uint8_t*)tmp_dst,
627
0
                                           is_16bit ? tmp_dst : NULL,
628
0
                                           0,
629
0
                                           in,
630
0
                                           xdec[pli],
631
0
                                           ydec[pli],
632
0
                                           *dir,
633
0
                                           &dirinit,
634
0
                                           *var,
635
0
                                           pli,
636
0
                                           dlist,
637
0
                                           cdef_count,
638
0
                                           cdef_ctrls->default_second_pass_fs[gi - first_pass_fs_num],
639
0
                                           damping,
640
0
                                           coeff_shift,
641
0
                                           subsampling_factor);
642
0
#endif
643
0
                    uint64_t curr_mse = compute_cdef_dist(
644
0
                        ref[pli],
645
0
                        (lr << mi_high_l2[pli]) * stride_ref[pli] + (lc << mi_wide_l2[pli]),
646
0
                        stride_ref[pli],
647
0
                        (uint8_t*)tmp_dst,
648
0
                        dlist,
649
0
                        cdef_count,
650
0
                        (BlockSize)plane_bsize[pli],
651
0
                        coeff_shift,
652
0
                        subsampling_factor,
653
0
                        is_16bit);
654
655
0
                    if (pli < 2) {
656
0
                        pcs->mse_seg[pli][fb_idx][gi] = curr_mse * subsampling_factor;
657
0
                    } else {
658
0
                        pcs->mse_seg[1][fb_idx][gi] += (curr_mse * subsampling_factor);
659
0
                    }
660
0
                }
661
0
            }
662
0
        }
663
0
    }
664
0
}
665
666
/******************************************************
667
 * CDEF Kernel
668
 ******************************************************/
669
896
EbErrorType svt_aom_cdef_kernel_iter(void* context) {
670
    // Context & SCS & PCS
671
896
    CdefContext*        context_ptr = (CdefContext*)context;
672
896
    PictureControlSet*  pcs;
673
896
    SequenceControlSet* scs;
674
675
    //// Input
676
896
    EbObjectWrapper* dlf_results_wrapper;
677
896
    DlfResults*      dlf_results;
678
679
    //// Output
680
896
    EbObjectWrapper* cdef_results_wrapper;
681
682
896
    FrameHeader* frm_hdr;
683
684
    // Get DLF Results
685
896
    EB_GET_FULL_OBJECT(context_ptr->cdef_input_fifo_ptr, &dlf_results_wrapper);
686
687
448
    dlf_results                   = (DlfResults*)dlf_results_wrapper->object_ptr;
688
448
    pcs                           = (PictureControlSet*)dlf_results->pcs_wrapper->object_ptr;
689
448
    PictureParentControlSet* ppcs = pcs->ppcs;
690
448
    scs                           = pcs->scs;
691
692
448
    bool       is_16bit                   = scs->is_16bit_pipeline;
693
448
    Av1Common* cm                         = pcs->ppcs->av1_cm;
694
448
    frm_hdr                               = &pcs->ppcs->frm_hdr;
695
448
    CdefSearchControls* cdef_search_ctrls = &pcs->ppcs->cdef_search_ctrls;
696
448
    if (!cdef_search_ctrls->use_reference_cdef_fs && !cdef_search_ctrls->use_qp_strength) {
697
0
        if (scs->seq_header.cdef_level && pcs->ppcs->cdef_level) {
698
0
            cdef_seg_search(context_ptr, pcs, scs, dlf_results->segment_index);
699
0
        }
700
0
    }
701
    //all seg based search is done. update total processed segments. if all done, finish the search and perfrom application.
702
448
    svt_block_on_mutex(pcs->cdef_search_mutex);
703
704
448
    pcs->tot_seg_searched_cdef++;
705
448
    if (pcs->tot_seg_searched_cdef == pcs->cdef_segments_total_count) {
706
448
        pcs->cdef_dist_dev = -1;
707
448
        if (scs->seq_header.cdef_level && pcs->ppcs->cdef_level) {
708
243
            finish_cdef_search(pcs);
709
243
            if (ppcs->enable_restoration || pcs->ppcs->is_ref || scs->static_config.recon_enabled) {
710
                // Do application iff there are non-zero filters
711
0
                if (frm_hdr->cdef_params.cdef_y_strength[0] != 0 || frm_hdr->cdef_params.cdef_uv_strength[0] != 0 ||
712
0
                    pcs->ppcs->nb_cdef_strengths != 1) {
713
0
                    svt_av1_cdef_frame(scs, pcs);
714
0
                }
715
0
            }
716
243
        } else {
717
205
            frm_hdr->cdef_params.cdef_bits           = 0;
718
205
            frm_hdr->cdef_params.cdef_y_strength[0]  = 0;
719
205
            pcs->ppcs->nb_cdef_strengths             = 1;
720
205
            frm_hdr->cdef_params.cdef_uv_strength[0] = 0;
721
205
        }
722
723
448
        if (pcs->ppcs->nb_cdef_strengths == 1 && frm_hdr->cdef_params.cdef_y_strength[0] == 0 &&
724
230
            frm_hdr->cdef_params.cdef_uv_strength[0] == 0) {
725
226
            pcs->cdef_dist_dev = 0;
726
226
        }
727
728
        //restoration prep
729
448
        bool is_lr = ppcs->enable_restoration && frm_hdr->allow_intrabc == 0;
730
448
        if (is_lr) {
731
0
            svt_av1_loop_restoration_save_boundary_lines(cm->frame_to_show, cm, 1);
732
0
            if (is_16bit) {
733
0
                set_unscaled_input_16bit(pcs);
734
0
            }
735
0
        }
736
737
        // ------- start: Normative upscaling - super-resolution tool
738
448
        if (frm_hdr->allow_intrabc == 0 && pcs->ppcs->frame_superres_enabled) {
739
0
            svt_av1_superres_upscale_frame(cm, pcs, scs);
740
0
        }
741
448
        if (scs->static_config.resize_mode != RESIZE_NONE) {
742
0
            EbPictureBufferDesc* recon = NULL;
743
0
            svt_aom_get_recon_pic(pcs, &recon, is_16bit);
744
0
            recon->width  = pcs->ppcs->render_width;
745
0
            recon->height = pcs->ppcs->render_height;
746
0
            if (is_lr) {
747
0
                EbPictureBufferDesc* input_pic = is_16bit ? pcs->input_frame16bit : pcs->ppcs->enhanced_unscaled_pic;
748
749
0
                svt_aom_assert_err(pcs->scaled_input_pic == NULL, "pcs_ptr->scaled_input_pic is not desctoried!");
750
0
                EbPictureBufferDesc* scaled_input_pic = NULL;
751
                // downscale input picture if recon is resized
752
0
                bool is_resized = recon->width != input_pic->width || recon->height != input_pic->height;
753
0
                if (is_resized) {
754
0
                    superres_params_type spr_params = {recon->width, recon->height, 0};
755
0
                    svt_aom_downscaled_source_buffer_desc_ctor(&scaled_input_pic, input_pic, spr_params);
756
0
                    svt_aom_resize_frame(input_pic,
757
0
                                         scaled_input_pic,
758
0
                                         scs->static_config.encoder_bit_depth,
759
0
                                         av1_num_planes(&scs->seq_header.color_config),
760
0
                                         scs->subsampling_x,
761
0
                                         scs->subsampling_y,
762
0
                                         input_pic->packed_flag,
763
0
                                         PICTURE_BUFFER_DESC_FULL_MASK,
764
0
                                         0); // is_2bcompress
765
0
                    pcs->scaled_input_pic = scaled_input_pic;
766
0
                }
767
0
            }
768
0
        }
769
        // ------- end: Normative upscaling - super-resolution tool
770
771
448
        pcs->rest_segments_column_count = scs->rest_segment_column_count;
772
448
        pcs->rest_segments_row_count    = scs->rest_segment_row_count;
773
448
        pcs->rest_segments_total_count  = (uint16_t)(pcs->rest_segments_column_count * pcs->rest_segments_row_count);
774
448
        pcs->tot_seg_searched_rest      = 0;
775
448
        pcs->ppcs->av1_cm->use_boundaries_in_rest_search = scs->use_boundaries_in_rest_search;
776
448
        pcs->rest_extend_flag[0]                         = false;
777
448
        pcs->rest_extend_flag[1]                         = false;
778
448
        pcs->rest_extend_flag[2]                         = false;
779
780
448
        uint32_t segment_index;
781
896
        for (segment_index = 0; segment_index < pcs->rest_segments_total_count; ++segment_index) {
782
            // Get Empty Cdef Results to Rest
783
448
            svt_get_empty_object(context_ptr->cdef_output_fifo_ptr, &cdef_results_wrapper);
784
448
            CdefResults* cdef_results   = (struct CdefResults*)cdef_results_wrapper->object_ptr;
785
448
            cdef_results->pcs_wrapper   = dlf_results->pcs_wrapper;
786
448
            cdef_results->segment_index = segment_index;
787
            // Post Cdef Results
788
448
            svt_post_full_object(cdef_results_wrapper);
789
448
        }
790
448
    }
791
448
    svt_release_mutex(pcs->cdef_search_mutex);
792
793
    // Release Dlf Results
794
448
    svt_release_object(dlf_results_wrapper);
795
796
448
    return EB_ErrorNone;
797
896
}
798
799
448
void* svt_aom_cdef_kernel(void* input_ptr) {
800
448
    EbThreadContext* thread_ctx = (EbThreadContext*)input_ptr;
801
896
    for (;;) {
802
896
        EbErrorType err = svt_aom_cdef_kernel_iter(thread_ctx->priv);
803
896
        if (err == EB_NoErrorFifoShutdown) {
804
448
            return NULL;
805
448
        }
806
896
    }
807
0
    return NULL;
808
448
}