From 40ed9a784a7e5fdfe29360583bfb62dfe92da1e9 Mon Sep 17 00:00:00 2001 From: Ram Mohan Date: Wed, 7 Aug 2019 14:14:13 +0530 Subject: [PATCH] libhevcenc: reduce memory consumption 1. Removed excess buffer contexts between core encoding and entropy 2. Allocate memory for lookahead feature on a need basis as opposed to allocation based on a pre-defined macro 3. Removed unused/debug structure members Test: hevcenc -c vid_enc_cfg.txt Bug: 139400088 Change-Id: Ibc7228181b51ec97f355b3657df87d70f207cdd9 --- encoder/ihevce_enc_structs.h | 60 ++++---------------------------- encoder/ihevce_frame_process.c | 59 +++++++++++++++++-------------- encoder/ihevce_hle_interface.c | 14 ++------ encoder/ihevce_lap_enc_structs.h | 2 +- encoder/ihevce_memory_init.c | 12 ++++--- 5 files changed, 50 insertions(+), 97 deletions(-) diff --git a/encoder/ihevce_enc_structs.h b/encoder/ihevce_enc_structs.h index b0ec5c6..e9e6921 100644 --- a/encoder/ihevce_enc_structs.h +++ b/encoder/ihevce_enc_structs.h @@ -99,18 +99,8 @@ #define MIN_PRE_ENC_RC_DELAY (MIN_L0_IPE_ENC_STAGGER + 1 + NUM_BUFS_DECOMP_HME) -/** @brief number of contexts buffers maintained at frame level b/w pre-encode : encode */ -/*Explaination for minus 1: eg: MAX_PRE_ENC_STAGGER = 31 and MAX_L0_IPE_ENC_STAGGER = 5, In this case L1 produce 30 buffer, - l0 will start off with 30th buffer and enc will work on 33nd and 34rd frame.*/ -/* NUM_BUFS_DECOMP_HME is added to take care of pipeline between Decomp-preintra and HME */ -#define MAX_NUM_PREENC_ENC_BUFS \ - (MAX_PRE_ENC_STAGGER + MAX_L0_IPE_ENC_STAGGER + NUM_BUFS_DECOMP_HME - 1) //22//5 - -#define MIN_NUM_PREENC_ENC_BUFS \ - (MAX_PRE_ENC_STAGGER + MIN_L0_IPE_ENC_STAGGER + NUM_BUFS_DECOMP_HME - 1) - /** @brief number of ctb contexts maintained at frame level b/w encode : entropy */ -#define NUM_FRMPROC_ENTCOD_BUFS 8 +#define NUM_FRMPROC_ENTCOD_BUFS 1 /** @brief number of extra recon buffs required for stagger design*/ #define NUM_EXTRA_RECON_BUFS 0 @@ -2487,11 +2477,6 @@ typedef struct * based on Load balance b/w stage in encoder */ WORD32 i4_num_active_enc_thrds; - /** Job Queue Memory encode */ - job_queue_t *ps_job_q_enc[PING_PONG_BUF]; - - /** Array of Job Queue handles of enc group for ping and pong instance*/ - job_queue_handle_t as_job_que_enc_hdls[NUM_ENC_JOBS_QUES][PING_PONG_BUF]; /** Mutex for ensuring thread safety of the access of Job queues in encode group */ void *pv_job_q_mutex_hdl_enc_grp_me; @@ -2502,18 +2487,6 @@ typedef struct /** Array of Semaphore handles (for each frame processing threads ) */ void *apv_enc_thrd_sem_handle[MAX_NUM_FRM_PROC_THRDS_ENC]; - /** Array for communcating start processing from master thread to indivisual - * threads in Enocde group of threads - * till 0 : wait - * 1 : start - * After reading the start signal, corresponding thread hould reset it to 0 - */ - WORD32 ai4_enc_frm_proc_start[MAX_NUM_FRM_PROC_THRDS_ENC]; - - /** Note: For Enc loop pass similar memory is used whihc is part of frm_proc_ent_cod_ctxt_t - * for Row level Sync hence not explicitly declared here - */ - /** Array for ME to export the Job que dependency for all layers */ multi_thrd_me_job_q_prms_t as_me_job_q_prms[MAX_NUM_HME_LAYERS][MAX_NUM_VERT_UNITS_FRM]; @@ -2628,47 +2601,29 @@ typedef struct /* Pointers to store input (only L0 IPE)*/ pre_enc_L0_ipe_encloop_ctxt_t *aps_cur_L0_ipe_inp_prms[MAX_NUM_ME_PARALLEL]; - /** Slice header parameters */ - /** temporarily store the slice header parameters in enc-loop thread - which will be copied to curr_out when buffer is aquired */ - //slice_header_t as_slice_hdr[PING_PONG_BUF]; - - /* Array to store input buffer ids for ping and pong instances*/ - //WORD32 in_buf_id[PING_PONG_BUF]; - /* Array tp store L0 IPE input buf ids*/ WORD32 ai4_in_frm_l0_ipe_id[MAX_NUM_ME_PARALLEL]; /* Array to store output buffer ids for ping and pong instances*/ - WORD32 out_buf_id[MAX_NUM_ENC_LOOP_PARALLEL][IHEVCE_MAX_NUM_BITRATES]; //[PING_PONG_BUF]; - - /* Variable to indicate ping and pong instance for each thread*/ - WORD32 ping_pong[MAX_NUM_FRM_PROC_THRDS_ENC]; + WORD32 out_buf_id[MAX_NUM_ENC_LOOP_PARALLEL][IHEVCE_MAX_NUM_BITRATES]; /* Array of pointers to store the recon buf pointers*/ - iv_enc_recon_data_buffs_t - *ps_recon_out[MAX_NUM_ENC_LOOP_PARALLEL][IHEVCE_MAX_NUM_BITRATES]; //[PING_PONG_BUF]; + iv_enc_recon_data_buffs_t *ps_recon_out[MAX_NUM_ENC_LOOP_PARALLEL][IHEVCE_MAX_NUM_BITRATES]; /* Array of pointers to frame recon for ping and pong instances*/ recon_pic_buf_t *ps_frm_recon[NUM_ME_ENC_BUFS][IHEVCE_MAX_NUM_BITRATES]; /* Array of recon buffer ids for ping and pong instance*/ - WORD32 recon_buf_id[NUM_ME_ENC_BUFS][IHEVCE_MAX_NUM_BITRATES]; //[PING_PONG_BUF]; - - /* End flag to signal end of all the frames in me*/ - WORD32 me_end_flag; - - /* End flag to signal end of all the frames in enc*/ - WORD32 enc_end_flag; + WORD32 recon_buf_id[NUM_ME_ENC_BUFS][IHEVCE_MAX_NUM_BITRATES]; /* Counter to keep track of num thrds done*/ WORD32 num_thrds_done; /* Flags to keep track of dumped ping pong recon buffer*/ - WORD32 is_recon_dumped[MAX_NUM_ENC_LOOP_PARALLEL][IHEVCE_MAX_NUM_BITRATES]; //[PING_PONG_BUF]; + WORD32 is_recon_dumped[MAX_NUM_ENC_LOOP_PARALLEL][IHEVCE_MAX_NUM_BITRATES]; /* Flags to keep track of dumped ping pong output buffer*/ - WORD32 is_out_buf_freed[MAX_NUM_ENC_LOOP_PARALLEL][IHEVCE_MAX_NUM_BITRATES]; //[PING_PONG_BUF]; + WORD32 is_out_buf_freed[MAX_NUM_ENC_LOOP_PARALLEL][IHEVCE_MAX_NUM_BITRATES]; /* flag to produce output buffer by the thread who ever is finishing enc-loop processing first, so that the entropy thread can start processing */ @@ -2787,9 +2742,6 @@ typedef struct /** buffer id for L0 IPE enc buffer*/ WORD32 i4_L0_IPE_out_buf_id; - /** current frame recon pointer */ - recon_pic_buf_t *aps_frm_recon_pre_enc[MAX_PRE_ENC_STAGGER + NUM_BUFS_DECOMP_HME]; - /** Current picture Qp */ WORD32 ai4_cur_frame_qp_pre_enc[MAX_PRE_ENC_STAGGER + NUM_BUFS_DECOMP_HME]; diff --git a/encoder/ihevce_frame_process.c b/encoder/ihevce_frame_process.c index 4b75a60..5476050 100644 --- a/encoder/ihevce_frame_process.c +++ b/encoder/ihevce_frame_process.c @@ -362,10 +362,12 @@ void complexity_RC_reset_marking(enc_ctxt_t *ps_enc_ctxt, WORD32 i4_cur_ipe_idx, ASSERT(i4_is_cur_pic_high_complex_region != -1); /*get the next idx of p/i picture */ - i4_next_ipe_idx = - (i4_cur_ipe_idx + 1) % (ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe + 1); - i4_temp_ipe_idx = - (i4_cur_ipe_idx + 1) % (ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe + 1); + i4_next_ipe_idx = (i4_cur_ipe_idx + 1); + if(i4_next_ipe_idx >= ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe) + { + i4_next_ipe_idx = 0; + } + i4_temp_ipe_idx = i4_next_ipe_idx; for(i = 0; i < (1 << i4_max_temporal_layers); i++) { ps_lap_out_temp = @@ -376,12 +378,18 @@ void complexity_RC_reset_marking(enc_ctxt_t *ps_enc_ctxt, WORD32 i4_cur_ipe_idx, { break; } - i4_next_ipe_idx = (i4_next_ipe_idx + 1) % - (ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe + 1); + i4_next_ipe_idx++; + if(i4_next_ipe_idx >= ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe) + { + i4_next_ipe_idx = 0; + } } /* get the next idx of next p/i picture*/ - i4_next_next_ipe_idx = - (i4_next_ipe_idx + 1) % (ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe + 1); + i4_next_next_ipe_idx = (i4_next_ipe_idx + 1); + if(i4_next_next_ipe_idx >= ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe) + { + i4_next_next_ipe_idx = 0; + } for(i = 0; i < (1 << i4_max_temporal_layers); i++) { ps_lap_out_temp = @@ -392,8 +400,11 @@ void complexity_RC_reset_marking(enc_ctxt_t *ps_enc_ctxt, WORD32 i4_cur_ipe_idx, { break; } - i4_next_next_ipe_idx = (i4_next_next_ipe_idx + 1) % - (ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe + 1); + i4_next_next_ipe_idx++; + if(i4_next_next_ipe_idx >= ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe) + { + i4_next_next_ipe_idx = 0; + } } /*check for any possible RC reset in the future 8 frames*/ @@ -411,8 +422,11 @@ void complexity_RC_reset_marking(enc_ctxt_t *ps_enc_ctxt, WORD32 i4_cur_ipe_idx, { ps_enc_ctxt->i4_future_RC_scd_reset = 1; } - i4_temp_ipe_idx = (i4_temp_ipe_idx + 1) % - (ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe + 1); + i4_temp_ipe_idx++; + if(i4_temp_ipe_idx >= ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe) + { + i4_temp_ipe_idx = 0; + } } if((!ps_enc_ctxt->i4_future_RC_reset) && (ps_enc_ctxt->i4_past_RC_reset_count > 8)) @@ -3021,11 +3035,6 @@ WORD32 ihevce_enc_frm_proc_slave_thrd(void *pv_frm_proc_thrd_ctxt) ps_curr_out_me->i4_end_flag = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->i4_end_flag; - /* set the parameters for sync b/w entropy thread */ - - ps_enc_ctxt->s_multi_thrd.me_end_flag = - ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->i4_end_flag; - /* do the processing if input frm data is valid */ if(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag) { @@ -5582,7 +5591,7 @@ void ihevce_variance_calc_acc_activity(enc_ctxt_t *ps_enc_ctxt, WORD32 i4_cur_ip (ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_lap_out.i4_pic_type == IV_P_FRAME); - WORD32 i4_delay_loop = (ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe + 1); + WORD32 i4_delay_loop = ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe; pre_enc_me_ctxt_t *ps_pre_enc_me_ctxt_t; pre_enc_me_ctxt_t *ps_curr_out = ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[i4_cur_ipe_idx]; rc_lap_out_params_t *ps_temp_ipe_rc_lap_out; @@ -6304,7 +6313,7 @@ WORD32 ihevce_pre_enc_process_frame_thrd(void *pv_frm_proc_thrd_ctxt) i4_cur_decomp_idx = i4_cur_decomp_idx + 1; /* wrap around case */ - if(i4_cur_decomp_idx == (MAX_PRE_ENC_STAGGER + NUM_BUFS_DECOMP_HME)) + if(i4_cur_decomp_idx >= ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe) { i4_cur_decomp_idx = 0; } @@ -6353,9 +6362,6 @@ WORD32 ihevce_pre_enc_process_frame_thrd(void *pv_frm_proc_thrd_ctxt) ps_multi_thrd->ai4_decomp_lyr_buf_idx[i4_cur_coarse_me_idx], ps_multi_thrd->ai4_cur_frame_qp_pre_enc[i4_cur_coarse_me_idx], i4_cur_coarse_me_idx); - - /* store the recon buffer pointer */ - ps_multi_thrd->aps_frm_recon_pre_enc[i4_cur_coarse_me_idx] = ps_frm_recon; } ps_multi_thrd->ai4_pre_enc_hme_init_done[i4_cur_coarse_me_idx] = 1; @@ -6418,7 +6424,7 @@ WORD32 ihevce_pre_enc_process_frame_thrd(void *pv_frm_proc_thrd_ctxt) /* wrap around case */ if(i4_cur_coarse_me_idx == 0) { - i4_prev_coarse_me_idx = MAX_PRE_ENC_STAGGER + NUM_BUFS_DECOMP_HME - 1; + i4_prev_coarse_me_idx = ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe - 1; } else { @@ -6495,7 +6501,7 @@ WORD32 ihevce_pre_enc_process_frame_thrd(void *pv_frm_proc_thrd_ctxt) i4_cur_coarse_me_idx = i4_cur_coarse_me_idx + 1; /* wrap around case */ - if(i4_cur_coarse_me_idx == (MAX_PRE_ENC_STAGGER + NUM_BUFS_DECOMP_HME)) + if(i4_cur_coarse_me_idx >= ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe) { i4_cur_coarse_me_idx = 0; } @@ -6531,7 +6537,7 @@ WORD32 ihevce_pre_enc_process_frame_thrd(void *pv_frm_proc_thrd_ctxt) i4_cur_coarse_me_idx = i4_cur_coarse_me_idx + 1; /* wrap around case */ - if(i4_cur_coarse_me_idx == (MAX_PRE_ENC_STAGGER + NUM_BUFS_DECOMP_HME)) + if(i4_cur_coarse_me_idx >= ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe) { i4_cur_coarse_me_idx = 0; } @@ -6970,10 +6976,11 @@ WORD32 ihevce_pre_enc_process_frame_thrd(void *pv_frm_proc_thrd_ctxt) i4_cur_ipe_idx = i4_cur_ipe_idx + 1; /* wrap around case */ - if(i4_cur_ipe_idx == (MAX_PRE_ENC_STAGGER + NUM_BUFS_DECOMP_HME)) + if(i4_cur_ipe_idx >= ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe) { i4_cur_ipe_idx = 0; } + i4_num_buf_prod_for_l0_ipe--; } /*NOTE: update of above indices should mark end if ipe.do not access below this*/ diff --git a/encoder/ihevce_hle_interface.c b/encoder/ihevce_hle_interface.c index 3d9926e..9fd8bec 100644 --- a/encoder/ihevce_hle_interface.c +++ b/encoder/ihevce_hle_interface.c @@ -1071,8 +1071,6 @@ WORD32 ihevce_hle_interface_thrd(void *pv_proc_intf_ctxt) /*initialize multi-thread context for enc group*/ ps_enc_ctxt->s_multi_thrd.i4_is_recon_free_done = 0; - ps_enc_ctxt->s_multi_thrd.me_end_flag = 0; - ps_enc_ctxt->s_multi_thrd.enc_end_flag = 0; ps_enc_ctxt->s_multi_thrd.i4_idx_dvsr_p = 0; ps_enc_ctxt->s_multi_thrd.i4_last_inp_buf = 0; @@ -1128,17 +1126,10 @@ WORD32 ihevce_hle_interface_thrd(void *pv_proc_intf_ctxt) ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_prev_frame_me_done[i]); } - /* reset the completed status & start proc flags of slave encode frame processing threads */ - for(ctr = 0; ctr < ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds; ctr++) - { - ps_enc_ctxt->s_multi_thrd.ai4_enc_frm_proc_start[ctr] = 0; - } - /* initialize multi-thread context for pre enc group */ ps_enc_ctxt->s_multi_thrd.i4_ctrl_blocking_mode = BUFF_QUE_BLOCKING_MODE; - //for (ctr=0; ctr< PING_PONG_BUF; ctr++) for(ctr = 0; ctr < MAX_PRE_ENC_STAGGER + NUM_BUFS_DECOMP_HME; ctr++) { ps_enc_ctxt->s_multi_thrd.ai4_pre_enc_init_done[ctr] = 0; @@ -1167,10 +1158,11 @@ WORD32 ihevce_hle_interface_thrd(void *pv_proc_intf_ctxt) /**init idx for handling delay between pre-me and l0-ipe*/ ps_enc_ctxt->s_multi_thrd.i4_delay_pre_me_btw_l0_ipe = 0; ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe = - MAX_PRE_ENC_STAGGER + NUM_BUFS_DECOMP_HME - 1; + MIN_L1_L0_STAGGER_NON_SEQ + + ps_enc_ctxt->s_lap_stat_prms.s_lap_params.i4_rc_look_ahead_pics + 1; if(ps_enc_ctxt->s_lap_stat_prms.s_lap_params.i4_rc_look_ahead_pics) { - ps_enc_ctxt->s_multi_thrd.i4_delay_pre_me_btw_l0_ipe += + ps_enc_ctxt->s_multi_thrd.i4_delay_pre_me_btw_l0_ipe = MIN_L1_L0_STAGGER_NON_SEQ + ps_enc_ctxt->s_lap_stat_prms.s_lap_params.i4_rc_look_ahead_pics; } diff --git a/encoder/ihevce_lap_enc_structs.h b/encoder/ihevce_lap_enc_structs.h index 054f369..65becd2 100644 --- a/encoder/ihevce_lap_enc_structs.h +++ b/encoder/ihevce_lap_enc_structs.h @@ -48,7 +48,7 @@ #define MAX_SCENE_NUM 30 #define INIT_HEVCE_QP_RC (-300) #define MAX_TEMPORAL_LAYERS 3 -#define NUM_LAP2_LOOK_AHEAD 120 +#define NUM_LAP2_LOOK_AHEAD 25 #define INFINITE_GOP_CDR_TIME_S 3 #define FRAME_PARALLEL_LVL 0 diff --git a/encoder/ihevce_memory_init.c b/encoder/ihevce_memory_init.c index 3402003..966baf9 100644 --- a/encoder/ihevce_memory_init.c +++ b/encoder/ihevce_memory_init.c @@ -181,7 +181,7 @@ void ihevce_mem_manager_init(enc_ctxt_t *ps_enc_ctxt, ihevce_hle_ctxt_t *ps_intr WORD32 a_disp_wd[MAX_NUM_HME_LAYERS], a_disp_ht[MAX_NUM_HME_LAYERS]; WORD32 a_ctb_align_wd[MAX_NUM_HME_LAYERS], a_ctb_align_ht[MAX_NUM_HME_LAYERS]; WORD32 n_enc_layers = 1, n_tot_layers; - WORD32 num_bufs_preenc_me_que, num_bufs_L0_ipe_enc; + WORD32 num_bufs_preenc_me_que, num_bufs_L0_ipe_enc, max_delay_preenc_l0_que; WORD32 i, i4_resolution_id = ps_enc_ctxt->i4_resolution_id; //counter WORD32 i4_num_bitrate_inst; iv_mem_rec_t *ps_memtab; @@ -392,6 +392,9 @@ void ihevce_mem_manager_init(enc_ctxt_t *ps_enc_ctxt, ihevce_hle_ctxt_t *ps_intr { num_bufs_L0_ipe_enc = MIN_L0_IPE_ENC_STAGGER; } + + max_delay_preenc_l0_que = MIN_L1_L0_STAGGER_NON_SEQ + + ps_enc_ctxt->ps_stat_prms->s_lap_prms.i4_rc_look_ahead_pics + 1; } /* ------------ popluate the lap static parameters ------------- */ @@ -1398,10 +1401,9 @@ void ihevce_mem_manager_init(enc_ctxt_t *ps_enc_ctxt, ihevce_hle_ctxt_t *ps_intr /* Job Queue related memory */ /* max num ctb rows is doubled to take care worst case */ /* requirements because of HME layers */ - buf_size = (MAX_NUM_VERT_UNITS_FRM) * (NUM_PRE_ENC_JOBS_QUES) * - (MAX_PRE_ENC_STAGGER + NUM_BUFS_DECOMP_HME); //PING_PONG_BUF; - + buf_size = (MAX_NUM_VERT_UNITS_FRM) * (NUM_PRE_ENC_JOBS_QUES) * (max_delay_preenc_l0_que); buf_size *= sizeof(job_queue_t); + ps_memtab[total_memtabs_used].i4_mem_alignment = 8; ps_memtab[total_memtabs_used].e_mem_type = (IV_MEM_TYPE_T)space_for_mem_in_enc_grp; @@ -2253,7 +2255,7 @@ void ihevce_mem_manager_init(enc_ctxt_t *ps_enc_ctxt, ihevce_hle_ctxt_t *ps_intr */ ps_enc_ctxt->s_multi_thrd.aps_job_q_pre_enc[0] = (job_queue_t *)ps_memtab->pv_base; - for(ctr = 1; ctr < MAX_PRE_ENC_STAGGER + NUM_BUFS_DECOMP_HME; ctr++) + for(ctr = 1; ctr < max_delay_preenc_l0_que; ctr++) { ps_enc_ctxt->s_multi_thrd.aps_job_q_pre_enc[ctr] = ps_enc_ctxt->s_multi_thrd.aps_job_q_pre_enc[0] +