Coverage Report

Created: 2025-07-23 06:28

/src/libhevc/encoder/est_sad.c
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Copyright (C) 2018 The Android Open Source Project
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at:
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 *****************************************************************************
18
 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19
*/
20
/*!
21
******************************************************************************
22
* \file est_sad.c
23
*
24
* \brief
25
*    This file contain sad estimation related functions
26
*
27
* \date
28
*
29
* \author
30
*    ittiam
31
*
32
******************************************************************************
33
*/
34
/*****************************************************************************/
35
/* File Includes                                                             */
36
/*****************************************************************************/
37
/* User include files */
38
#include "ittiam_datatypes.h"
39
#include "rc_common.h"
40
#include "rc_cntrl_param.h"
41
#include "var_q_operator.h"
42
#include "mem_req_and_acq.h"
43
#include "est_sad.h"
44
45
typedef struct est_sad_t
46
{
47
    WORD32 i4_use_est_intra_sad;
48
    UWORD32 au4_prev_frm_sad[MAX_PIC_TYPE]; /* Previous frame SAD */
49
    UWORD32 u4_n_p_frm_ifi_avg_sad; /* Current (nth) ifi average P frame SAD */
50
    UWORD32 u4_n_1_p_frm_ifi_avg_sad; /* (n-1)th ifi average P frame SAD */
51
    UWORD32 u4_n_2_p_frm_ifi_avg_sad; /* (n-2)th ifi average P frame SAD */
52
    WORD32 i4_num_ifi_encoded; /* number of ifi encoded till now */
53
    WORD32 i4_num_p_frm_in_cur_ifi; /* number of P frames in the current IFI */
54
} est_sad_t;
55
56
#if NON_STEADSTATE_CODE
57
WORD32 est_sad_num_fill_use_free_memtab(
58
    est_sad_t **pps_est_sad, itt_memtab_t *ps_memtab, ITT_FUNC_TYPE_E e_func_type)
59
57.5k
{
60
57.5k
    WORD32 i4_mem_tab_idx = 0;
61
57.5k
    static est_sad_t s_est_sad;
62
63
    /* Hack for al alloc, during which we dont have any state memory.
64
      Dereferencing can cause issues */
65
57.5k
    if(e_func_type == GET_NUM_MEMTAB || e_func_type == FILL_MEMTAB)
66
49.3k
        (*pps_est_sad) = &s_est_sad;
67
68
    /*for src rate control state structure*/
69
57.5k
    if(e_func_type != GET_NUM_MEMTAB)
70
24.6k
    {
71
24.6k
        fill_memtab(
72
24.6k
            &ps_memtab[i4_mem_tab_idx], sizeof(est_sad_t), MEM_TAB_ALIGNMENT, PERSISTENT, DDR);
73
24.6k
        use_or_fill_base(&ps_memtab[0], (void **)pps_est_sad, e_func_type);
74
24.6k
    }
75
57.5k
    i4_mem_tab_idx++;
76
77
57.5k
    return (i4_mem_tab_idx);
78
57.5k
}
79
#endif /* #if NON_STEADSTATE_CODE */
80
/****************************************************************************
81
Function Name : init_est_sad
82
Description   :
83
Inputs        : ps_est_sad
84
                i4_use_est_intra_sad
85
86
Revision History:
87
DD MM YYYY   Author(s)       Changes (Describe the changes made)
88
 *****************************************************************************/
