Coverage Report

Created: 2025-07-23 06:18

/src/libavc/encoder/irc_est_sad.c
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Copyright (C) 2015 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
/* Includes */
23
/*****************************************************************************/
24
25
/* User include files */
26
#include "irc_datatypes.h"
27
#include "irc_cntrl_param.h"
28
#include "irc_mem_req_and_acq.h"
29
#include "irc_est_sad.h"
30
#include "irc_common.h"
31
32
typedef struct est_sad_t
33
{
34
    WORD32 i4_use_est_intra_sad;
35
36
    /* Previous frame SAD */
37
    UWORD32 au4_prev_frm_sad[MAX_PIC_TYPE];
38
39
    /* Current (nth) ifi average P frame SAD */
40
    UWORD32 u4_n_p_frm_ifi_avg_sad;
41
42
    /* (n-1)th ifi average P frame SAD */
43
    UWORD32 u4_n_1_p_frm_ifi_avg_sad;
44
45
    /* (n-2)th ifi average P frame SAD */
46
    UWORD32 u4_n_2_p_frm_ifi_avg_sad;
47
48
    /* number of ifi encoded till now */
49
    WORD32 i4_num_ifi_encoded;
50
51
    /* number of P frames in the current IFI */
52
    WORD32 i4_num_p_frm_in_cur_ifi;
53
54
} est_sad_t;
55
56
WORD32 irc_est_sad_num_fill_use_free_memtab(est_sad_t **pps_est_sad,
57
                                            itt_memtab_t *ps_memtab,
58
                                            ITT_FUNC_TYPE_E e_func_type)
59
127k
{
60
127k
    WORD32 i4_mem_tab_idx = 0;
61
127k
    est_sad_t s_est_sad;
62
63
    /* Hack for al alloc, during which we don't have any state memory.
64
     * Dereferencing can cause issues
65
     */
66
127k
    if(e_func_type == GET_NUM_MEMTAB || e_func_type == FILL_MEMTAB)
67
106k
        (*pps_est_sad) = &s_est_sad;
68
69
    /* For src rate control state structure */
70
127k
    if(e_func_type != GET_NUM_MEMTAB)
71
63.8k
    {
72
63.8k
        fill_memtab(&ps_memtab[i4_mem_tab_idx], sizeof(est_sad_t),
73
63.8k
                    ALIGN_128_BYTE, PERSISTENT, DDR);
74
63.8k
        use_or_fill_base(&ps_memtab[0], (void**)pps_est_sad, e_func_type);
75
63.8k
    }
76
127k
    i4_mem_tab_idx++;
77
78
127k
    return (i4_mem_tab_idx);
79
127k
}
80
81
void irc_init_est_sad(est_sad_t *ps_est_sad, WORD32 i4_use_est_intra_sad)
82
44.7k
{
83
44.7k
    WORD32 i;
84
44.7k
    ps_est_sad->i4_use_est_intra_sad = i4_use_est_intra_sad;
85
86
179k
    for(i = 0; i < MAX_PIC_TYPE; i++)
87
134k
    {
88
134k
        ps_est_sad->au4_prev_frm_sad[i] = 0;
89
134k
    }
90
91
44.7k
    ps_est_sad->u4_n_p_frm_ifi_avg_sad = 0;
92
44.7k
    ps_est_sad->u4_n_1_p_frm_ifi_avg_sad = 0;
93
44.7k
    ps_est_sad->u4_n_2_p_frm_ifi_avg_sad = 0;
94
44.7k
    ps_est_sad->i4_num_ifi_encoded = 0;
95
44.7k
    ps_est_sad->i4_num_p_frm_in_cur_ifi = 0;
96
44.7k
}
97
98
void irc_reset_est_sad(est_sad_t *ps_est_sad)
99
2.88k
{
100
2.88k
    irc_init_est_sad(ps_est_sad, ps_est_sad->i4_use_est_intra_sad);
101
2.88k
}
102
103
/*
104
 * Get estimated SAD can be called at any point. The various use cases are:
105
 * 1) When a I frame is getting encoded,
106
 *    - get the estimated of P => No issues since we use the last coded P frame
107
 *      value
108
 *    - get estimated of I => This call for two cases:
109
 *    => a) if num_ifi_encoded is less than 2
110
 *          then return the previous encoded I frame sad
111
 *    => b) if num_ifi_encoded is more than 2, then we scale
112
 *          the prev I sad by the ratio of (n-1) ifi P to n-2 ifi P
113
 * 2) When P frame is getting encoded,
114
 *    - get the estimated of P =>  No issues since we use the last coded P frame value
115
 *    - get the estimated of I => Simillar to I we have two cases.
116
 *      To handle the b) case extra logic had to introduced using
117
 *      u1_is_n_1_p_frm_ifi_avg_sad_usable flag
118
 */
