Coverage Report

Created: 2026-10-28 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/svt-av1/Source/Lib/Codec/dlf_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 "enc_handle.h"
15
#include "dlf_process.h"
16
#include "enc_dec_results.h"
17
#include "reference_object.h"
18
#include "deblocking_filter.h"
19
#include "definitions.h"
20
#include "sequence_control_set.h"
21
#include "pcs.h"
22
#include "aom_dsp_rtcd.h"
23
#include "pic_operators.h"
24
25
604
static void dlf_context_dctor(EbPtr p) {
26
604
    EbThreadContext* thread_ctx = (EbThreadContext*)p;
27
604
    DlfContext*      obj        = (DlfContext*)thread_ctx->priv;
28
604
    EB_FREE_ARRAY(obj);
29
604
}
30
31
/******************************************************
32
 * Dlf Context Constructor
33
 ******************************************************/
34
604
EbErrorType svt_aom_dlf_context_ctor(EbThreadContext* thread_ctx, const EbEncHandle* enc_handle_ptr, int index) {
35
604
    DlfContext* context_ptr;
36
604
    EB_CALLOC_ARRAY(context_ptr, 1);
37
604
    thread_ctx->priv  = context_ptr;
38
604
    thread_ctx->dctor = dlf_context_dctor;
39
40
    // Input/Output System Resource Manager FIFOs
41
604
    context_ptr->dlf_input_fifo_ptr = svt_system_resource_get_consumer_fifo(
42
604
        enc_handle_ptr->enc_dec_results_resource_ptr, index);
43
604
    context_ptr->dlf_output_fifo_ptr = svt_system_resource_get_producer_fifo(enc_handle_ptr->dlf_results_resource_ptr,
44
604
                                                                             index);
45
604
    return EB_ErrorNone;
46
604
}
47
48
/******************************************************
49
 * Dlf Kernel
50
 ******************************************************/