89
void init_est_sad(est_sad_t *ps_est_sad, WORD32 i4_use_est_intra_sad)
90
13.5k
{
91
13.5k
    WORD32 i;
92
13.5k
    ps_est_sad->i4_use_est_intra_sad = i4_use_est_intra_sad;
93
94
135k
    for(i = 0; i < MAX_PIC_TYPE; i++)
95
122k
        ps_est_sad->au4_prev_frm_sad[i] = 0;
96
97
13.5k
    ps_est_sad->u4_n_p_frm_ifi_avg_sad = 0;
98
13.5k
    ps_est_sad->u4_n_1_p_frm_ifi_avg_sad = 0;
99
13.5k
    ps_est_sad->u4_n_2_p_frm_ifi_avg_sad = 0;
100
13.5k
    ps_est_sad->i4_num_ifi_encoded = 0;
101
13.5k
    ps_est_sad->i4_num_p_frm_in_cur_ifi = 0;
102
13.5k
}
103
/****************************************************************************
104
Function Name : reset_est_sad
105
Description   :
106
Inputs        : ps_est_sad
107
108
Revision History:
109
DD MM YYYY   Author(s)       Changes (Describe the changes made)
110
 *****************************************************************************/
111
void reset_est_sad(est_sad_t *ps_est_sad)
112
8.92k
{
113
8.92k
    init_est_sad(ps_est_sad, ps_est_sad->i4_use_est_intra_sad);
114
8.92k
}
115
116
/****************************************************************************
117
Function Name : get_est_sad
118
Description   :
119
Inputs        : ps_est_sad
120
121
Revision History:
122
DD MM YYYY   Author(s)       Changes (Describe the changes made)
123
 *****************************************************************************/
124
/*
125
Get estimated SAD can be called at any point. The various use cases are:
126
1) When a I frame is getting encoded,
127
     - get the estimated of P => No issues since we use the last coded P frame value
128
     - get estimated of I => This call for two cases:
129
                   => a) if num_ifi_encoded is less than 2
130
                         then return the previous encoded I frame sad
131
                   => b) if num_ifi_encoded is more than 2, then we scale
132
                         the prev I sad by the ratio of (n-1) ifi P to n-2 ifi P
133
2) When P frame is getting encoded,
134
    - get the estimated of P =>  No issues since we use the last coded P frame value
135
    - get the estimated of I => Simillar to I we have two cases. To handle the b) case
136
                                extra logic had to introduced using
137
                                u1_is_n_1_p_frm_ifi_avg_sad_usable flag
138
*/
139
UWORD32 get_est_sad(est_sad_t *ps_est_sad, picture_type_e e_pic_type)
140
1.09M
{
141
1.09M
    if(ps_est_sad->i4_use_est_intra_sad)
142
0
    {
143
0
        UWORD32 u4_estimated_sad;
144
0
        if(e_pic_type == P_PIC)
145
0
        {
146
0
            u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[P_PIC];
147
0
        }
148
0
        else if(e_pic_type == B_PIC)
149
0
        {
150
0
            u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[B_PIC];
151
0
        }
152
0
        else
153
0
        {
154
0
            if(ps_est_sad->i4_num_ifi_encoded < 2)
155
0
            {
156
                /* Only one IFI has been encoded and so use the previous I frames SAD */
157
0
                u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[I_PIC];
158
0
            }
159
0
            else
160
0
            {
161
                /* Since the n-1 'P' frame IFI would have just accumulated the frame sads
162
                we average it out here */
163
0
                UWORD32 u4_n_1_p_frm_ifi_avg_sad, u4_n_2_p_frm_ifi_avg_sad;
164
0
                number_t vq_n_1_p_frm_ifi_avg_sad, vq_n_2_p_frm_ifi_avg_sad;
165
0
                number_t vq_prev_frm_sad_i;
166
                /* If there are frames in the current IFI start using it to estimate the I frame SAD */
167
0
                if(ps_est_sad->i4_num_p_frm_in_cur_ifi)
168
0
                {
169
0
                    u4_n_1_p_frm_ifi_avg_sad =
170
0
                        (ps_est_sad->u4_n_p_frm_ifi_avg_sad / ps_est_sad->i4_num_p_frm_in_cur_ifi);
171
0
                    u4_n_2_p_frm_ifi_avg_sad = ps_est_sad->u4_n_1_p_frm_ifi_avg_sad;
172
0
                }
173
0
                else
174
0
                {
175
0
                    u4_n_1_p_frm_ifi_avg_sad = ps_est_sad->u4_n_1_p_frm_ifi_avg_sad;
176
0
                    u4_n_2_p_frm_ifi_avg_sad = ps_est_sad->u4_n_2_p_frm_ifi_avg_sad;
177
0
                }
178
                /* If any of the previous p frame SADs are zeros we just return the previous
179
                I frame SAD */
180
0
                if(u4_n_1_p_frm_ifi_avg_sad && u4_n_2_p_frm_ifi_avg_sad)
181
0
                {
182
0
                    SET_VAR_Q(vq_prev_frm_sad_i, ps_est_sad->au4_prev_frm_sad[I_PIC], 0);
183
0
                    SET_VAR_Q(vq_n_1_p_frm_ifi_avg_sad, u4_n_1_p_frm_ifi_avg_sad, 0);
184
0
                    SET_VAR_Q(vq_n_2_p_frm_ifi_avg_sad, u4_n_2_p_frm_ifi_avg_sad, 0);
185
                    /**************************************************************************
186
                    Estimated SAD =
187
                    (n-1)th intra frame interval(ifi) P frame Avg SAD *
188
                    (prev I frame SAD / (n-2)nd intra frame interval(ifi) P frame Avg SAD)
189
                    **************************************************************************/
190
0
                    mult32_var_q(vq_prev_frm_sad_i, vq_n_1_p_frm_ifi_avg_sad, &vq_prev_frm_sad_i);
191
0
                    div32_var_q(vq_prev_frm_sad_i, vq_n_2_p_frm_ifi_avg_sad, &vq_prev_frm_sad_i);
192
0
                    number_t_to_word32(vq_prev_frm_sad_i, (WORD32 *)&u4_estimated_sad);
193
0
                }
194
0
                else
195
0
                {
196
0
                    u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[I_PIC];
197
0
                }
198
0
            }
199
0
        }
200
0
        return u4_estimated_sad;
201
0
    }
202
1.09M
    else
203
1.09M
    {
204
1.09M
        return ps_est_sad->au4_prev_frm_sad[e_pic_type];
205
1.09M
    }
206
1.09M
}
207
/****************************************************************************
208
Function Name : update_ppic_sad
209
Description   :
210
Inputs        : ps_est_sad
211
212
Revision History:
213
DD MM YYYY   Author(s)       Changes (Describe the changes made)
214
 *****************************************************************************/
