Home | History | Annotate | Download | only in encoder
      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 {
     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  *****************************************************************************/
     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  *****************************************************************************/
    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 */
    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  *****************************************************************************/
    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  *****************************************************************************/
    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  *****************************************************************************/
    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  *****************************************************************************/
    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  *****************************************************************************/
    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  *****************************************************************************/
    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