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 
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 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 {
60     WORD32 i4_mem_tab_idx = 0;
61     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     if(e_func_type == GET_NUM_MEMTAB || e_func_type == FILL_MEMTAB)
67         (*pps_est_sad) = &s_est_sad;
68 
69     /* For src rate control state structure */
70     if(e_func_type != GET_NUM_MEMTAB)
71     {
72         fill_memtab(&ps_memtab[i4_mem_tab_idx], sizeof(est_sad_t),
73                     ALIGN_128_BYTE, PERSISTENT, DDR);
74         use_or_fill_base(&ps_memtab[0], (void**)pps_est_sad, e_func_type);
75     }
76     i4_mem_tab_idx++;
77 
78     return (i4_mem_tab_idx);
79 }
80 
irc_init_est_sad(est_sad_t * ps_est_sad,WORD32 i4_use_est_intra_sad)81 void irc_init_est_sad(est_sad_t *ps_est_sad, WORD32 i4_use_est_intra_sad)
82 {
83     WORD32 i;
84     ps_est_sad->i4_use_est_intra_sad = i4_use_est_intra_sad;
85 
86     for(i = 0; i < MAX_PIC_TYPE; i++)
87     {
88         ps_est_sad->au4_prev_frm_sad[i] = 0;
89     }
90 
91     ps_est_sad->u4_n_p_frm_ifi_avg_sad = 0;
92     ps_est_sad->u4_n_1_p_frm_ifi_avg_sad = 0;
93     ps_est_sad->u4_n_2_p_frm_ifi_avg_sad = 0;
94     ps_est_sad->i4_num_ifi_encoded = 0;
95     ps_est_sad->i4_num_p_frm_in_cur_ifi = 0;
96 }
97 
irc_reset_est_sad(est_sad_t * ps_est_sad)98 void irc_reset_est_sad(est_sad_t *ps_est_sad)
99 {
100     irc_init_est_sad(ps_est_sad, ps_est_sad->i4_use_est_intra_sad);
101 }
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  */
irc_get_est_sad(est_sad_t * ps_est_sad,picture_type_e e_pic_type)119 UWORD32 irc_get_est_sad(est_sad_t *ps_est_sad, picture_type_e e_pic_type)
120 {
121     if(ps_est_sad->i4_use_est_intra_sad)
122     {
123         UWORD32 u4_estimated_sad;
124         if(e_pic_type == P_PIC)
125         {
126             u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[P_PIC];
127         }
128         else if(e_pic_type == B_PIC)
129         {
130             u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[B_PIC];
131         }
132         else
133         {
134             if(ps_est_sad->i4_num_ifi_encoded < 2)
135             {
136                 /*
137                  * Only one IFI has been encoded and so use the previous I
138                  * frames SAD
139                  */
140                 u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[I_PIC];
141             }
142             else
143             {
144                 /*
145                  * Since the n-1 'P' frame IFI would have just accumulated the
146                  * frame sads we average it out here
147                  */
148                 UWORD32 u4_n_1_p_frm_ifi_avg_sad, u4_n_2_p_frm_ifi_avg_sad;
149                 number_t vq_n_1_p_frm_ifi_avg_sad, vq_n_2_p_frm_ifi_avg_sad;
150                 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                 if(ps_est_sad->i4_num_p_frm_in_cur_ifi)
157                 {
158                     u4_n_1_p_frm_ifi_avg_sad =
159                                     (ps_est_sad->u4_n_p_frm_ifi_avg_sad
160                                      / ps_est_sad->i4_num_p_frm_in_cur_ifi);
161                     u4_n_2_p_frm_ifi_avg_sad =
162                                     ps_est_sad->u4_n_1_p_frm_ifi_avg_sad;
163                 }
164                 else
165                 {
166                     u4_n_1_p_frm_ifi_avg_sad =
167                                     ps_est_sad->u4_n_1_p_frm_ifi_avg_sad;
168                     u4_n_2_p_frm_ifi_avg_sad =
169                                     ps_est_sad->u4_n_2_p_frm_ifi_avg_sad;
170                 }
171 
172                 /*
173                  * If any of the previous p frame SADs are zeros we just return
174                  * the previous I frame SAD
175                  */
176                 if(u4_n_1_p_frm_ifi_avg_sad && u4_n_2_p_frm_ifi_avg_sad)
177                 {
178                     SET_VAR_Q(vq_prev_frm_sad_i,
179                               ps_est_sad->au4_prev_frm_sad[I_PIC], 0);
180                     SET_VAR_Q(vq_n_1_p_frm_ifi_avg_sad,
181                               u4_n_1_p_frm_ifi_avg_sad, 0);
182                     SET_VAR_Q(vq_n_2_p_frm_ifi_avg_sad,
183                               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                     mult32_var_q(vq_prev_frm_sad_i, vq_n_1_p_frm_ifi_avg_sad,
191                                  &vq_prev_frm_sad_i);
192                     div32_var_q(vq_prev_frm_sad_i, vq_n_2_p_frm_ifi_avg_sad,
193                                 &vq_prev_frm_sad_i);
194                     number_t_to_word32(vq_prev_frm_sad_i,
195                                        (WORD32*)&u4_estimated_sad);
196                 }
197                 else
198                 {
199                     u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[I_PIC];
200                 }
201             }
202         }
203         return u4_estimated_sad;
204     }
205     else
206     {
207         return ps_est_sad->au4_prev_frm_sad[e_pic_type];
208     }
209 }
210 
irc_update_actual_sad(est_sad_t * ps_est_sad,UWORD32 u4_actual_sad,picture_type_e e_pic_type)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 {
215     ps_est_sad->au4_prev_frm_sad[e_pic_type] = u4_actual_sad;
216 
217     if(ps_est_sad->i4_use_est_intra_sad)
218     {
219         if(e_pic_type == I_PIC)
220         {
221             /* The requirement is to have two IFI before estimating I frame SAD */
222             if(ps_est_sad->i4_num_ifi_encoded < 2)
223                 ps_est_sad->i4_num_ifi_encoded++;
224 
225             /* Calculate the average SAD */
226             if(ps_est_sad->i4_num_p_frm_in_cur_ifi)
227             {
228                 ps_est_sad->u4_n_p_frm_ifi_avg_sad /=
229                                 ps_est_sad->i4_num_p_frm_in_cur_ifi;
230             }
231             else
232             {
233                 ps_est_sad->u4_n_p_frm_ifi_avg_sad = 0;
234             }
235             /* Push the (n-1)th average SAD to the (n-2)th average SAD  */
236             ps_est_sad->u4_n_2_p_frm_ifi_avg_sad =
237                             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             ps_est_sad->u4_n_1_p_frm_ifi_avg_sad =
240                             ps_est_sad->u4_n_p_frm_ifi_avg_sad;
241             /* Reset SAD and number of P frames */
242             ps_est_sad->u4_n_p_frm_ifi_avg_sad = 0;
243             ps_est_sad->i4_num_p_frm_in_cur_ifi = 0;
244         }
245         else
246         {
247             ps_est_sad->u4_n_p_frm_ifi_avg_sad += u4_actual_sad;
248             ps_est_sad->i4_num_p_frm_in_cur_ifi++;
249         }
250     }
251 }
252 
irc_update_actual_sad_for_intra(est_sad_t * ps_est_sad,WORD32 i4_intra_frm_cost)253 void irc_update_actual_sad_for_intra(est_sad_t *ps_est_sad,
254                                      WORD32 i4_intra_frm_cost)
255 {
256     if(!(ps_est_sad->i4_use_est_intra_sad))
257     {
258         irc_update_actual_sad(ps_est_sad, i4_intra_frm_cost, I_PIC);
259     }
260 }
261