You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
260 lines
9.1 KiB
260 lines
9.1 KiB
/****************************************************************************** |
|
* |
|
* Copyright (C) 2015 The Android Open Source Project |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at: |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
* |
|
***************************************************************************** |
|
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore |
|
*/ |
|
|
|
/*****************************************************************************/ |
|
/* Includes */ |
|
/*****************************************************************************/ |
|
|
|
/* User include files */ |
|
#include "irc_datatypes.h" |
|
#include "irc_cntrl_param.h" |
|
#include "irc_mem_req_and_acq.h" |
|
#include "irc_est_sad.h" |
|
#include "irc_common.h" |
|
|
|
typedef struct est_sad_t |
|
{ |
|
WORD32 i4_use_est_intra_sad; |
|
|
|
/* Previous frame SAD */ |
|
UWORD32 au4_prev_frm_sad[MAX_PIC_TYPE]; |
|
|
|
/* Current (nth) ifi average P frame SAD */ |
|
UWORD32 u4_n_p_frm_ifi_avg_sad; |
|
|
|
/* (n-1)th ifi average P frame SAD */ |
|
UWORD32 u4_n_1_p_frm_ifi_avg_sad; |
|
|
|
/* (n-2)th ifi average P frame SAD */ |
|
UWORD32 u4_n_2_p_frm_ifi_avg_sad; |
|
|
|
/* number of ifi encoded till now */ |
|
WORD32 i4_num_ifi_encoded; |
|
|
|
/* number of P frames in the current IFI */ |
|
WORD32 i4_num_p_frm_in_cur_ifi; |
|
|
|
} est_sad_t; |
|
|
|
WORD32 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) |
|
{ |
|
WORD32 i4_mem_tab_idx = 0; |
|
est_sad_t s_est_sad; |
|
|
|
/* Hack for al alloc, during which we don't have any state memory. |
|
* Dereferencing can cause issues |
|
*/ |
|
if(e_func_type == GET_NUM_MEMTAB || e_func_type == FILL_MEMTAB) |
|
(*pps_est_sad) = &s_est_sad; |
|
|
|
/* For src rate control state structure */ |
|
if(e_func_type != GET_NUM_MEMTAB) |
|
{ |
|
fill_memtab(&ps_memtab[i4_mem_tab_idx], sizeof(est_sad_t), |
|
ALIGN_128_BYTE, PERSISTENT, DDR); |
|
use_or_fill_base(&ps_memtab[0], (void**)pps_est_sad, e_func_type); |
|
} |
|
i4_mem_tab_idx++; |
|
|
|
return (i4_mem_tab_idx); |
|
} |
|
|
|
void irc_init_est_sad(est_sad_t *ps_est_sad, WORD32 i4_use_est_intra_sad) |
|
{ |
|
WORD32 i; |
|
ps_est_sad->i4_use_est_intra_sad = i4_use_est_intra_sad; |
|
|
|
for(i = 0; i < MAX_PIC_TYPE; i++) |
|
{ |
|
ps_est_sad->au4_prev_frm_sad[i] = 0; |
|
} |
|
|
|
ps_est_sad->u4_n_p_frm_ifi_avg_sad = 0; |
|
ps_est_sad->u4_n_1_p_frm_ifi_avg_sad = 0; |
|
ps_est_sad->u4_n_2_p_frm_ifi_avg_sad = 0; |
|
ps_est_sad->i4_num_ifi_encoded = 0; |
|
ps_est_sad->i4_num_p_frm_in_cur_ifi = 0; |
|
} |
|
|
|
void irc_reset_est_sad(est_sad_t *ps_est_sad) |
|
{ |
|
irc_init_est_sad(ps_est_sad, ps_est_sad->i4_use_est_intra_sad); |
|
} |
|
|
|
/* |
|
* Get estimated SAD can be called at any point. The various use cases are: |
|
* 1) When a I frame is getting encoded, |
|
* - get the estimated of P => No issues since we use the last coded P frame |
|
* value |
|
* - get estimated of I => This call for two cases: |
|
* => a) if num_ifi_encoded is less than 2 |
|
* then return the previous encoded I frame sad |
|
* => b) if num_ifi_encoded is more than 2, then we scale |
|
* the prev I sad by the ratio of (n-1) ifi P to n-2 ifi P |
|
* 2) When P frame is getting encoded, |
|
* - get the estimated of P => No issues since we use the last coded P frame value |
|
* - get the estimated of I => Simillar to I we have two cases. |
|
* To handle the b) case extra logic had to introduced using |
|
* u1_is_n_1_p_frm_ifi_avg_sad_usable flag |
|
*/ |
|
UWORD32 irc_get_est_sad(est_sad_t *ps_est_sad, picture_type_e e_pic_type) |
|
{ |
|
if(ps_est_sad->i4_use_est_intra_sad) |
|
{ |
|
UWORD32 u4_estimated_sad; |
|
if(e_pic_type == P_PIC) |
|
{ |
|
u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[P_PIC]; |
|
} |
|
else if(e_pic_type == B_PIC) |
|
{ |
|
u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[B_PIC]; |
|
} |
|
else |
|
{ |
|
if(ps_est_sad->i4_num_ifi_encoded < 2) |
|
{ |
|
/* |
|
* Only one IFI has been encoded and so use the previous I |
|
* frames SAD |
|
*/ |
|
u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[I_PIC]; |
|
} |
|
else |
|
{ |
|
/* |
|
* Since the n-1 'P' frame IFI would have just accumulated the |
|
* frame sads we average it out here |
|
*/ |
|
UWORD32 u4_n_1_p_frm_ifi_avg_sad, u4_n_2_p_frm_ifi_avg_sad; |
|
number_t vq_n_1_p_frm_ifi_avg_sad, vq_n_2_p_frm_ifi_avg_sad; |
|
number_t vq_prev_frm_sad_i; |
|
|
|
/* |
|
* If there are frames in the current IFI start using it to |
|
* estimate the I frame SAD |
|
*/ |
|
if(ps_est_sad->i4_num_p_frm_in_cur_ifi) |
|
{ |
|
u4_n_1_p_frm_ifi_avg_sad = |
|
(ps_est_sad->u4_n_p_frm_ifi_avg_sad |
|
/ ps_est_sad->i4_num_p_frm_in_cur_ifi); |
|
u4_n_2_p_frm_ifi_avg_sad = |
|
ps_est_sad->u4_n_1_p_frm_ifi_avg_sad; |
|
} |
|
else |
|
{ |
|
u4_n_1_p_frm_ifi_avg_sad = |
|
ps_est_sad->u4_n_1_p_frm_ifi_avg_sad; |
|
u4_n_2_p_frm_ifi_avg_sad = |
|
ps_est_sad->u4_n_2_p_frm_ifi_avg_sad; |
|
} |
|
|
|
/* |
|
* If any of the previous p frame SADs are zeros we just return |
|
* the previous I frame SAD |
|
*/ |
|
if(u4_n_1_p_frm_ifi_avg_sad && u4_n_2_p_frm_ifi_avg_sad) |
|
{ |
|
SET_VAR_Q(vq_prev_frm_sad_i, |
|
ps_est_sad->au4_prev_frm_sad[I_PIC], 0); |
|
SET_VAR_Q(vq_n_1_p_frm_ifi_avg_sad, |
|
u4_n_1_p_frm_ifi_avg_sad, 0); |
|
SET_VAR_Q(vq_n_2_p_frm_ifi_avg_sad, |
|
u4_n_2_p_frm_ifi_avg_sad, 0); |
|
/* |
|
* Estimated SAD = |
|
*(n-1)th intra frame interval(ifi) P frame Avg SAD * |
|
*(prev I frame SAD / |
|
*(prev (n-2)nd intra frame interval(ifi) P frame Avg SAD) |
|
*/ |
|
mult32_var_q(vq_prev_frm_sad_i, vq_n_1_p_frm_ifi_avg_sad, |
|
&vq_prev_frm_sad_i); |
|
div32_var_q(vq_prev_frm_sad_i, vq_n_2_p_frm_ifi_avg_sad, |
|
&vq_prev_frm_sad_i); |
|
number_t_to_word32(vq_prev_frm_sad_i, |
|
(WORD32*)&u4_estimated_sad); |
|
} |
|
else |
|
{ |
|
u4_estimated_sad = ps_est_sad->au4_prev_frm_sad[I_PIC]; |
|
} |
|
} |
|
} |
|
return u4_estimated_sad; |
|
} |
|
else |
|
{ |
|
return ps_est_sad->au4_prev_frm_sad[e_pic_type]; |
|
} |
|
} |
|
|
|
void irc_update_actual_sad(est_sad_t *ps_est_sad, |
|
UWORD32 u4_actual_sad, |
|
picture_type_e e_pic_type) |
|
{ |
|
ps_est_sad->au4_prev_frm_sad[e_pic_type] = u4_actual_sad; |
|
|
|
if(ps_est_sad->i4_use_est_intra_sad) |
|
{ |
|
if(e_pic_type == I_PIC) |
|
{ |
|
/* The requirement is to have two IFI before estimating I frame SAD */ |
|
if(ps_est_sad->i4_num_ifi_encoded < 2) |
|
ps_est_sad->i4_num_ifi_encoded++; |
|
|
|
/* Calculate the average SAD */ |
|
if(ps_est_sad->i4_num_p_frm_in_cur_ifi) |
|
{ |
|
ps_est_sad->u4_n_p_frm_ifi_avg_sad /= |
|
ps_est_sad->i4_num_p_frm_in_cur_ifi; |
|
} |
|
else |
|
{ |
|
ps_est_sad->u4_n_p_frm_ifi_avg_sad = 0; |
|
} |
|
/* Push the (n-1)th average SAD to the (n-2)th average SAD */ |
|
ps_est_sad->u4_n_2_p_frm_ifi_avg_sad = |
|
ps_est_sad->u4_n_1_p_frm_ifi_avg_sad; |
|
/* Push the nth average SAD to the (n-1)th average SAD */ |
|
ps_est_sad->u4_n_1_p_frm_ifi_avg_sad = |
|
ps_est_sad->u4_n_p_frm_ifi_avg_sad; |
|
/* Reset SAD and number of P frames */ |
|
ps_est_sad->u4_n_p_frm_ifi_avg_sad = 0; |
|
ps_est_sad->i4_num_p_frm_in_cur_ifi = 0; |
|
} |
|
else |
|
{ |
|
ps_est_sad->u4_n_p_frm_ifi_avg_sad += u4_actual_sad; |
|
ps_est_sad->i4_num_p_frm_in_cur_ifi++; |
|
} |
|
} |
|
} |
|
|
|
void irc_update_actual_sad_for_intra(est_sad_t *ps_est_sad, |
|
WORD32 i4_intra_frm_cost) |
|
{ |
|
if(!(ps_est_sad->i4_use_est_intra_sad)) |
|
{ |
|
irc_update_actual_sad(ps_est_sad, i4_intra_frm_cost, I_PIC); |
|
} |
|
}
|
|
|