215
WORD32 update_ppic_sad(est_sad_t *ps_est_sad, WORD32 i4_est_sad, WORD32 i4_prev_p_sad)
216
0
{
217
0
    i4_est_sad = ((ps_est_sad->au4_prev_frm_sad[P_PIC]) * ((i4_est_sad << 4) / i4_prev_p_sad)) >> 4;
218
    /* printf("i4_est_sad=%d prev_psad=%d\n",i4_est_sad,ps_est_sad->au4_prev_frm_sad[P_PIC]); */
219
0
    if(i4_est_sad > (WORD32)ps_est_sad->au4_prev_frm_sad[P_PIC])
220
0
    {
221
0
        if(4 * i4_est_sad > 5 * i4_prev_p_sad)
222
0
            i4_est_sad = (5 * i4_prev_p_sad) >> 2;
223
0
        ps_est_sad->au4_prev_frm_sad[P_PIC] = i4_est_sad;
224
0
        return 0;
225
0
    }
226
0
    return 1;
227
0
}
228
/****************************************************************************
229
Function Name : update_actual_sad
230
Description   :
231
Inputs        : ps_est_sad
232
233
Revision History:
234
DD MM YYYY   Author(s)       Changes (Describe the changes made)
235
 *****************************************************************************/
236
void update_actual_sad(est_sad_t *ps_est_sad, UWORD32 u4_actual_sad, picture_type_e e_pic_type)
237
87.6k
{
238
87.6k
    ps_est_sad->au4_prev_frm_sad[e_pic_type] = u4_actual_sad;
239
240
87.6k
    if(ps_est_sad->i4_use_est_intra_sad)
241
0
    {
242
0
        if(e_pic_type == I_PIC)
243
0
        {
244
            /* The requirement is to have two IFI before estimating I frame SAD */
245
0
            if(ps_est_sad->i4_num_ifi_encoded < 2)
246
0
                ps_est_sad->i4_num_ifi_encoded++;
247
248
            /* Calculate the average SAD */
249
0
            if(ps_est_sad->i4_num_p_frm_in_cur_ifi)
250
0
            {
251
0
                ps_est_sad->u4_n_p_frm_ifi_avg_sad /= ps_est_sad->i4_num_p_frm_in_cur_ifi;
252
0
            }
253
0
            else
254
0
            {
255
0
                ps_est_sad->u4_n_p_frm_ifi_avg_sad = 0;
256
0
            }
257
            /* Push the (n-1)th average SAD to the (n-2)th average SAD  */
258
0
            ps_est_sad->u4_n_2_p_frm_ifi_avg_sad = ps_est_sad->u4_n_1_p_frm_ifi_avg_sad;
259
            /* Push the nth average SAD to the (n-1)th average SAD */
260
0
            ps_est_sad->u4_n_1_p_frm_ifi_avg_sad = ps_est_sad->u4_n_p_frm_ifi_avg_sad;
261
            /* Reset SAD and number of P frames */
262
0
            ps_est_sad->u4_n_p_frm_ifi_avg_sad = 0;
263
0
            ps_est_sad->i4_num_p_frm_in_cur_ifi = 0;
264
0
        }
265
0
        else
266
0
        {
267
0
            ps_est_sad->u4_n_p_frm_ifi_avg_sad += u4_actual_sad;
268
0
            ps_est_sad->i4_num_p_frm_in_cur_ifi++;
269
0
        }
270
0
    }
271
87.6k
}
272
/****************************************************************************
273
Function Name : update_prev_frame_intra_sad
274
Description   :
275
Inputs        : ps_est_sad
276
277
Revision History:
278
DD MM YYYY   Author(s)       Changes (Describe the changes made)
279
 *****************************************************************************/