51
1.20k
EbErrorType svt_aom_dlf_kernel_iter(void* context) {
52
    // Context & SCS & PCS
53
1.20k
    DlfContext*         context_ptr = (DlfContext*)context;
54
1.20k
    PictureControlSet*  pcs;
55
1.20k
    SequenceControlSet* scs;
56
57
    //// Input
58
1.20k
    EbObjectWrapper* enc_dec_results_wrapper;
59
1.20k
    EncDecResults*   enc_dec_results;
60
61
    //// Output
62
1.20k
    EbObjectWrapper* dlf_results_wrapper;
63
64
    // Get EncDec Results
65
1.20k
    EB_GET_FULL_OBJECT(context_ptr->dlf_input_fifo_ptr, &enc_dec_results_wrapper);
66
67
604
    enc_dec_results               = (EncDecResults*)enc_dec_results_wrapper->object_ptr;
68
604
    pcs                           = (PictureControlSet*)enc_dec_results->pcs_wrapper->object_ptr;
69
604
    PictureParentControlSet* ppcs = pcs->ppcs;
70
604
    scs                           = pcs->scs;
71
72
604
    bool is_16bit = SVT_EFFECTIVE_IS_16BIT_PIPELINE(scs->is_16bit_pipeline);
73
604
    if (is_16bit && SVT_EFFECTIVE_BIT_DEPTH(scs->static_config.encoder_bit_depth) == EB_EIGHT_BIT) {
74
0
        svt_aom_convert_pic_8bit_to_16bit(pcs->ppcs->enhanced_pic,
75
0
                                          pcs->input_frame16bit,
76
0
                                          pcs->ppcs->scs->subsampling_x,
77
0
                                          pcs->ppcs->scs->subsampling_y);
78
        // convert 8-bit recon to 16-bit for it bypass encdec process
79
0
        if (pcs->pic_bypass_encdec) {
80
0
            EbPictureBufferDesc* recon_pic;
81
0
            EbPictureBufferDesc* recon_picture_16bit_ptr;
82
0
            svt_aom_get_recon_pic(pcs, &recon_pic, 0);
83
0
            svt_aom_get_recon_pic(pcs, &recon_picture_16bit_ptr, 1);
84
0
            svt_aom_convert_pic_8bit_to_16bit(
85
0
                recon_pic, recon_picture_16bit_ptr, pcs->ppcs->scs->subsampling_x, pcs->ppcs->scs->subsampling_y);
86
0
        }
87
0
    }
88
    // Initialize dev to negative value to indicate it was not computed.
89
    // SB-based DLF does not compute the distortion
90
604
    pcs->zero_filt_sse             = -1;
91
604
    pcs->best_filt_sse             = -1;
92
604
    pcs->dlf_dist_dev              = -1;
93
604
    FrameHeader*   frm_hdr         = &pcs->ppcs->frm_hdr;
94
604
    bool           dlf_enable_flag = (bool)pcs->ppcs->dlf_ctrls.enabled;
95
604
    const uint16_t tg_count        = pcs->ppcs->tile_group_cols * pcs->ppcs->tile_group_rows;
96
    // Move sb level lf to here if tile_parallel
97
604
    if ((dlf_enable_flag && !pcs->ppcs->dlf_ctrls.sb_based_dlf) ||
98
604
        (dlf_enable_flag && pcs->ppcs->dlf_ctrls.sb_based_dlf && tg_count > 1)) {
99
0
        EbPictureBufferDesc* recon_buffer;
100
0
        svt_aom_get_recon_pic(pcs, &recon_buffer, is_16bit);
101
0
        svt_av1_loop_filter_init(pcs);
102
0
        svt_av1_pick_filter_level((EbPictureBufferDesc*)pcs->ppcs->enhanced_pic, pcs);
103
0
        if (pcs->zero_filt_sse == -1 &&
104
0
            (frm_hdr->loop_filter_params.filter_level[0] || frm_hdr->loop_filter_params.filter_level[1])) {
105
0
            pcs->zero_filt_sse = picture_sse_calculations(pcs, recon_buffer, /*plane*/ 0);
106
0
            if (pcs->best_filt_sse != -1 && pcs->zero_filt_sse <= pcs->best_filt_sse) {
107
0
                frm_hdr->loop_filter_params.filter_level[0] = 0;
108
0
                frm_hdr->loop_filter_params.filter_level[1] = 0;
109
0
                frm_hdr->loop_filter_params.filter_level_u  = 0;
110
0
                frm_hdr->loop_filter_params.filter_level_v  = 0;
111
0
            }
112
0
        }
113
114
        // The search did not measure the filtered SSE (e.g. levels taken from the references), so it is
115
        // computed below from the filtered recon
116
0
        const bool need_filt_sse = pcs->best_filt_sse == -1 &&
117
0
            (frm_hdr->loop_filter_params.filter_level[0] || frm_hdr->loop_filter_params.filter_level[1]);
118
        // The levels are final; only filter the recon if something uses it
119
0
        if (svt_av1_lf_recon_needed(pcs) || need_filt_sse) {
120
0
            svt_av1_loop_filter_frame(recon_buffer, pcs, 0, 3);
121
0
        }
122
0
        if (need_filt_sse) {
123
0
            pcs->best_filt_sse = picture_sse_calculations(pcs, recon_buffer, /*plane*/ 0);
124
0
        }
125
0
        pcs->dlf_dist_dev = pcs->zero_filt_sse == 0 ||
126
0
                !(frm_hdr->loop_filter_params.filter_level[0] || frm_hdr->loop_filter_params.filter_level[1])
127
0
            ? 0
128
0
            : (int32_t)(1000 - ((1000 * pcs->best_filt_sse) / pcs->zero_filt_sse));
129
0
    }
130
131
    //pre-cdef prep
132
604
    {
133
604
        EbPictureBufferDesc* recon_pic;
134
604
        svt_aom_get_recon_pic(pcs, &recon_pic, is_16bit);
135
136
604
        Av1Common* cm = pcs->ppcs->av1_cm;
137
604
        if (SVT_EFFECTIVE_RESTORATION(ppcs->enable_restoration)) {
138
0
            svt_aom_link_eb_to_aom_buffer_desc(
139
0
                recon_pic, cm->frame_to_show, scs->max_input_pad_right, scs->max_input_pad_bottom, is_16bit);
140
0
            svt_av1_loop_restoration_save_boundary_lines(cm->frame_to_show, cm, 0);
141
0
        }
142
143
604
        if (scs->seq_header.cdef_level && pcs->ppcs->cdef_level) {
144
286
            pcs->cdef_input_recon[0] = recon_pic->y_buffer;
145
286
            pcs->cdef_input_recon[1] = recon_pic->u_buffer;
146
286
            pcs->cdef_input_recon[2] = recon_pic->v_buffer;
147
148
286
            EbPictureBufferDesc* input_pic = is_16bit ? pcs->input_frame16bit : pcs->ppcs->enhanced_pic;
149
286
            pcs->cdef_input_source[0]      = input_pic->y_buffer;
150
286
            pcs->cdef_input_source[1]      = input_pic->u_buffer;
151
286
            pcs->cdef_input_source[2]      = input_pic->v_buffer;
152
286
        }
153
604
    }
154
155
604
    pcs->cdef_segments_column_count = scs->cdef_segment_column_count;
156
604
    pcs->cdef_segments_row_count    = scs->cdef_segment_row_count;
157
604
    pcs->cdef_segments_total_count  = (uint16_t)(pcs->cdef_segments_column_count * pcs->cdef_segments_row_count);
158
604
    pcs->tot_seg_searched_cdef      = 0;
159
604
    uint32_t segment_index;
160
161
1.20k
    for (segment_index = 0; segment_index < pcs->cdef_segments_total_count; ++segment_index) {
162
        // Get Empty DLF Results to Cdef
163
604
        svt_get_empty_object(context_ptr->dlf_output_fifo_ptr, &dlf_results_wrapper);
164
604
        struct DlfResults* dlf_results = (struct DlfResults*)dlf_results_wrapper->object_ptr;
165
604
        dlf_results->pcs_wrapper       = enc_dec_results->pcs_wrapper;
166
604
        dlf_results->segment_index     = segment_index;
167
        // Post DLF Results
168
604
        svt_post_full_object(dlf_results_wrapper);
169
604
    }
170
171
    // Release EncDec Results
172
604
    svt_release_object(enc_dec_results_wrapper);
173
174
604
    return EB_ErrorNone;
175
1.20k
}
176
177
604
void* svt_aom_dlf_kernel(void* input_ptr) {
178
604
    EbThreadContext* thread_ctx = (EbThreadContext*)input_ptr;
179
1.20k
    for (;;) {
180
1.20k
        EbErrorType err = svt_aom_dlf_kernel_iter(thread_ctx->priv);
181
1.20k
        if (err == EB_NoErrorFifoShutdown) {
182
604
            return NULL;
183
604
        }
184
1.20k
    }
185
0
    return NULL;
186
604
}