Coverage Report

Created: 2026-05-16 06:41

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
474
static void dlf_context_dctor(EbPtr p) {
26
474
    EbThreadContext* thread_ctx = (EbThreadContext*)p;
27
474
    DlfContext*      obj        = (DlfContext*)thread_ctx->priv;
28
474
    EB_FREE_ARRAY(obj);
29
474
}
30
31
/******************************************************
32
 * Dlf Context Constructor
33
 ******************************************************/
34
474
EbErrorType svt_aom_dlf_context_ctor(EbThreadContext* thread_ctx, const EbEncHandle* enc_handle_ptr, int index) {
35
474
    DlfContext* context_ptr;
36
474
    EB_CALLOC_ARRAY(context_ptr, 1);
37
474
    thread_ctx->priv  = context_ptr;
38
474
    thread_ctx->dctor = dlf_context_dctor;
39
40
    // Input/Output System Resource Manager FIFOs
41
474
    context_ptr->dlf_input_fifo_ptr = svt_system_resource_get_consumer_fifo(
42
474
        enc_handle_ptr->enc_dec_results_resource_ptr, index);
43
474
    context_ptr->dlf_output_fifo_ptr = svt_system_resource_get_producer_fifo(enc_handle_ptr->dlf_results_resource_ptr,
44
474
                                                                             index);
45
474
    return EB_ErrorNone;
46
474
}
47
48
/******************************************************
49
 * Dlf Kernel
50
 ******************************************************/
51
948
EbErrorType svt_aom_dlf_kernel_iter(void* context) {
52
    // Context & SCS & PCS
53
948
    DlfContext*         context_ptr = (DlfContext*)context;
54
948
    PictureControlSet*  pcs;
55
948
    SequenceControlSet* scs;
56
57
    //// Input
58
948
    EbObjectWrapper* enc_dec_results_wrapper;
59
948
    EncDecResults*   enc_dec_results;
60
61
    //// Output
62
948
    EbObjectWrapper* dlf_results_wrapper;
63
64
    // Get EncDec Results
65
948
    EB_GET_FULL_OBJECT(context_ptr->dlf_input_fifo_ptr, &enc_dec_results_wrapper);
66
67
474
    enc_dec_results               = (EncDecResults*)enc_dec_results_wrapper->object_ptr;
68
474
    pcs                           = (PictureControlSet*)enc_dec_results->pcs_wrapper->object_ptr;
69
474
    PictureParentControlSet* ppcs = pcs->ppcs;
70
474
    scs                           = pcs->scs;
71
72
474
    bool is_16bit = scs->is_16bit_pipeline;
73
474
    if (is_16bit && 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
474
    pcs->zero_filt_sse             = -1;
91
474
    pcs->best_filt_sse             = -1;
92
474
    pcs->dlf_dist_dev              = -1;
93
474
    FrameHeader*   frm_hdr         = &pcs->ppcs->frm_hdr;
94
474
    bool           dlf_enable_flag = (bool)pcs->ppcs->dlf_ctrls.enabled;
95
474
    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
474
    if ((dlf_enable_flag && !pcs->ppcs->dlf_ctrls.sb_based_dlf) ||
98
474
        (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, LPF_PICK_FROM_FULL_IMAGE);
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
0
        svt_av1_loop_filter_frame(recon_buffer, pcs, 0, 3);
115
0
        if (pcs->best_filt_sse == -1 &&
116
0
            (frm_hdr->loop_filter_params.filter_level[0] || frm_hdr->loop_filter_params.filter_level[1])) {
117
0
            pcs->best_filt_sse = picture_sse_calculations(pcs, recon_buffer, /*plane*/ 0);
118
0
        }
119
0
        pcs->dlf_dist_dev = pcs->zero_filt_sse == 0 ||
120
0
                !(frm_hdr->loop_filter_params.filter_level[0] || frm_hdr->loop_filter_params.filter_level[1])
121
0
            ? 0
122
0
            : (int32_t)(1000 - ((1000 * pcs->best_filt_sse) / pcs->zero_filt_sse));
123
0
    }
124
125
    //pre-cdef prep
126
474
    {
127
474
        EbPictureBufferDesc* recon_pic;
128
474
        svt_aom_get_recon_pic(pcs, &recon_pic, is_16bit);
129
130
474
        Av1Common* cm = pcs->ppcs->av1_cm;
131
474
        if (ppcs->enable_restoration) {
132
0
            svt_aom_link_eb_to_aom_buffer_desc(
133
0
                recon_pic, cm->frame_to_show, scs->max_input_pad_right, scs->max_input_pad_bottom, is_16bit);
134
0
            svt_av1_loop_restoration_save_boundary_lines(cm->frame_to_show, cm, 0);
135
0
        }
136
137
474
        if (scs->seq_header.cdef_level && pcs->ppcs->cdef_level) {
138
274
            pcs->cdef_input_recon[0] = recon_pic->y_buffer;
139
274
            pcs->cdef_input_recon[1] = recon_pic->u_buffer;
140
274
            pcs->cdef_input_recon[2] = recon_pic->v_buffer;
141
142
274
            EbPictureBufferDesc* input_pic = is_16bit ? pcs->input_frame16bit : pcs->ppcs->enhanced_pic;
143
274
            pcs->cdef_input_source[0]      = input_pic->y_buffer;
144
274
            pcs->cdef_input_source[1]      = input_pic->u_buffer;
145
274
            pcs->cdef_input_source[2]      = input_pic->v_buffer;
146
274
        }
147
474
    }
148
149
474
    pcs->cdef_segments_column_count = scs->cdef_segment_column_count;
150
474
    pcs->cdef_segments_row_count    = scs->cdef_segment_row_count;
151
474
    pcs->cdef_segments_total_count  = (uint16_t)(pcs->cdef_segments_column_count * pcs->cdef_segments_row_count);
152
474
    pcs->tot_seg_searched_cdef      = 0;
153
474
    uint32_t segment_index;
154
155
948
    for (segment_index = 0; segment_index < pcs->cdef_segments_total_count; ++segment_index) {
156
        // Get Empty DLF Results to Cdef
157
474
        svt_get_empty_object(context_ptr->dlf_output_fifo_ptr, &dlf_results_wrapper);
158
474
        struct DlfResults* dlf_results = (struct DlfResults*)dlf_results_wrapper->object_ptr;
159
474
        dlf_results->pcs_wrapper       = enc_dec_results->pcs_wrapper;
160
474
        dlf_results->segment_index     = segment_index;
161
        // Post DLF Results
162
474
        svt_post_full_object(dlf_results_wrapper);
163
474
    }
164
165
    // Release EncDec Results
166
474
    svt_release_object(enc_dec_results_wrapper);
167
168
474
    return EB_ErrorNone;
169
948
}
170
171
474
void* svt_aom_dlf_kernel(void* input_ptr) {
172
474
    EbThreadContext* thread_ctx = (EbThreadContext*)input_ptr;
173
948
    for (;;) {
174
948
        EbErrorType err = svt_aom_dlf_kernel_iter(thread_ctx->priv);
175
948
        if (err == EB_NoErrorFifoShutdown) {
176
474
            return NULL;
177
474
        }
178
948
    }
179
0
    return NULL;
180
474
}