280
void update_prev_frame_intra_sad(est_sad_t *ps_est_sad, WORD32 i4_intra_frm_sad)
281
19.5k
{
282
19.5k
    ps_est_sad->au4_prev_frm_sad[I_PIC] = i4_intra_frm_sad;
283
19.5k
}
284
/****************************************************************************
285
Function Name : get_prev_frame_intra_sad
286
Description   :
287
Inputs        : ps_est_sad
288
289
Revision History:
290
DD MM YYYY   Author(s)       Changes (Describe the changes made)
291
 *****************************************************************************/
292
WORD32 get_prev_frame_intra_sad(est_sad_t *ps_est_sad)
293
19.5k
{
294
19.5k
    return ps_est_sad->au4_prev_frm_sad[I_PIC];
295
19.5k
}
296
/****************************************************************************
297
Function Name : update_prev_frame_sad
298
Description   :
299
Inputs        : ps_est_sad
300
301
Revision History:
302
DD MM YYYY   Author(s)       Changes (Describe the changes made)
303
 *****************************************************************************/
304
void update_prev_frame_sad(est_sad_t *ps_est_sad, WORD32 i4_frm_sad, picture_type_e e_pic_type)
305
64.1k
{
306
64.1k
    ps_est_sad->au4_prev_frm_sad[e_pic_type] = i4_frm_sad;
307
64.1k
}
308
/****************************************************************************
309
Function Name : get_prev_frame_sad
310
Description   :
311
Inputs        : ps_est_sad
312
313
Revision History:
314
DD MM YYYY   Author(s)       Changes (Describe the changes made)
315
 *****************************************************************************/
316
WORD32 get_prev_frame_sad(est_sad_t *ps_est_sad, picture_type_e e_pic_type)
317
64.1k
{
318
64.1k
    return ps_est_sad->au4_prev_frm_sad[e_pic_type];
319
64.1k
}