119
UWORD32 irc_get_est_sad(est_sad_t *ps_est_sad, picture_type_e e_pic_type)
120
171k
{
121
171k
    if(ps_est_sad->i4_use_est_intra_sad)
122
0
    {
123
0
        UWORD32 u4_estimated_sad;
124
0
        if(e_pic_type == P_PIC)
125
0
        {
126
0
            u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[P_PIC];
127
0
        }
128
0
        else if(e_pic_type == B_PIC)
129
0
        {
130
0
            u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[B_PIC];
131
0
        }
132
0
        else
133
0
        {
134
0
            if(ps_est_sad->i4_num_ifi_encoded < 2)
135
0
            {
136
                /*
137
                 * Only one IFI has been encoded and so use the previous I
138
                 * frames SAD
139
                 */
140
0
                u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[I_PIC];
141
0
            }
142
0
            else
143
0
            {
144
                /*
145
                 * Since the n-1 'P' frame IFI would have just accumulated the
146
                 * frame sads we average it out here
147
                 */
148
0
                UWORD32 u4_n_1_p_frm_ifi_avg_sad, u4_n_2_p_frm_ifi_avg_sad;
149
0
                number_t vq_n_1_p_frm_ifi_avg_sad, vq_n_2_p_frm_ifi_avg_sad;
150
0
                number_t vq_prev_frm_sad_i;
151
152
                /*
153
                 * If there are frames in the current IFI start using it to
154
                 * estimate the I frame SAD
155
                 */
156
0
                if(ps_est_sad->i4_num_p_frm_in_cur_ifi)
157
0
                {
158
0
                    u4_n_1_p_frm_ifi_avg_sad =
159
0
                                    (ps_est_sad->u4_n_p_frm_ifi_avg_sad
160
0
                                     / ps_est_sad->i4_num_p_frm_in_cur_ifi);
161
0
                    u4_n_2_p_frm_ifi_avg_sad =
162
0
                                    ps_est_sad->u4_n_1_p_frm_ifi_avg_sad;
163
0
                }
164
0
                else
165
0
                {
166
0
                    u4_n_1_p_frm_ifi_avg_sad =
167
0
                                    ps_est_sad->u4_n_1_p_frm_ifi_avg_sad;
168
0
                    u4_n_2_p_frm_ifi_avg_sad =
169
0
                                    ps_est_sad->u4_n_2_p_frm_ifi_avg_sad;
170
0
                }
171
172
                /*
173
                 * If any of the previous p frame SADs are zeros we just return
174
                 * the previous I frame SAD
175
                 */
176
0
                if(u4_n_1_p_frm_ifi_avg_sad && u4_n_2_p_frm_ifi_avg_sad)
177
0
                {
178
0
                    SET_VAR_Q(vq_prev_frm_sad_i,
179
0
                              ps_est_sad->au4_prev_frm_sad[I_PIC], 0);
180
0
                    SET_VAR_Q(vq_n_1_p_frm_ifi_avg_sad,
181
0
                              u4_n_1_p_frm_ifi_avg_sad, 0);
182
0
                    SET_VAR_Q(vq_n_2_p_frm_ifi_avg_sad,
183
0
                              u4_n_2_p_frm_ifi_avg_sad, 0);
184
                    /*
185
                     * Estimated SAD =
186
                     *(n-1)th intra frame interval(ifi) P frame Avg SAD *
187
                     *(prev I frame SAD /
188
                     *(prev (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,
191
0
                                 &vq_prev_frm_sad_i);
192
0
                    div32_var_q(vq_prev_frm_sad_i, vq_n_2_p_frm_ifi_avg_sad,
193
0
                                &vq_prev_frm_sad_i);
194
0
                    number_t_to_word32(vq_prev_frm_sad_i,
195
0
                                       (WORD32*)&u4_estimated_sad);
196
0
                }
197
0
                else
198
0
                {
199
0
                    u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[I_PIC];
200
0
                }
201
0
            }
202
0
        }
203
0
        return u4_estimated_sad;
204
0
    }
205
171k
    else
206
171k
    {
207
171k
        return ps_est_sad->au4_prev_frm_sad[e_pic_type];
208
171k
    }
209
171k
}
210
211
void irc_update_actual_sad(est_sad_t *ps_est_sad,
212
                           UWORD32 u4_actual_sad,
213
                           picture_type_e e_pic_type)
214
137k
{
215
137k
    ps_est_sad->au4_prev_frm_sad[e_pic_type] = u4_actual_sad;
216
217
137k
    if(ps_est_sad->i4_use_est_intra_sad)
218
0
    {
219
0
        if(e_pic_type == I_PIC)
220
0
        {
221
            /* The requirement is to have two IFI before estimating I frame SAD */
222
0
            if(ps_est_sad->i4_num_ifi_encoded < 2)
223
0
                ps_est_sad->i4_num_ifi_encoded++;
224
225
            /* Calculate the average SAD */
226
0
            if(ps_est_sad->i4_num_p_frm_in_cur_ifi)
227
0
            {
228
0
                ps_est_sad->u4_n_p_frm_ifi_avg_sad /=
229
0
                                ps_est_sad->i4_num_p_frm_in_cur_ifi;
230
0
            }
231
0
            else
232
0
            {
233
0
                ps_est_sad->u4_n_p_frm_ifi_avg_sad = 0;
234
0
            }
235
            /* Push the (n-1)th average SAD to the (n-2)th average SAD  */
236
0
            ps_est_sad->u4_n_2_p_frm_ifi_avg_sad =
237
0
                            ps_est_sad->u4_n_1_p_frm_ifi_avg_sad;
238
            /* Push the nth average SAD to the (n-1)th average SAD */
239
0
            ps_est_sad->u4_n_1_p_frm_ifi_avg_sad =
240
0
                            ps_est_sad->u4_n_p_frm_ifi_avg_sad;
241
            /* Reset SAD and number of P frames */
242
0
            ps_est_sad->u4_n_p_frm_ifi_avg_sad = 0;
243
0
            ps_est_sad->i4_num_p_frm_in_cur_ifi = 0;
244
0
        }
245
0
        else
246
0
        {
247
0
            ps_est_sad->u4_n_p_frm_ifi_avg_sad += u4_actual_sad;
248
0
            ps_est_sad->i4_num_p_frm_in_cur_ifi++;
249
0
        }
250
0
    }
251
137k
}
252
253
void irc_update_actual_sad_for_intra(est_sad_t *ps_est_sad,
254
                                     WORD32 i4_intra_frm_cost)
255
68.8k
{
256
68.8k
    if(!(ps_est_sad->i4_use_est_intra_sad))
257
68.8k
    {
258
68.8k
        irc_update_actual_sad(ps_est_sad, i4_intra_frm_cost, I_PIC);
259
68.8k
    }
260
68.8k
}