• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
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)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 {
60     WORD32 i4_mem_tab_idx = 0;
61     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     if(e_func_type == GET_NUM_MEMTAB || e_func_type == FILL_MEMTAB)
66         (*pps_est_sad) = &s_est_sad;
67 
68     /*for src rate control state structure*/
69     if(e_func_type != GET_NUM_MEMTAB)
70     {
71         fill_memtab(
72             &ps_memtab[i4_mem_tab_idx], sizeof(est_sad_t), MEM_TAB_ALIGNMENT, PERSISTENT, DDR);
73         use_or_fill_base(&ps_memtab[0], (void **)pps_est_sad, e_func_type);
74     }
75     i4_mem_tab_idx++;
76 
77     return (i4_mem_tab_idx);
78 }
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  *****************************************************************************/
init_est_sad(est_sad_t * ps_est_sad,WORD32 i4_use_est_intra_sad)89 void init_est_sad(est_sad_t *ps_est_sad, WORD32 i4_use_est_intra_sad)
90 {
91     WORD32 i;
92     ps_est_sad->i4_use_est_intra_sad = i4_use_est_intra_sad;
93 
94     for(i = 0; i < MAX_PIC_TYPE; i++)
95         ps_est_sad->au4_prev_frm_sad[i] = 0;
96 
97     ps_est_sad->u4_n_p_frm_ifi_avg_sad = 0;
98     ps_est_sad->u4_n_1_p_frm_ifi_avg_sad = 0;
99     ps_est_sad->u4_n_2_p_frm_ifi_avg_sad = 0;
100     ps_est_sad->i4_num_ifi_encoded = 0;
101     ps_est_sad->i4_num_p_frm_in_cur_ifi = 0;
102 }
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  *****************************************************************************/
reset_est_sad(est_sad_t * ps_est_sad)111 void reset_est_sad(est_sad_t *ps_est_sad)
112 {
113     init_est_sad(ps_est_sad, ps_est_sad->i4_use_est_intra_sad);
114 }
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 */
get_est_sad(est_sad_t * ps_est_sad,picture_type_e e_pic_type)139 UWORD32 get_est_sad(est_sad_t *ps_est_sad, picture_type_e e_pic_type)
140 {
141     if(ps_est_sad->i4_use_est_intra_sad)
142     {
143         UWORD32 u4_estimated_sad;
144         if(e_pic_type == P_PIC)
145         {
146             u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[P_PIC];
147         }
148         else if(e_pic_type == B_PIC)
149         {
150             u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[B_PIC];
151         }
152         else
153         {
154             if(ps_est_sad->i4_num_ifi_encoded < 2)
155             {
156                 /* Only one IFI has been encoded and so use the previous I frames SAD */
157                 u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[I_PIC];
158             }
159             else
160             {
161                 /* Since the n-1 'P' frame IFI would have just accumulated the frame sads
162                 we average it out here */
163                 UWORD32 u4_n_1_p_frm_ifi_avg_sad, u4_n_2_p_frm_ifi_avg_sad;
164                 number_t vq_n_1_p_frm_ifi_avg_sad, vq_n_2_p_frm_ifi_avg_sad;
165                 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                 if(ps_est_sad->i4_num_p_frm_in_cur_ifi)
168                 {
169                     u4_n_1_p_frm_ifi_avg_sad =
170                         (ps_est_sad->u4_n_p_frm_ifi_avg_sad / ps_est_sad->i4_num_p_frm_in_cur_ifi);
171                     u4_n_2_p_frm_ifi_avg_sad = ps_est_sad->u4_n_1_p_frm_ifi_avg_sad;
172                 }
173                 else
174                 {
175                     u4_n_1_p_frm_ifi_avg_sad = ps_est_sad->u4_n_1_p_frm_ifi_avg_sad;
176                     u4_n_2_p_frm_ifi_avg_sad = ps_est_sad->u4_n_2_p_frm_ifi_avg_sad;
177                 }
178                 /* If any of the previous p frame SADs are zeros we just return the previous
179                 I frame SAD */
180                 if(u4_n_1_p_frm_ifi_avg_sad && u4_n_2_p_frm_ifi_avg_sad)
181                 {
182                     SET_VAR_Q(vq_prev_frm_sad_i, ps_est_sad->au4_prev_frm_sad[I_PIC], 0);
183                     SET_VAR_Q(vq_n_1_p_frm_ifi_avg_sad, u4_n_1_p_frm_ifi_avg_sad, 0);
184                     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                     mult32_var_q(vq_prev_frm_sad_i, vq_n_1_p_frm_ifi_avg_sad, &vq_prev_frm_sad_i);
191                     div32_var_q(vq_prev_frm_sad_i, vq_n_2_p_frm_ifi_avg_sad, &vq_prev_frm_sad_i);
192                     number_t_to_word32(vq_prev_frm_sad_i, (WORD32 *)&u4_estimated_sad);
193                 }
194                 else
195                 {
196                     u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[I_PIC];
197                 }
198             }
199         }
200         return u4_estimated_sad;
201     }
202     else
203     {
204         return ps_est_sad->au4_prev_frm_sad[e_pic_type];
205     }
206 }
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  *****************************************************************************/
update_ppic_sad(est_sad_t * ps_est_sad,WORD32 i4_est_sad,WORD32 i4_prev_p_sad)215 WORD32 update_ppic_sad(est_sad_t *ps_est_sad, WORD32 i4_est_sad, WORD32 i4_prev_p_sad)
216 {
217     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     if(i4_est_sad > (WORD32)ps_est_sad->au4_prev_frm_sad[P_PIC])
220     {
221         if(4 * i4_est_sad > 5 * i4_prev_p_sad)
222             i4_est_sad = (5 * i4_prev_p_sad) >> 2;
223         ps_est_sad->au4_prev_frm_sad[P_PIC] = i4_est_sad;
224         return 0;
225     }
226     return 1;
227 }
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  *****************************************************************************/
update_actual_sad(est_sad_t * ps_est_sad,UWORD32 u4_actual_sad,picture_type_e e_pic_type)236 void update_actual_sad(est_sad_t *ps_est_sad, UWORD32 u4_actual_sad, picture_type_e e_pic_type)
237 {
238     ps_est_sad->au4_prev_frm_sad[e_pic_type] = u4_actual_sad;
239 
240     if(ps_est_sad->i4_use_est_intra_sad)
241     {
242         if(e_pic_type == I_PIC)
243         {
244             /* The requirement is to have two IFI before estimating I frame SAD */
245             if(ps_est_sad->i4_num_ifi_encoded < 2)
246                 ps_est_sad->i4_num_ifi_encoded++;
247 
248             /* Calculate the average SAD */
249             if(ps_est_sad->i4_num_p_frm_in_cur_ifi)
250             {
251                 ps_est_sad->u4_n_p_frm_ifi_avg_sad /= ps_est_sad->i4_num_p_frm_in_cur_ifi;
252             }
253             else
254             {
255                 ps_est_sad->u4_n_p_frm_ifi_avg_sad = 0;
256             }
257             /* Push the (n-1)th average SAD to the (n-2)th average SAD  */
258             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             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             ps_est_sad->u4_n_p_frm_ifi_avg_sad = 0;
263             ps_est_sad->i4_num_p_frm_in_cur_ifi = 0;
264         }
265         else
266         {
267             ps_est_sad->u4_n_p_frm_ifi_avg_sad += u4_actual_sad;
268             ps_est_sad->i4_num_p_frm_in_cur_ifi++;
269         }
270     }
271 }
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  *****************************************************************************/
update_prev_frame_intra_sad(est_sad_t * ps_est_sad,WORD32 i4_intra_frm_sad)280 void update_prev_frame_intra_sad(est_sad_t *ps_est_sad, WORD32 i4_intra_frm_sad)
281 {
282     ps_est_sad->au4_prev_frm_sad[I_PIC] = i4_intra_frm_sad;
283 }
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  *****************************************************************************/
get_prev_frame_intra_sad(est_sad_t * ps_est_sad)292 WORD32 get_prev_frame_intra_sad(est_sad_t *ps_est_sad)
293 {
294     return ps_est_sad->au4_prev_frm_sad[I_PIC];
295 }
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  *****************************************************************************/
update_prev_frame_sad(est_sad_t * ps_est_sad,WORD32 i4_frm_sad,picture_type_e e_pic_type)304 void update_prev_frame_sad(est_sad_t *ps_est_sad, WORD32 i4_frm_sad, picture_type_e e_pic_type)
305 {
306     ps_est_sad->au4_prev_frm_sad[e_pic_type] = i4_frm_sad;
307 }
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  *****************************************************************************/
get_prev_frame_sad(est_sad_t * ps_est_sad,picture_type_e e_pic_type)316 WORD32 get_prev_frame_sad(est_sad_t *ps_est_sad, picture_type_e e_pic_type)
317 {
318     return ps_est_sad->au4_prev_frm_sad[e_pic_type];
319 }
320