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