xref: /aosp_15_r20/external/libhevc/encoder/ihevce_frame_process.c (revision c83a76b084498d55f252f48b2e3786804cdf24b7)
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 ******************************************************************************
23 * \file ihevce_frame_process.c
24 *
25 * \brief
26 *    This file contains top level functions related Frame processing
27 *
28 * \date
29 *    18/09/2012
30 *
31 * \author
32 *    Ittiam
33 *
34 *
35 * List of Functions
36 *
37 *
38 ******************************************************************************
39 */
40 
41 /*****************************************************************************/
42 /* File Includes                                                             */
43 /*****************************************************************************/
44 /* System include files */
45 #include <stdio.h>
46 #include <string.h>
47 #include <stdlib.h>
48 #include <assert.h>
49 #include <stdarg.h>
50 #include <math.h>
51 #include <time.h>
52 
53 /* User include files */
54 #include "ihevc_typedefs.h"
55 #include "itt_video_api.h"
56 #include "ihevce_api.h"
57 
58 #include "rc_cntrl_param.h"
59 #include "rc_frame_info_collector.h"
60 #include "rc_look_ahead_params.h"
61 
62 #include "ihevc_defs.h"
63 #include "ihevc_debug.h"
64 #include "ihevc_macros.h"
65 #include "ihevc_structs.h"
66 #include "ihevc_platform_macros.h"
67 #include "ihevc_deblk.h"
68 #include "ihevc_itrans_recon.h"
69 #include "ihevc_chroma_itrans_recon.h"
70 #include "ihevc_chroma_intra_pred.h"
71 #include "ihevc_intra_pred.h"
72 #include "ihevc_inter_pred.h"
73 #include "ihevc_mem_fns.h"
74 #include "ihevc_padding.h"
75 #include "ihevc_weighted_pred.h"
76 #include "ihevc_sao.h"
77 #include "ihevc_resi_trans.h"
78 #include "ihevc_quant_iquant_ssd.h"
79 #include "ihevc_cabac_tables.h"
80 #include "ihevc_common_tables.h"
81 
82 #include "ihevce_defs.h"
83 #include "ihevce_buffer_que_interface.h"
84 #include "ihevce_hle_interface.h"
85 #include "ihevce_hle_q_func.h"
86 #include "ihevce_lap_enc_structs.h"
87 #include "ihevce_lap_interface.h"
88 #include "ihevce_multi_thrd_structs.h"
89 #include "ihevce_multi_thrd_funcs.h"
90 #include "ihevce_me_common_defs.h"
91 #include "ihevce_had_satd.h"
92 #include "ihevce_error_checks.h"
93 #include "ihevce_error_codes.h"
94 #include "ihevce_bitstream.h"
95 #include "ihevce_cabac.h"
96 #include "ihevce_rdoq_macros.h"
97 #include "ihevce_function_selector.h"
98 #include "ihevce_enc_structs.h"
99 #include "ihevce_global_tables.h"
100 #include "ihevce_cmn_utils_instr_set_router.h"
101 #include "ihevce_ipe_instr_set_router.h"
102 #include "ihevce_entropy_structs.h"
103 #include "ihevce_enc_loop_structs.h"
104 #include "ihevce_enc_loop_utils.h"
105 #include "ihevce_inter_pred.h"
106 #include "ihevce_common_utils.h"
107 #include "ihevce_sub_pic_rc.h"
108 #include "hme_datatype.h"
109 #include "hme_interface.h"
110 #include "hme_common_defs.h"
111 #include "hme_defs.h"
112 #include "ihevce_enc_loop_pass.h"
113 #include "ihevce_trace.h"
114 #include "ihevce_encode_header.h"
115 #include "ihevce_encode_header_sei_vui.h"
116 #include "ihevce_ipe_structs.h"
117 #include "ihevce_ipe_pass.h"
118 #include "ihevce_dep_mngr_interface.h"
119 #include "ihevce_rc_enc_structs.h"
120 #include "hme_globals.h"
121 #include "ihevce_me_pass.h"
122 #include "ihevce_coarse_me_pass.h"
123 #include "ihevce_frame_process.h"
124 #include "ihevce_rc_interface.h"
125 #include "ihevce_profile.h"
126 #include "ihevce_decomp_pre_intra_structs.h"
127 #include "ihevce_decomp_pre_intra_pass.h"
128 #include "ihevce_frame_process_utils.h"
129 
130 #include "cast_types.h"
131 #include "osal.h"
132 #include "osal_defaults.h"
133 
134 /*****************************************************************************/
135 /* Constant Macros                                                           */
136 /*****************************************************************************/
137 
138 #define REF_MOD_STRENGTH 1.0
139 #define REF_MAX_STRENGTH 1.4f
140 
141 /*****************************************************************************/
142 /* Extern variables                                                          */
143 /*****************************************************************************/
144 
145 /**
146 * @var   QP2QUANT_MD[]
147 *
148 * @brief Direct Cost Comoparision Table
149 *
150 * @param Comments: Direct cost is compared with 16 * QP2QUANT_MD[Qp]
151 *                  If direct cost is less  than 16 * QP2QUANT_MD[Qp]
152 *                  than direct cost is assumed to be zero
153 */
154 const WORD16 QP2QUANT_MD[52] = { 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
155                                  1,  1,  1,  2,  2,  2,  2,  3,  3,  3,  4,  4,  4,
156                                  5,  6,  6,  7,  8,  9,  10, 11, 13, 14, 16, 18, 20,
157                                  23, 25, 29, 32, 36, 40, 45, 51, 57, 64, 72, 81, 91 };
158 
159 /*
160 Gaussian 11x11 window with a sigma of 1.5 - values multiplied by 2048
161 Window made into 9x9 window as most entries were zero
162 The center weight has been reduced by 1 after dropping first row/col and last row/col
163 */
164 UWORD8 g_u1_win_size = 9;
165 UWORD8 g_u1_win_q_shift = 11;
166 UWORD8 au1_g_win[81] = { 0,  1,  2, 3,  4,  3,   2,   1,   0,  1,  3, 8,  16, 20, 16,  8,   3,
167                          1,  2,  8, 24, 48, 60,  48,  24,  8,  2,  3, 16, 48, 93, 116, 93,  48,
168                          16, 3,  4, 20, 60, 116, 144, 116, 60, 20, 4, 3,  16, 48, 93,  116, 93,
169                          48, 16, 3, 2,  8,  24,  48,  60,  48, 24, 8, 2,  1,  3,  8,   16,  20,
170                          16, 8,  3, 1,  0,  1,   2,   3,   4,  3,  2, 1,  0 };
171 
172 /* lagrange params */
173 const double lamda_modifier_for_I_pic[8] = { 0.85,   0.7471, 0.6646, 0.5913,
174                                              0.5261, 0.4680, 0.4164, 0.3705 };
175 
176 /*****************************************************************************/
177 /* Function Definitions                                                      */
178 /*****************************************************************************/
179 
180 /*!
181 ******************************************************************************
182 * \if Function name : ihevce_mbr_quality_tool_set_configuration \endif
183 *
184 * \brief
185 *   tool set selection for auxilary bitrate. currently only num intra and inter
186 *       candidates for auxilary bitrates are controlled
187 *
188 * \param[in] ps_enc_loop_thrd_ctxt : enc ctxt
189 * \param[in] ps_stat_prms: static parameters
190 * \return
191 *    None
192 *
193 * \author
194 *  Ittiam
195 *
196 *****************************************************************************
197 */
ihevce_mbr_quality_tool_set_configuration(ihevce_enc_loop_ctxt_t * ps_enc_loop_thrd_ctxt,ihevce_static_cfg_params_t * ps_stat_prms)198 void ihevce_mbr_quality_tool_set_configuration(
199     ihevce_enc_loop_ctxt_t *ps_enc_loop_thrd_ctxt, ihevce_static_cfg_params_t *ps_stat_prms)
200 {
201     /* for single bitrate encoder*/
202     switch(ps_stat_prms->s_tgt_lyr_prms.i4_mbr_quality_setting)
203     {
204     case IHEVCE_MBR_HIGH_QUALITY:
205         ps_enc_loop_thrd_ctxt->i4_num_modes_to_evaluate_intra = 3;
206         ps_enc_loop_thrd_ctxt->i4_num_modes_to_evaluate_inter = 4;
207         break;
208 
209     case IHEVCE_MBR_MEDIUM_SPEED:
210         ps_enc_loop_thrd_ctxt->i4_num_modes_to_evaluate_intra = 3;
211         ps_enc_loop_thrd_ctxt->i4_num_modes_to_evaluate_inter = 3;
212         break;
213 
214     case IHEVCE_MBR_HIGH_SPEED:
215         ps_enc_loop_thrd_ctxt->i4_num_modes_to_evaluate_intra = 2;
216         ps_enc_loop_thrd_ctxt->i4_num_modes_to_evaluate_inter = 2;
217         break;
218 
219     case IHEVCE_MBR_EXTREME_SPEED:
220         ps_enc_loop_thrd_ctxt->i4_num_modes_to_evaluate_intra = 1;
221         ps_enc_loop_thrd_ctxt->i4_num_modes_to_evaluate_inter = 1;
222         break;
223 
224     default:
225         assert(0);
226         break;
227     }
228 }
229 
230 /*!
231 ******************************************************************************
232 * \if Function name : ihevce_find_free_indx \endif
233 *
234 * \brief
235 *    Pre encode Frame processing slave thread entry point function
236 *
237 * \param[in] Frame processing thread context pointer
238 *
239 * \return
240 *    None
241 *
242 * \author
243 *  Ittiam
244 *
245 *****************************************************************************
246 */
ihevce_find_free_indx(recon_pic_buf_t ** pps_recon_buf_q,WORD32 i4_num_buf)247 WORD32 ihevce_find_free_indx(recon_pic_buf_t **pps_recon_buf_q, WORD32 i4_num_buf)
248 {
249     WORD32 i4_ctr;
250     WORD32 i4_is_full = 1;
251     WORD32 i4_least_POC = 0x7FFFFFFF;
252     WORD32 i4_least_POC_idx = -1;
253     WORD32 i4_least_GOP_num = 0x7FFFFFFF;
254 
255     for(i4_ctr = 0; i4_ctr < i4_num_buf; i4_ctr++)
256     {
257         if(pps_recon_buf_q[i4_ctr]->i4_is_free == 1)
258         {
259             i4_is_full = 0;
260             break;
261         }
262     }
263     if(i4_is_full)
264     {
265         /* remove if any non-reference pictures are present */
266         for(i4_ctr = 0; i4_ctr < i4_num_buf; i4_ctr++)
267         {
268             if(!pps_recon_buf_q[i4_ctr]->i4_is_reference &&
269                pps_recon_buf_q[i4_ctr]->i4_non_ref_free_flag)
270             {
271                 i4_least_POC_idx = i4_ctr;
272                 break;
273             }
274         }
275         /* if all non reference pictures are removed, then find the least poc
276         in the least gop number*/
277         if(i4_least_POC_idx == -1)
278         {
279             for(i4_ctr = 0; i4_ctr < i4_num_buf; i4_ctr++)
280             {
281                 if(i4_least_GOP_num > pps_recon_buf_q[i4_ctr]->i4_idr_gop_num)
282                 {
283                     i4_least_GOP_num = pps_recon_buf_q[i4_ctr]->i4_idr_gop_num;
284                 }
285             }
286             for(i4_ctr = 0; i4_ctr < i4_num_buf; i4_ctr++)
287             {
288                 if(i4_least_POC > pps_recon_buf_q[i4_ctr]->i4_poc &&
289                    i4_least_GOP_num == pps_recon_buf_q[i4_ctr]->i4_idr_gop_num)
290                 {
291                     i4_least_POC = pps_recon_buf_q[i4_ctr]->i4_poc;
292                     i4_least_POC_idx = i4_ctr;
293                 }
294             }
295         }
296     }
297     return i4_least_POC_idx;
298 }
299 
300 /*!
301 ******************************************************************************
302 * \if Function name : complexity_RC_reset_marking \endif
303 *
304 * \brief
305 *   this function the complexity variation and set the complexity change flag for
306 *   rate control to reset the model
307 *
308 * \param[in] ps_enc_loop_thrd_ctxt : enc ctxt
309 * \param[in] ps_stat_prms: static parameters
310 * \return
311 *    None
312 *
313 * \author
314 *  Ittiam
315 *
316 *****************************************************************************
317 */
complexity_RC_reset_marking(enc_ctxt_t * ps_enc_ctxt,WORD32 i4_cur_ipe_idx,WORD32 i4_end_flag)318 void complexity_RC_reset_marking(enc_ctxt_t *ps_enc_ctxt, WORD32 i4_cur_ipe_idx, WORD32 i4_end_flag)
319 {
320     rc_lap_out_params_t *ps_cur_ipe_lap_out;
321     rc_lap_out_params_t *ps_lap_out_temp;
322     WORD32 i4_max_temporal_layers;
323 
324     ps_cur_ipe_lap_out =
325         &ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_rc_lap_out;
326     ps_cur_ipe_lap_out->i4_is_cmplx_change_reset_model = 0;
327     ps_cur_ipe_lap_out->i4_is_cmplx_change_reset_bits = 0;
328 
329     i4_max_temporal_layers = ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_max_temporal_layers;
330 
331     /*reset the RC_reset counter at reset points*/
332     if(ps_cur_ipe_lap_out->i4_is_I_only_scd || ps_cur_ipe_lap_out->i4_is_non_I_scd ||
333        ps_cur_ipe_lap_out->i4_rc_scene_type == SCENE_TYPE_SCENE_CUT)
334     {
335         ps_enc_ctxt->i4_past_RC_reset_count = 0;
336     }
337 
338     if(ps_cur_ipe_lap_out->i4_rc_scene_type == SCENE_TYPE_SCENE_CUT)
339     {
340         ps_enc_ctxt->i4_past_RC_scd_reset_count = 0;
341     }
342     ps_enc_ctxt->i4_past_RC_reset_count++;
343     ps_enc_ctxt->i4_past_RC_scd_reset_count++;
344 
345     /*complexity based rate control reset */
346 
347     if((ps_cur_ipe_lap_out->i4_rc_pic_type == IV_P_FRAME ||
348         ps_cur_ipe_lap_out->i4_rc_pic_type == IV_I_FRAME) &&
349        (i4_max_temporal_layers > 1) && (!i4_end_flag) &&
350        (ps_enc_ctxt->s_multi_thrd.i4_delay_pre_me_btw_l0_ipe > (2 * (1 << i4_max_temporal_layers))))
351     {
352         WORD32 i4_is_cur_pic_high_complex_region =
353             ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[i4_cur_ipe_idx]
354                 ->i4_is_high_complex_region;
355         WORD32 i4_next_ipe_idx;
356         WORD32 i4_next_next_ipe_idx;
357         WORD32 i4_temp_ipe_idx;
358         WORD32 i;
359 
360         ps_enc_ctxt->i4_future_RC_reset = 0;
361         ps_enc_ctxt->i4_future_RC_scd_reset = 0;
362         ASSERT(i4_is_cur_pic_high_complex_region != -1);
363 
364         /*get the next idx of p/i picture */
365         i4_next_ipe_idx = (i4_cur_ipe_idx + 1);
366         if(i4_next_ipe_idx >= ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe)
367         {
368             i4_next_ipe_idx = 0;
369         }
370         i4_temp_ipe_idx = i4_next_ipe_idx;
371         for(i = 0; i < (1 << i4_max_temporal_layers); i++)
372         {
373             ps_lap_out_temp =
374                 &ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_next_ipe_idx]->s_rc_lap_out;
375 
376             if(ps_lap_out_temp->i4_rc_pic_type == IV_P_FRAME ||
377                ps_lap_out_temp->i4_rc_pic_type == IV_I_FRAME)
378             {
379                 break;
380             }
381             i4_next_ipe_idx++;
382             if(i4_next_ipe_idx >= ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe)
383             {
384                 i4_next_ipe_idx = 0;
385             }
386         }
387         /* get the next idx of next p/i picture*/
388         i4_next_next_ipe_idx = (i4_next_ipe_idx + 1);
389         if(i4_next_next_ipe_idx >= ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe)
390         {
391             i4_next_next_ipe_idx = 0;
392         }
393         for(i = 0; i < (1 << i4_max_temporal_layers); i++)
394         {
395             ps_lap_out_temp =
396                 &ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_next_next_ipe_idx]->s_rc_lap_out;
397 
398             if(ps_lap_out_temp->i4_rc_pic_type == IV_P_FRAME ||
399                ps_lap_out_temp->i4_rc_pic_type == IV_I_FRAME)
400             {
401                 break;
402             }
403             i4_next_next_ipe_idx++;
404             if(i4_next_next_ipe_idx >= ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe)
405             {
406                 i4_next_next_ipe_idx = 0;
407             }
408         }
409 
410         /*check for any possible RC reset in the future 8 frames*/
411         for(i = 0; i < 8; i++)
412         {
413             ps_lap_out_temp =
414                 &ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_temp_ipe_idx]->s_rc_lap_out;
415 
416             if(ps_lap_out_temp->i4_is_I_only_scd || ps_lap_out_temp->i4_is_non_I_scd ||
417                ps_lap_out_temp->i4_rc_scene_type == SCENE_TYPE_SCENE_CUT)
418             {
419                 ps_enc_ctxt->i4_future_RC_reset = 1;
420             }
421             if(ps_cur_ipe_lap_out->i4_rc_scene_type == SCENE_TYPE_SCENE_CUT)
422             {
423                 ps_enc_ctxt->i4_future_RC_scd_reset = 1;
424             }
425             i4_temp_ipe_idx++;
426             if(i4_temp_ipe_idx >= ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe)
427             {
428                 i4_temp_ipe_idx = 0;
429             }
430         }
431 
432         if((!ps_enc_ctxt->i4_future_RC_reset) && (ps_enc_ctxt->i4_past_RC_reset_count > 8))
433         {
434             /*if the prev two P/I pic is not in high complex region
435             then enable reset RC flag*/
436             if((!ps_enc_ctxt->ai4_is_past_pic_complex[0]) &&
437                (!ps_enc_ctxt->ai4_is_past_pic_complex[1]))
438             {
439                 if(i4_is_cur_pic_high_complex_region)
440                 {
441                     ps_cur_ipe_lap_out->i4_is_cmplx_change_reset_model = 1;
442                     ps_cur_ipe_lap_out->i4_is_cmplx_change_reset_bits = 1;
443                     ps_enc_ctxt->i4_is_I_reset_done = 0;
444                 }
445             }
446 
447             /*if the next two P/I pic is not in high complex region
448             then enable reset RC flag*/
449             if((!ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[i4_next_ipe_idx]
450                      ->i4_is_high_complex_region) &&
451                (!ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[i4_next_next_ipe_idx]
452                      ->i4_is_high_complex_region))
453             {
454                 if(i4_is_cur_pic_high_complex_region)
455                 {
456                     ps_cur_ipe_lap_out->i4_is_cmplx_change_reset_model = 1;
457                     ps_cur_ipe_lap_out->i4_is_cmplx_change_reset_bits = 1;
458                     ps_enc_ctxt->i4_is_I_reset_done = 0;
459                 }
460             }
461         }
462         else if((!ps_enc_ctxt->i4_future_RC_scd_reset) && (ps_enc_ctxt->i4_past_RC_scd_reset_count > 8))
463         {
464             /*if the prev two P/I pic is not in high complex region
465             then enable reset RC flag*/
466             if((!ps_enc_ctxt->ai4_is_past_pic_complex[0]) &&
467                (!ps_enc_ctxt->ai4_is_past_pic_complex[1]))
468             {
469                 if(i4_is_cur_pic_high_complex_region)
470                 {
471                     ps_cur_ipe_lap_out->i4_is_cmplx_change_reset_bits = 1;
472                 }
473             }
474 
475             /*if the next two P/I pic is not in high complex region
476             then enable reset RC flag*/
477             if((!ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[i4_next_ipe_idx]
478                      ->i4_is_high_complex_region) &&
479                (!ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[i4_next_next_ipe_idx]
480                      ->i4_is_high_complex_region))
481             {
482                 if(i4_is_cur_pic_high_complex_region)
483                 {
484                     ps_cur_ipe_lap_out->i4_is_cmplx_change_reset_bits = 1;
485                 }
486             }
487         }
488 
489         /* forcing I frame reset after complexity change is disable as it gives gain, could be due to that
490         required i reset is already happening on pre Intra SAD*/
491         /*if(!ps_enc_ctxt->i4_is_I_reset_done && (ps_cur_ipe_lap_out->i4_pic_type
492         == IV_I_FRAME))
493         {
494             ps_cur_ipe_lap_out->i4_is_I_only_scd = 1;
495             ps_enc_ctxt->i4_is_I_reset_done = 1;
496         }*/
497 
498         ps_enc_ctxt->ai4_is_past_pic_complex[0] = i4_is_cur_pic_high_complex_region;
499 
500         ps_enc_ctxt->ai4_is_past_pic_complex[1] = ps_enc_ctxt->ai4_is_past_pic_complex[0];
501     }
502     return;
503 }
504 /*!
505 ******************************************************************************
506 * \if Function name : ihevce_manage_ref_pics \endif
507 *
508 * \brief
509 *    Reference picture management based on delta poc array given by LAP
510 *    Populates the reference list after removing non used reference pictures
511 *    populates the delta poc of reference pics to be signalled in slice header
512 *
513 * \param[in] encoder context pointer
514 * \param[in] current LAP Encoder buffer pointer
515 * \param[in] current frame process and entropy buffer pointer
516 *
517 * \return
518 *    None
519 *
520 * \author
521 *  Ittiam
522 *
523 *****************************************************************************
524 */
ihevce_pre_enc_manage_ref_pics(enc_ctxt_t * ps_enc_ctxt,ihevce_lap_enc_buf_t * ps_curr_inp,pre_enc_me_ctxt_t * ps_curr_out,WORD32 i4_ping_pong)525 void ihevce_pre_enc_manage_ref_pics(
526     enc_ctxt_t *ps_enc_ctxt,
527     ihevce_lap_enc_buf_t *ps_curr_inp,
528     pre_enc_me_ctxt_t *ps_curr_out,
529     WORD32 i4_ping_pong)
530 {
531     /* local variables */
532     WORD32 ctr;
533     WORD32 ref_pics;
534     WORD32 ai4_buf_status[HEVCE_MAX_DPB_PICS] = { 0 };
535     WORD32 curr_poc;
536     WORD32 wp_flag = 0;
537     WORD32 num_ref_pics_list0 = 0;
538     WORD32 num_ref_pics_list1 = 0;
539     WORD32 cra_poc = ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc;
540     WORD32 slice_type = ps_curr_out->s_slice_hdr.i1_slice_type;
541     recon_pic_buf_t *(*aps_pre_enc_ref_pic_list)[HEVCE_MAX_REF_PICS * 2];
542     WORD32 i4_inc_L1_active_ref_pic = 0;
543     WORD32 i4_inc_L0_active_ref_pic = 0;
544 
545     (void)ps_curr_out;
546     curr_poc = ps_curr_inp->s_lap_out.i4_poc;
547 
548     /* Number of reference pics given by LAP should not be greater than max */
549     ASSERT(HEVCE_MAX_REF_PICS >= ps_curr_inp->s_lap_out.i4_num_ref_pics);
550 
551     /*derive ref_pic_list based on ping_pong instance */
552     aps_pre_enc_ref_pic_list = ps_enc_ctxt->aps_pre_enc_ref_lists[i4_ping_pong];
553 
554     /* derive the weighted prediction enable flag based on slice type */
555     if(BSLICE == slice_type)
556     {
557         wp_flag = ps_curr_inp->s_lap_out.i1_weighted_bipred_flag;
558     }
559     else if(PSLICE == slice_type)
560     {
561         wp_flag = ps_curr_inp->s_lap_out.i1_weighted_pred_flag;
562     }
563     else
564     {
565         wp_flag = 0;
566     }
567 
568     /*to support diplicate pics*/
569     {
570         WORD32 i, j;
571         for(i = 0; i < 2; i++)
572         {
573             for(j = 0; j < HEVCE_MAX_REF_PICS * 2; j++)
574             {
575                 aps_pre_enc_ref_pic_list[i][j] =
576                     &ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][i][j];
577             }
578         }
579     }
580 
581     /* run a loop over the number of reference pics given by LAP */
582     for(ref_pics = 0; ref_pics < ps_curr_inp->s_lap_out.i4_num_ref_pics; ref_pics++)
583     {
584         WORD32 ref_poc;
585         WORD32 i4_loop = 1;
586         WORD32 i4_temp_list;
587 
588         ref_poc = curr_poc + ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_ref_pic_delta_poc;
589 
590         /* run a loop to check the poc based on delta poc array */
591         for(ctr = 0; ctr < ps_enc_ctxt->i4_pre_enc_num_buf_recon_q; ctr++)
592         {
593             /* if the POC is matching with current ref picture*/
594             if((ref_poc == ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr]->i4_poc) &&
595                (0 == ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr]->i4_is_free))
596             {
597                 /* mark the buf status as used */
598                 ai4_buf_status[ctr] = 1;
599 
600                 /* populate the reference lists based on delta poc array */
601                 if((ref_poc < curr_poc) || (0 == curr_poc))
602                 {
603                     /* list 0 */
604                     memcpy(
605                         &ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_0][num_ref_pics_list0],
606                         ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr],
607                         sizeof(recon_pic_buf_t));
608                     i4_temp_list = num_ref_pics_list0;
609 
610                     /*duplicate pics added to the list*/
611                     while(i4_loop != ps_curr_inp->s_lap_out.as_ref_pics[ref_pics]
612                                          .i4_num_duplicate_entries_in_ref_list)
613                     {
614                         /* list 0 */
615                         i4_temp_list++;
616                         memcpy(
617                             &ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_0][i4_temp_list],
618                             ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr],
619                             sizeof(recon_pic_buf_t));
620                         i4_loop++;
621                     }
622 
623                     /* populate weights and offsets corresponding to this ref pic */
624                     memcpy(
625                         &ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_0][num_ref_pics_list0]
626                              .s_weight_offset,
627                         &ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].as_wght_off[0],
628                         sizeof(ihevce_wght_offst_t));
629 
630                     /* Store the used as ref for current pic flag  */
631                     ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_0][num_ref_pics_list0]
632                         .i4_used_by_cur_pic_flag =
633                         ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_used_by_cur_pic_flag;
634 
635                     num_ref_pics_list0++;
636                     i4_loop = 1;
637                     /*duplicate pics added to the list*/
638                     while(i4_loop != ps_curr_inp->s_lap_out.as_ref_pics[ref_pics]
639                                          .i4_num_duplicate_entries_in_ref_list)
640                     {
641                         /* populate weights and offsets corresponding to this ref pic */
642                         memcpy(
643                             &ps_enc_ctxt
644                                  ->as_pre_enc_ref_lists[i4_ping_pong][LIST_0][num_ref_pics_list0]
645                                  .s_weight_offset,
646                             &ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].as_wght_off[i4_loop],
647                             sizeof(ihevce_wght_offst_t));
648 
649                         /* Store the used as ref for current pic flag  */
650                         ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_0][num_ref_pics_list0]
651                             .i4_used_by_cur_pic_flag =
652                             ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_used_by_cur_pic_flag;
653 
654                         num_ref_pics_list0++;
655                         i4_loop++;
656                     }
657                 }
658                 else
659                 {
660                     /* list 1 */
661                     memcpy(
662                         &ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_1][num_ref_pics_list1],
663                         ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr],
664                         sizeof(recon_pic_buf_t));
665 
666                     i4_temp_list = num_ref_pics_list1;
667                     /*duplicate pics added to the list*/
668                     while(i4_loop != ps_curr_inp->s_lap_out.as_ref_pics[ref_pics]
669                                          .i4_num_duplicate_entries_in_ref_list)
670                     {
671                         /* list 1 */
672                         i4_temp_list++;
673                         memcpy(
674                             &ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_1][i4_temp_list],
675                             ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr],
676                             sizeof(recon_pic_buf_t));
677                         i4_loop++;
678                     }
679 
680                     /* populate weights and offsets corresponding to this ref pic */
681                     memcpy(
682                         &ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_1][num_ref_pics_list1]
683                              .s_weight_offset,
684                         &ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].as_wght_off[0],
685                         sizeof(ihevce_wght_offst_t));
686 
687                     /* Store the used as ref for current pic flag  */
688                     ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_1][num_ref_pics_list1]
689                         .i4_used_by_cur_pic_flag =
690                         ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_used_by_cur_pic_flag;
691 
692                     num_ref_pics_list1++;
693                     i4_loop = 1;
694                     /*duplicate pics added to the list*/
695                     while(i4_loop != ps_curr_inp->s_lap_out.as_ref_pics[ref_pics]
696                                          .i4_num_duplicate_entries_in_ref_list)
697                     {
698                         /* populate weights and offsets corresponding to this ref pic */
699                         memcpy(
700                             &ps_enc_ctxt
701                                  ->as_pre_enc_ref_lists[i4_ping_pong][LIST_1][num_ref_pics_list1]
702                                  .s_weight_offset,
703                             &ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].as_wght_off[i4_loop],
704                             sizeof(ihevce_wght_offst_t));
705 
706                         /* Store the used as ref for current pic flag  */
707                         ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_1][num_ref_pics_list1]
708                             .i4_used_by_cur_pic_flag =
709                             ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_used_by_cur_pic_flag;
710 
711                         num_ref_pics_list1++;
712                         i4_loop++;
713                     }
714                 }
715                 break;
716             }
717         }
718 
719         /* if the reference picture is not found then error */
720         ASSERT(ctr != ps_enc_ctxt->i4_pre_enc_num_buf_recon_q);
721     }
722     /* sort the reference pics in List0 in descending order POC */
723     if(num_ref_pics_list0 > 1)
724     {
725         /* run a loop for num ref pics -1 */
726         for(ctr = 0; ctr < num_ref_pics_list0 - 1; ctr++)
727         {
728             WORD32 max_idx = ctr;
729             recon_pic_buf_t *ps_temp;
730             WORD32 i;
731 
732             for(i = (ctr + 1); i < num_ref_pics_list0; i++)
733             {
734                 /* check for poc greater than current ref poc */
735                 if(aps_pre_enc_ref_pic_list[LIST_0][i]->i4_poc >
736                    aps_pre_enc_ref_pic_list[LIST_0][max_idx]->i4_poc)
737                 {
738                     max_idx = i;
739                 }
740             }
741 
742             /* if max of remaining is not current, swap the pointers */
743             if(max_idx != ctr)
744             {
745                 ps_temp = aps_pre_enc_ref_pic_list[LIST_0][max_idx];
746                 aps_pre_enc_ref_pic_list[LIST_0][max_idx] = aps_pre_enc_ref_pic_list[LIST_0][ctr];
747                 aps_pre_enc_ref_pic_list[LIST_0][ctr] = ps_temp;
748             }
749         }
750     }
751 
752     /* sort the reference pics in List1 in ascending order POC */
753     if(num_ref_pics_list1 > 1)
754     {
755         /* run a loop for num ref pics -1 */
756         for(ctr = 0; ctr < num_ref_pics_list1 - 1; ctr++)
757         {
758             WORD32 min_idx = ctr;
759             recon_pic_buf_t *ps_temp;
760             WORD32 i;
761 
762             for(i = (ctr + 1); i < num_ref_pics_list1; i++)
763             {
764                 /* check for p[oc less than current ref poc */
765                 if(aps_pre_enc_ref_pic_list[LIST_1][i]->i4_poc <
766                    aps_pre_enc_ref_pic_list[LIST_1][min_idx]->i4_poc)
767                 {
768                     min_idx = i;
769                 }
770             }
771 
772             /* if min of remaining is not current, swap the pointers */
773             if(min_idx != ctr)
774             {
775                 ps_temp = aps_pre_enc_ref_pic_list[LIST_1][min_idx];
776                 aps_pre_enc_ref_pic_list[LIST_1][min_idx] = aps_pre_enc_ref_pic_list[LIST_1][ctr];
777                 aps_pre_enc_ref_pic_list[LIST_1][ctr] = ps_temp;
778             }
779         }
780     }
781 
782     /* call the ME API to update the DPB of HME pyramids coarse layers */
783     ihevce_coarse_me_frame_dpb_update(
784         ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
785         num_ref_pics_list0,
786         num_ref_pics_list1,
787         &aps_pre_enc_ref_pic_list[LIST_0][0],
788         &aps_pre_enc_ref_pic_list[LIST_1][0]);
789 
790     /* Default list creation based on uses as ref pic for current pic flag */
791     {
792         WORD32 num_ref_pics_list_final = 0;
793         WORD32 list_idx = 0;
794 
795         /* LIST 0 */
796         /* run a loop for num ref pics in list 0 */
797         for(ctr = 0; ctr < num_ref_pics_list0; ctr++)
798         {
799             /* check for used as reference flag */
800             if(1 == aps_pre_enc_ref_pic_list[LIST_0][ctr]->i4_used_by_cur_pic_flag)
801             {
802                 /* copy the pointer to the actual valid list idx */
803                 aps_pre_enc_ref_pic_list[LIST_0][list_idx] = aps_pre_enc_ref_pic_list[LIST_0][ctr];
804 
805                 /* increment the valid pic counters and idx */
806                 list_idx++;
807                 num_ref_pics_list_final++;
808             }
809         }
810 
811         /* finally store the number of pictures in List0 */
812         num_ref_pics_list0 = num_ref_pics_list_final;
813         /* LIST 1 */
814         num_ref_pics_list_final = 0;
815         list_idx = 0;
816 
817         /* run a loop for num ref pics in list 1 */
818         for(ctr = 0; ctr < num_ref_pics_list1; ctr++)
819         {
820             /* check for used as reference flag */
821             if(1 == aps_pre_enc_ref_pic_list[LIST_1][ctr]->i4_used_by_cur_pic_flag)
822             {
823                 /* copy the pointer to the actual valid list idx */
824                 aps_pre_enc_ref_pic_list[LIST_1][list_idx] = aps_pre_enc_ref_pic_list[LIST_1][ctr];
825 
826                 /* increment the valid pic counters and idx */
827                 list_idx++;
828                 num_ref_pics_list_final++;
829             }
830         }
831 
832         /* finally store the number of pictures in List1 */
833         num_ref_pics_list1 = num_ref_pics_list_final;
834     }
835     /*in case of single active ref picture on L0 and L1, then consider one of them weighted
836     and another non-weighted*/
837     if(ps_curr_inp->s_lap_out.i4_pic_type == IV_P_FRAME)
838     {
839         if(num_ref_pics_list0 > 2)
840         {
841             if(aps_pre_enc_ref_pic_list[LIST_0][0]->i4_poc ==
842                aps_pre_enc_ref_pic_list[LIST_0][1]->i4_poc)
843             {
844                 i4_inc_L0_active_ref_pic = 1;
845             }
846         }
847     }
848     else
849     {
850         if(num_ref_pics_list0 >= 2 && num_ref_pics_list1 >= 2)
851         {
852             if(aps_pre_enc_ref_pic_list[LIST_0][0]->i4_poc ==
853                aps_pre_enc_ref_pic_list[LIST_0][1]->i4_poc)
854             {
855                 i4_inc_L0_active_ref_pic = 1;
856             }
857             if(aps_pre_enc_ref_pic_list[LIST_1][0]->i4_poc ==
858                aps_pre_enc_ref_pic_list[LIST_1][1]->i4_poc)
859             {
860                 i4_inc_L1_active_ref_pic = 1;
861             }
862         }
863     }
864 
865     /* append the reference pics in List1 and end of list0 */
866     for(ctr = 0; ctr < num_ref_pics_list1; ctr++)
867     {
868         aps_pre_enc_ref_pic_list[LIST_0][num_ref_pics_list0 + ctr] =
869             aps_pre_enc_ref_pic_list[LIST_1][ctr];
870     }
871 
872     /* append the reference pics in List0 and end of list1 */
873     for(ctr = 0; ctr < num_ref_pics_list0; ctr++)
874     {
875         aps_pre_enc_ref_pic_list[LIST_1][num_ref_pics_list1 + ctr] =
876             aps_pre_enc_ref_pic_list[LIST_0][ctr];
877     }
878 
879     /* reference list modification for adding duplicate reference */
880     {
881 
882     }
883 
884     /* popluate the default weights and offsets for disabled cases */
885     {
886         WORD32 i;
887 
888         /* populate the weights and offsets for all pics in L0 + L1 */
889         for(i = 0; i < (num_ref_pics_list0 + num_ref_pics_list1); i++)
890         {
891             /* populate the weights and offsets if weighted prediction is disabled */
892             if(1 == wp_flag)
893             {
894                 /* if weights are disabled then populate default values */
895                 if(0 ==
896                    aps_pre_enc_ref_pic_list[LIST_0][i]->s_weight_offset.u1_luma_weight_enable_flag)
897                 {
898                     /* set to default values */
899                     aps_pre_enc_ref_pic_list[LIST_0][i]->s_weight_offset.i2_luma_weight =
900                         (1 << ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom);
901 
902                     aps_pre_enc_ref_pic_list[LIST_0][i]->s_weight_offset.i2_luma_offset = 0;
903                 }
904             }
905         }
906 
907         for(i = 0; i < (num_ref_pics_list0 + num_ref_pics_list1); i++)
908         {
909             /* populate the weights and offsets if weighted prediction is enabled */
910             if(1 == wp_flag)
911             {
912                 /* if weights are disabled then populate default values */
913                 if(0 ==
914                    aps_pre_enc_ref_pic_list[LIST_1][i]->s_weight_offset.u1_luma_weight_enable_flag)
915                 {
916                     /* set to default values */
917                     aps_pre_enc_ref_pic_list[LIST_1][i]->s_weight_offset.i2_luma_weight =
918                         (1 << ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom);
919 
920                     aps_pre_enc_ref_pic_list[LIST_1][i]->s_weight_offset.i2_luma_offset = 0;
921                 }
922             }
923         }
924     }
925 
926     /* run a loop to free the non used reference pics */
927     for(ctr = 0; ctr < ps_enc_ctxt->i4_pre_enc_num_buf_recon_q; ctr++)
928     {
929         /* if not used as reference */
930         if(0 == ai4_buf_status[ctr])
931         {
932             ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr]->i4_is_free = 1;
933             ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr]->i4_poc = -1;
934         }
935     }
936 
937     /* store the number of reference pics in the list for ME/MC etc */
938     ps_enc_ctxt->i4_pre_enc_num_ref_l0 = num_ref_pics_list0;
939     ps_enc_ctxt->i4_pre_enc_num_ref_l1 = num_ref_pics_list1;
940 
941 #define HME_USE_ONLY_2REF
942 #ifndef HME_USE_ONLY_2REF
943     ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = num_ref_pics_list0;
944     ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = num_ref_pics_list1;
945 #else
946 #if MULTI_REF_ENABLE == 1
947     if(ps_curr_inp->s_lap_out.i4_quality_preset >= IHEVCE_QUALITY_P3)
948     {
949         if(ps_curr_inp->s_lap_out.i4_pic_type == IV_P_FRAME)
950         {
951             if(IHEVCE_QUALITY_P6 == ps_curr_inp->s_lap_out.i4_quality_preset)
952             {
953                 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
954                 {
955                     ps_enc_ctxt->i4_pre_enc_num_ref_l0_active =
956                         MIN(MAX_NUM_REFS_IN_PPICS_IN_XS25 + 1, num_ref_pics_list0);
957                 }
958                 else
959                 {
960                     ps_enc_ctxt->i4_pre_enc_num_ref_l0_active =
961                         MIN(MAX_NUM_REFS_IN_PPICS_IN_XS25, num_ref_pics_list0);
962                     ps_enc_ctxt->i4_pre_enc_num_ref_l0_active += i4_inc_L0_active_ref_pic;
963                 }
964 
965                 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = 0;
966             }
967             else
968             {
969                 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
970                 {
971                     ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(3, num_ref_pics_list0);
972                 }
973                 else
974                 {
975                     ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(2, num_ref_pics_list0);
976                     ps_enc_ctxt->i4_pre_enc_num_ref_l0_active += i4_inc_L0_active_ref_pic;
977                 }
978 
979                 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = 0;
980             }
981         }
982         else
983         {
984             if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
985             {
986                 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(2, num_ref_pics_list0);
987                 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = MIN(1, num_ref_pics_list1);
988                 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active += i4_inc_L1_active_ref_pic;
989             }
990             else
991             {
992                 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(1, num_ref_pics_list0);
993                 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = MIN(1, num_ref_pics_list1);
994                 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active += i4_inc_L1_active_ref_pic;
995                 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active += i4_inc_L0_active_ref_pic;
996             }
997         }
998     }
999     else
1000     {
1001         if(ps_curr_inp->s_lap_out.i4_pic_type == IV_P_FRAME)
1002         {
1003             if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1004                 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(4, num_ref_pics_list0);
1005             else
1006                 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(4, num_ref_pics_list0);
1007 
1008             ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = 0;
1009         }
1010         else
1011         {
1012             if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1013             {
1014                 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(4, num_ref_pics_list0);
1015                 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = MIN(4, num_ref_pics_list1);
1016             }
1017             else
1018             {
1019                 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(4, num_ref_pics_list0);
1020                 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = MIN(4, num_ref_pics_list1);
1021             }
1022         }
1023     }
1024 #else
1025     {
1026         if(ps_curr_inp->s_lap_out.i4_pic_type == IV_P_FRAME)
1027         {
1028             if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1029                 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(3, num_ref_pics_list0);
1030             else
1031                 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(2, num_ref_pics_list0);
1032 
1033             ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = 0;
1034         }
1035         else
1036         {
1037             if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1038             {
1039                 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(2, num_ref_pics_list0);
1040                 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = MIN(1, num_ref_pics_list1);
1041             }
1042             else
1043             {
1044                 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(1, num_ref_pics_list0);
1045                 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = MIN(1, num_ref_pics_list1);
1046             }
1047         }
1048     }
1049 #endif
1050 #endif
1051 
1052     return;
1053 }
1054 
1055 /*!
1056 ******************************************************************************
1057 * \if Function name : ihevce_manage_ref_pics \endif
1058 *
1059 * \brief
1060 *    Reference picture management based on delta poc array given by LAP
1061 *    Populates the reference list after removing non used reference pictures
1062 *    populates the delta poc of reference pics to be signalled in slice header
1063 *
1064 * \param[in] encoder context pointer
1065 * \param[in] current LAP Encoder buffer pointer
1066 * \param[in] current frame process and entropy buffer pointer
1067 *
1068 * \return
1069 *    None
1070 *
1071 * \author
1072 *  Ittiam
1073 *
1074 *****************************************************************************
1075 */
ihevce_manage_ref_pics(enc_ctxt_t * ps_enc_ctxt,ihevce_lap_enc_buf_t * ps_curr_inp,slice_header_t * ps_slice_header,WORD32 i4_me_frm_id,WORD32 i4_thrd_id,WORD32 i4_bitrate_instance_id)1076 void ihevce_manage_ref_pics(
1077     enc_ctxt_t *ps_enc_ctxt,
1078     ihevce_lap_enc_buf_t *ps_curr_inp,
1079     slice_header_t *ps_slice_header,
1080     WORD32 i4_me_frm_id,
1081     WORD32 i4_thrd_id,
1082     WORD32 i4_bitrate_instance_id)
1083 {
1084     WORD32 ctr;
1085     WORD32 ref_pics;
1086     WORD32 curr_poc, curr_idr_gop_num;
1087     WORD32 wp_flag;
1088     WORD32 num_ref_pics_list0 = 0;
1089     WORD32 num_ref_pics_list1 = 0;
1090     WORD32 cra_poc = ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc;
1091     WORD32 slice_type = ps_slice_header->i1_slice_type;
1092     recon_pic_buf_t *(*aps_ref_list)[HEVCE_MAX_REF_PICS * 2];
1093     recon_pic_buf_t(*aps_ref_list_temp)[HEVCE_MAX_REF_PICS * 2];
1094     WORD32 i4_num_rpics_l0_excl_dup;
1095     WORD32 i4_num_rpics_l1_excl_dup;
1096     WORD32 i4_inc_L1_active_ref_pic = 0;
1097     WORD32 i4_inc_L0_active_ref_pic = 0;
1098     WORD32 i4_bridx = i4_bitrate_instance_id;  //bitrate instance index
1099     WORD32 i4_resolution_id = ps_enc_ctxt->i4_resolution_id;
1100     me_enc_rdopt_ctxt_t *ps_cur_out_me_prms;
1101     recon_pic_buf_t ***ppps_recon_bufs = ps_enc_ctxt->pps_recon_buf_q;
1102     WORD32 i4_num_recon_bufs = ps_enc_ctxt->ai4_num_buf_recon_q[i4_bridx];
1103 
1104     ps_cur_out_me_prms = ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id];
1105 
1106     /*to support diplicate pics*/
1107     {
1108         WORD32 i, j;
1109         for(i = 0; i < NUM_REF_LISTS; i++)
1110         {
1111             for(j = 0; j < HEVCE_MAX_REF_PICS * 2; j++)
1112             {
1113                 ps_cur_out_me_prms->aps_ref_list[i4_bridx][i][j] =
1114                     &ps_cur_out_me_prms->as_ref_list[i4_bridx][i][j];
1115             }
1116         }
1117     }
1118 
1119     aps_ref_list = ps_cur_out_me_prms->aps_ref_list[i4_bridx];
1120     aps_ref_list_temp = ps_cur_out_me_prms->as_ref_list[i4_bridx];
1121 
1122     curr_poc = ps_curr_inp->s_lap_out.i4_poc;
1123     curr_idr_gop_num = ps_curr_inp->s_lap_out.i4_idr_gop_num;
1124 
1125     /* Number of reference pics given by LAP should not be greater than max */
1126     ASSERT(HEVCE_MAX_REF_PICS >= ps_curr_inp->s_lap_out.i4_num_ref_pics);
1127 
1128     /* derive the weighted prediction enable flag based on slice type */
1129     if(BSLICE == slice_type)
1130     {
1131         wp_flag = ps_curr_inp->s_lap_out.i1_weighted_bipred_flag;
1132     }
1133     else if(PSLICE == slice_type)
1134     {
1135         wp_flag = ps_curr_inp->s_lap_out.i1_weighted_pred_flag;
1136     }
1137     else
1138     {
1139         wp_flag = 0;
1140     }
1141 
1142     ps_slice_header->s_rplm.i1_ref_pic_list_modification_flag_l0 = 0;
1143     ps_slice_header->s_rplm.i1_ref_pic_list_modification_flag_l1 = 0;
1144     ASSERT(curr_poc != INVALID_POC);
1145 
1146     /* run a loop over the number of reference pics given by LAP */
1147     for(ref_pics = 0; ref_pics < ps_curr_inp->s_lap_out.i4_num_ref_pics; ref_pics++)
1148     {
1149         WORD32 ref_poc;
1150         WORD32 i4_loop = 1;
1151         WORD32 i4_temp_list;
1152 
1153         ref_poc = curr_poc + ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_ref_pic_delta_poc;
1154         if((0 == curr_poc) && curr_idr_gop_num)
1155         {
1156             curr_idr_gop_num -= 1;
1157         }
1158         ASSERT(ref_poc != INVALID_POC);
1159         /* run a loop to check the poc based on delta poc array */
1160         for(ctr = 0; ctr < i4_num_recon_bufs; ctr++)
1161         {
1162             /* if the POC is matching with current ref picture*/
1163             if((ref_poc == ppps_recon_bufs[i4_bridx][ctr]->i4_poc) &&
1164                (0 == ppps_recon_bufs[i4_bridx][ctr]->i4_is_free) &&
1165                (curr_idr_gop_num == ppps_recon_bufs[i4_bridx][ctr]->i4_idr_gop_num))
1166             {
1167                 /* populate the reference lists based on delta poc array */
1168                 if((ref_poc < curr_poc) || (0 == curr_poc))
1169                 {
1170                     /* list 0 */
1171                     memcpy(
1172                         &aps_ref_list_temp[LIST_0][num_ref_pics_list0],
1173                         ppps_recon_bufs[i4_bridx][ctr],
1174                         sizeof(recon_pic_buf_t));
1175 
1176                     i4_temp_list = num_ref_pics_list0;
1177 
1178                     /*duplicate pics added to the list*/
1179                     while(i4_loop != ps_curr_inp->s_lap_out.as_ref_pics[ref_pics]
1180                                          .i4_num_duplicate_entries_in_ref_list)
1181                     {
1182                         i4_temp_list++;
1183                         /* list 0 */
1184                         memcpy(
1185                             &aps_ref_list_temp[LIST_0][i4_temp_list],
1186                             ppps_recon_bufs[i4_bridx][ctr],
1187                             sizeof(recon_pic_buf_t));
1188                         i4_loop++;
1189                     }
1190 
1191                     /* populate weights and offsets corresponding to this ref pic */
1192                     memcpy(
1193                         &aps_ref_list_temp[LIST_0][num_ref_pics_list0].s_weight_offset,
1194                         &ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].as_wght_off[0],
1195                         sizeof(ihevce_wght_offst_t));
1196 
1197                     /* Store the used as ref for current pic flag  */
1198                     aps_ref_list_temp[LIST_0][num_ref_pics_list0].i4_used_by_cur_pic_flag =
1199                         ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_used_by_cur_pic_flag;
1200 
1201                     if(wp_flag)
1202                     {
1203                         WORD16 i2_luma_weight = (aps_ref_list[LIST_0][num_ref_pics_list0]
1204                                                      ->s_weight_offset.i2_luma_weight);
1205 
1206                         aps_ref_list[LIST_0][num_ref_pics_list0]->i4_inv_luma_wt =
1207                             ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1208 
1209                         aps_ref_list[LIST_0][num_ref_pics_list0]->i4_log2_wt_denom =
1210                             ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1211                     }
1212                     else
1213                     {
1214                         WORD16 i2_luma_weight =
1215                             (1 << ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom);
1216 
1217                         aps_ref_list[LIST_0][num_ref_pics_list0]->s_weight_offset.i2_luma_weight =
1218                             i2_luma_weight;
1219 
1220                         aps_ref_list[LIST_0][num_ref_pics_list0]->i4_inv_luma_wt =
1221                             ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1222 
1223                         aps_ref_list[LIST_0][num_ref_pics_list0]->i4_log2_wt_denom =
1224                             ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1225                     }
1226 
1227                     num_ref_pics_list0++;
1228                     i4_loop = 1;
1229 
1230                     /*duplicate pics added to the list*/
1231                     while(i4_loop != ps_curr_inp->s_lap_out.as_ref_pics[ref_pics]
1232                                          .i4_num_duplicate_entries_in_ref_list)
1233                     {
1234                         /* populate weights and offsets corresponding to this ref pic */
1235                         memcpy(
1236                             &aps_ref_list_temp[LIST_0][num_ref_pics_list0].s_weight_offset,
1237                             &ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].as_wght_off[i4_loop],
1238                             sizeof(ihevce_wght_offst_t));
1239 
1240                         /* Store the used as ref for current pic flag  */
1241                         aps_ref_list_temp[LIST_0][num_ref_pics_list0].i4_used_by_cur_pic_flag =
1242                             ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_used_by_cur_pic_flag;
1243 
1244                         if(wp_flag)
1245                         {
1246                             WORD16 i2_luma_weight = (aps_ref_list[LIST_0][num_ref_pics_list0]
1247                                                          ->s_weight_offset.i2_luma_weight);
1248 
1249                             aps_ref_list[LIST_0][num_ref_pics_list0]->i4_inv_luma_wt =
1250                                 ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1251 
1252                             aps_ref_list[LIST_0][num_ref_pics_list0]->i4_log2_wt_denom =
1253                                 ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1254                         }
1255                         else
1256                         {
1257                             WORD16 i2_luma_weight =
1258                                 (1 << ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom);
1259 
1260                             aps_ref_list[LIST_0][num_ref_pics_list0]
1261                                 ->s_weight_offset.i2_luma_weight = i2_luma_weight;
1262 
1263                             aps_ref_list[LIST_0][num_ref_pics_list0]->i4_inv_luma_wt =
1264                                 ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1265 
1266                             aps_ref_list[LIST_0][num_ref_pics_list0]->i4_log2_wt_denom =
1267                                 ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1268                         }
1269 
1270                         num_ref_pics_list0++;
1271                         i4_loop++;
1272                         ps_slice_header->s_rplm.i1_ref_pic_list_modification_flag_l0 = 1;
1273                         ps_slice_header->s_rplm.i1_ref_pic_list_modification_flag_l1 = 1;
1274                     }
1275                 }
1276                 else
1277                 {
1278                     /* list 1 */
1279                     memcpy(
1280                         &aps_ref_list_temp[LIST_1][num_ref_pics_list1],
1281                         ppps_recon_bufs[i4_bridx][ctr],
1282                         sizeof(recon_pic_buf_t));
1283                     i4_temp_list = num_ref_pics_list1;
1284                     /*duplicate pics added to the list*/
1285                     while(i4_loop != ps_curr_inp->s_lap_out.as_ref_pics[ref_pics]
1286                                          .i4_num_duplicate_entries_in_ref_list)
1287                     {
1288                         i4_temp_list++;
1289                         /* list 1 */
1290                         memcpy(
1291                             &aps_ref_list_temp[LIST_1][i4_temp_list],
1292                             ppps_recon_bufs[i4_bridx][ctr],
1293                             sizeof(recon_pic_buf_t));
1294                         i4_loop++;
1295                     }
1296 
1297                     /* populate weights and offsets corresponding to this ref pic */
1298                     memcpy(
1299                         &aps_ref_list_temp[LIST_1][num_ref_pics_list1].s_weight_offset,
1300                         &ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].as_wght_off[0],
1301                         sizeof(ihevce_wght_offst_t));
1302 
1303                     /* Store the used as ref for current pic flag  */
1304                     aps_ref_list_temp[LIST_1][num_ref_pics_list1].i4_used_by_cur_pic_flag =
1305                         ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_used_by_cur_pic_flag;
1306 
1307                     if(wp_flag)
1308                     {
1309                         WORD16 i2_luma_weight = (aps_ref_list[LIST_1][num_ref_pics_list1]
1310                                                      ->s_weight_offset.i2_luma_weight);
1311 
1312                         aps_ref_list[LIST_1][num_ref_pics_list1]->i4_inv_luma_wt =
1313                             ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1314 
1315                         aps_ref_list[LIST_1][num_ref_pics_list1]->i4_log2_wt_denom =
1316                             ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1317                     }
1318                     else
1319                     {
1320                         WORD16 i2_luma_weight =
1321                             (1 << ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom);
1322 
1323                         aps_ref_list[LIST_1][num_ref_pics_list1]->s_weight_offset.i2_luma_weight =
1324                             i2_luma_weight;
1325 
1326                         aps_ref_list[LIST_1][num_ref_pics_list1]->i4_inv_luma_wt =
1327                             ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1328 
1329                         aps_ref_list[LIST_1][num_ref_pics_list1]->i4_log2_wt_denom =
1330                             ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1331                     }
1332 
1333                     num_ref_pics_list1++;
1334                     i4_loop = 1;
1335                     /*duplicate pics added to the list*/
1336                     while(i4_loop != ps_curr_inp->s_lap_out.as_ref_pics[ref_pics]
1337                                          .i4_num_duplicate_entries_in_ref_list)
1338                     {
1339                         /* populate weights and offsets corresponding to this ref pic */
1340                         memcpy(
1341                             &aps_ref_list_temp[LIST_1][num_ref_pics_list1].s_weight_offset,
1342                             &ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].as_wght_off[i4_loop],
1343                             sizeof(ihevce_wght_offst_t));
1344 
1345                         /* Store the used as ref for current pic flag  */
1346                         aps_ref_list_temp[LIST_1][num_ref_pics_list1].i4_used_by_cur_pic_flag =
1347                             ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_used_by_cur_pic_flag;
1348 
1349                         if(wp_flag)
1350                         {
1351                             WORD16 i2_luma_weight = (aps_ref_list[LIST_1][num_ref_pics_list1]
1352                                                          ->s_weight_offset.i2_luma_weight);
1353 
1354                             aps_ref_list[LIST_1][num_ref_pics_list1]->i4_inv_luma_wt =
1355                                 ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1356 
1357                             aps_ref_list[LIST_1][num_ref_pics_list1]->i4_log2_wt_denom =
1358                                 ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1359                         }
1360                         else
1361                         {
1362                             WORD16 i2_luma_weight =
1363                                 (1 << ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom);
1364 
1365                             aps_ref_list[LIST_1][num_ref_pics_list1]
1366                                 ->s_weight_offset.i2_luma_weight = i2_luma_weight;
1367 
1368                             aps_ref_list[LIST_1][num_ref_pics_list1]->i4_inv_luma_wt =
1369                                 ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1370 
1371                             aps_ref_list[LIST_1][num_ref_pics_list1]->i4_log2_wt_denom =
1372                                 ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1373                         }
1374 
1375                         num_ref_pics_list1++;
1376                         i4_loop++;
1377                         ps_slice_header->s_rplm.i1_ref_pic_list_modification_flag_l1 = 1;
1378                         ps_slice_header->s_rplm.i1_ref_pic_list_modification_flag_l0 = 1;
1379                     }
1380                 }
1381                 break;
1382             }
1383         }
1384 
1385         /* if the reference picture is not found then error */
1386         ASSERT(ctr != i4_num_recon_bufs);
1387     }
1388 
1389     i4_num_rpics_l0_excl_dup = num_ref_pics_list0;
1390     i4_num_rpics_l1_excl_dup = num_ref_pics_list1;
1391 
1392     /* sort the reference pics in List0 in descending order POC */
1393     if(num_ref_pics_list0 > 1)
1394     {
1395         /* run a loop for num ref pics -1 */
1396         for(ctr = 0; ctr < num_ref_pics_list0 - 1; ctr++)
1397         {
1398             WORD32 max_idx = ctr;
1399             recon_pic_buf_t *ps_temp;
1400             WORD32 i;
1401 
1402             for(i = (ctr + 1); i < num_ref_pics_list0; i++)
1403             {
1404                 /* check for poc greater than current ref poc */
1405                 if(aps_ref_list[LIST_0][i]->i4_poc > aps_ref_list[LIST_0][max_idx]->i4_poc)
1406                 {
1407                     max_idx = i;
1408                 }
1409             }
1410 
1411             /* if max of remaining is not current, swap the pointers */
1412             if(max_idx != ctr)
1413             {
1414                 ps_temp = aps_ref_list[LIST_0][max_idx];
1415                 aps_ref_list[LIST_0][max_idx] = aps_ref_list[LIST_0][ctr];
1416                 aps_ref_list[LIST_0][ctr] = ps_temp;
1417             }
1418         }
1419     }
1420 
1421     /* sort the reference pics in List1 in ascending order POC */
1422     if(num_ref_pics_list1 > 1)
1423     {
1424         /* run a loop for num ref pics -1 */
1425         for(ctr = 0; ctr < num_ref_pics_list1 - 1; ctr++)
1426         {
1427             WORD32 min_idx = ctr;
1428             recon_pic_buf_t *ps_temp;
1429             WORD32 i;
1430 
1431             for(i = (ctr + 1); i < num_ref_pics_list1; i++)
1432             {
1433                 /* check for p[oc less than current ref poc */
1434                 if(aps_ref_list[LIST_1][i]->i4_poc < aps_ref_list[LIST_1][min_idx]->i4_poc)
1435                 {
1436                     min_idx = i;
1437                 }
1438             }
1439 
1440             /* if min of remaining is not current, swap the pointers */
1441             if(min_idx != ctr)
1442             {
1443                 ps_temp = aps_ref_list[LIST_1][min_idx];
1444                 aps_ref_list[LIST_1][min_idx] = aps_ref_list[LIST_1][ctr];
1445                 aps_ref_list[LIST_1][ctr] = ps_temp;
1446             }
1447         }
1448     }
1449 
1450     /* popluate the slice header parameters to signal delta POCs and use flags */
1451     {
1452         WORD32 i;
1453         WORD32 prev_poc = curr_poc;
1454 
1455         ps_slice_header->s_stref_picset.i1_inter_ref_pic_set_prediction_flag = 0;
1456 
1457         ps_slice_header->s_stref_picset.i1_num_neg_pics = num_ref_pics_list0;
1458 
1459         ps_slice_header->s_stref_picset.i1_num_pos_pics = num_ref_pics_list1;
1460 
1461         ps_slice_header->s_stref_picset.i1_num_ref_idc = -1;
1462 
1463         /* populate the delta POCs of reference pics */
1464         i = 0;
1465 
1466         for(ctr = 0; ctr < i4_num_rpics_l0_excl_dup; ctr++)
1467         {
1468             WORD32 ref_poc_l0 = aps_ref_list[LIST_0][i]->i4_poc;
1469 
1470             ps_slice_header->s_stref_picset.ai2_delta_poc[ctr] = prev_poc - ref_poc_l0;
1471             ps_slice_header->s_stref_picset.ai1_used[ctr] =
1472                 aps_ref_list[LIST_0][i]->i4_used_by_cur_pic_flag;
1473 
1474             /* check if this picture has to be used as reference */
1475             if(1 == ps_slice_header->s_stref_picset.ai1_used[ctr])
1476             {
1477                 /* check for CRA poc related use flag signalling */
1478                 ps_slice_header->s_stref_picset.ai1_used[ctr] =
1479                     (curr_poc > cra_poc) ? (ref_poc_l0 >= cra_poc) : (slice_type != ISLICE);
1480             }
1481             if(!(prev_poc - ref_poc_l0))
1482             {
1483                 ctr -= 1;
1484                 i4_num_rpics_l0_excl_dup -= 1;
1485             }
1486             prev_poc = ref_poc_l0;
1487 
1488             i++;
1489         }
1490 
1491         i = 0;
1492         prev_poc = curr_poc;
1493         for(; ctr < (i4_num_rpics_l0_excl_dup + i4_num_rpics_l1_excl_dup); ctr++)
1494         {
1495             WORD32 ref_poc_l1 = aps_ref_list[LIST_1][i]->i4_poc;
1496 
1497             ps_slice_header->s_stref_picset.ai2_delta_poc[ctr] = ref_poc_l1 - prev_poc;
1498 
1499             ps_slice_header->s_stref_picset.ai1_used[ctr] =
1500                 aps_ref_list[LIST_1][i]->i4_used_by_cur_pic_flag;
1501 
1502             /* check if this picture has to be used as reference */
1503             if(1 == ps_slice_header->s_stref_picset.ai1_used[ctr])
1504             {
1505                 /* check for CRA poc related use flag signalling */
1506                 ps_slice_header->s_stref_picset.ai1_used[ctr] =
1507                     (curr_poc > cra_poc) ? (ref_poc_l1 >= cra_poc) : (slice_type != ISLICE);
1508                 /* (slice_type != ISLICE); */
1509             }
1510             if(!(ref_poc_l1 - prev_poc))
1511             {
1512                 ctr -= 1;
1513                 i4_num_rpics_l1_excl_dup -= 1;
1514             }
1515             prev_poc = ref_poc_l1;
1516             i++;
1517         }
1518         ps_slice_header->s_stref_picset.i1_num_neg_pics = i4_num_rpics_l0_excl_dup;
1519 
1520         ps_slice_header->s_stref_picset.i1_num_pos_pics = i4_num_rpics_l1_excl_dup;
1521 
1522         if(IV_IDR_FRAME == ps_curr_inp->s_lap_out.i4_pic_type)
1523         {
1524             ps_slice_header->s_stref_picset.i1_num_neg_pics = 0;
1525             ps_slice_header->s_stref_picset.i1_num_pos_pics = 0;
1526         }
1527 
1528         /* not used so set to -1 */
1529         memset(&ps_slice_header->s_stref_picset.ai1_ref_idc[0], -1, MAX_DPB_SIZE);
1530     }
1531     /* call the ME API to update the DPB of HME pyramids
1532     Upadate list for reference bit-rate only */
1533     if(0 == i4_bridx)
1534     {
1535         ihevce_me_frame_dpb_update(
1536             ps_enc_ctxt->s_module_ctxt.pv_me_ctxt,
1537             num_ref_pics_list0,
1538             num_ref_pics_list1,
1539             &aps_ref_list[LIST_0][0],
1540             &aps_ref_list[LIST_1][0],
1541             i4_thrd_id);
1542     }
1543 
1544     /* Default list creation based on uses as ref pic for current pic flag */
1545     {
1546         WORD32 num_ref_pics_list_final = 0;
1547         WORD32 list_idx = 0;
1548 
1549         /* LIST 0 */
1550         /* run a loop for num ref pics in list 0 */
1551         for(ctr = 0; ctr < num_ref_pics_list0; ctr++)
1552         {
1553             /* check for used as reference flag */
1554             if(1 == aps_ref_list[LIST_0][ctr]->i4_used_by_cur_pic_flag)
1555             {
1556                 /* copy the pointer to the actual valid list idx */
1557                 aps_ref_list[LIST_0][list_idx] = aps_ref_list[LIST_0][ctr];
1558 
1559                 /* increment the valid pic counters and idx */
1560                 list_idx++;
1561                 num_ref_pics_list_final++;
1562             }
1563         }
1564 
1565         /* finally store the number of pictures in List0 */
1566         num_ref_pics_list0 = num_ref_pics_list_final;
1567 
1568         /* LIST 1 */
1569         num_ref_pics_list_final = 0;
1570         list_idx = 0;
1571 
1572         /* run a loop for num ref pics in list 1 */
1573         for(ctr = 0; ctr < num_ref_pics_list1; ctr++)
1574         {
1575             /* check for used as reference flag */
1576             if(1 == aps_ref_list[LIST_1][ctr]->i4_used_by_cur_pic_flag)
1577             {
1578                 /* copy the pointer to the actual valid list idx */
1579                 aps_ref_list[LIST_1][list_idx] = aps_ref_list[LIST_1][ctr];
1580 
1581                 /* increment the valid pic counters and idx */
1582                 list_idx++;
1583                 num_ref_pics_list_final++;
1584             }
1585         }
1586 
1587         /* finally store the number of pictures in List1 */
1588         num_ref_pics_list1 = num_ref_pics_list_final;
1589     }
1590     /*in case of single active ref picture on L0 and L1, then consider one of them weighted
1591     and another non-weighted*/
1592     if(ps_curr_inp->s_lap_out.i4_pic_type == IV_P_FRAME)
1593     {
1594         if(num_ref_pics_list0 > 2)
1595         {
1596             if(aps_ref_list[LIST_0][0]->i4_poc == aps_ref_list[LIST_0][1]->i4_poc)
1597             {
1598                 i4_inc_L0_active_ref_pic = 1;
1599             }
1600         }
1601     }
1602     else
1603     {
1604         if(num_ref_pics_list0 >= 2 && num_ref_pics_list1 >= 2)
1605         {
1606             if(aps_ref_list[LIST_0][0]->i4_poc == aps_ref_list[LIST_0][1]->i4_poc)
1607             {
1608                 i4_inc_L0_active_ref_pic = 1;
1609             }
1610 
1611             if(aps_ref_list[LIST_1][0]->i4_poc == aps_ref_list[LIST_1][1]->i4_poc)
1612             {
1613                 i4_inc_L1_active_ref_pic = 1;
1614             }
1615         }
1616     }
1617     /* append the reference pics in List1 and end of list0 */
1618     for(ctr = 0; ctr < num_ref_pics_list1; ctr++)
1619     {
1620         aps_ref_list[LIST_0][num_ref_pics_list0 + ctr] = aps_ref_list[LIST_1][ctr];
1621     }
1622 
1623     /* append the reference pics in List0 and end of list1 */
1624     for(ctr = 0; ctr < num_ref_pics_list0; ctr++)
1625     {
1626         aps_ref_list[LIST_1][num_ref_pics_list1 + ctr] = aps_ref_list[LIST_0][ctr];
1627     }
1628 
1629     /* reference list modification for adding duplicate reference */
1630     {
1631         WORD32 i4_latest_idx = 0;
1632         recon_pic_buf_t *ps_ref_list_cur;
1633         recon_pic_buf_t *ps_ref_list_prev;
1634         /*List 0*/
1635         ps_ref_list_cur = aps_ref_list[LIST_0][0];
1636         ps_ref_list_prev = ps_ref_list_cur;
1637         for(ctr = 0; ctr < (num_ref_pics_list0 + num_ref_pics_list1); ctr++)
1638         {
1639             if(ps_ref_list_cur->i4_poc != ps_ref_list_prev->i4_poc)
1640             {
1641                 i4_latest_idx++;
1642             }
1643             ps_ref_list_prev = ps_ref_list_cur;
1644             ps_slice_header->s_rplm.i4_ref_poc_l0[ctr] = ps_ref_list_cur->i4_poc;
1645             ps_slice_header->s_rplm.i1_list_entry_l0[ctr] = i4_latest_idx;
1646             if((ctr + 1) < (num_ref_pics_list0 + num_ref_pics_list1))
1647             {
1648                 ps_ref_list_cur = aps_ref_list[LIST_0][ctr + 1];
1649             }
1650         } /*end for*/
1651 
1652         /*LIST 1*/
1653         i4_latest_idx = 0;
1654         ps_ref_list_cur = aps_ref_list[LIST_1][0];
1655         ps_ref_list_prev = ps_ref_list_cur;
1656         for(ctr = 0; ctr < (num_ref_pics_list0 + num_ref_pics_list1); ctr++)
1657         {
1658             if(ps_ref_list_cur->i4_poc != ps_ref_list_prev->i4_poc)
1659             {
1660                 i4_latest_idx++;
1661             }
1662             ps_ref_list_prev = ps_ref_list_cur;
1663             ps_slice_header->s_rplm.i4_ref_poc_l1[ctr] = ps_ref_list_cur->i4_poc;
1664             ps_slice_header->s_rplm.i1_list_entry_l1[ctr] = i4_latest_idx;
1665             if((ctr + 1) < (num_ref_pics_list0 + num_ref_pics_list1))
1666             {
1667                 ps_ref_list_cur = aps_ref_list[LIST_1][ctr + 1];
1668             }
1669         } /*end for*/
1670     }
1671 
1672     /* set number of active references used for l0 and l1 in slice hdr */
1673     ps_slice_header->i1_num_ref_idx_active_override_flag = 1;
1674     ps_slice_header->i1_num_ref_idx_l0_active = num_ref_pics_list0 + num_ref_pics_list1;
1675     if(BSLICE == slice_type)
1676     {
1677         /* i1_num_ref_idx_l1_active applicable only for B pics */
1678         ps_slice_header->i1_num_ref_idx_l1_active = num_ref_pics_list0 + num_ref_pics_list1;
1679     }
1680     /* popluate the slice header parameters with weights and offsets */
1681     {
1682         WORD32 i;
1683 
1684         /* populate the log 2 weight denom if weighted prediction is enabled */
1685         if(1 == wp_flag)
1686         {
1687             ps_slice_header->s_wt_ofst.i1_chroma_log2_weight_denom =
1688                 ps_curr_inp->s_lap_out.i4_log2_chroma_wght_denom;
1689             ps_slice_header->s_wt_ofst.i1_luma_log2_weight_denom =
1690                 ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1691         }
1692 
1693         /* populate the weights and offsets for all pics in L0 + L1 */
1694         for(i = 0; i < (num_ref_pics_list0 + num_ref_pics_list1); i++)
1695         {
1696             /* populate the weights and offsets if weighted prediction is enabled */
1697             if(1 == wp_flag)
1698             {
1699                 ps_slice_header->s_wt_ofst.i1_luma_weight_l0_flag[i] =
1700                     aps_ref_list[LIST_0][i]->s_weight_offset.u1_luma_weight_enable_flag;
1701 
1702                 /* if weights are enabled then copy to slice header */
1703                 if(1 == ps_slice_header->s_wt_ofst.i1_luma_weight_l0_flag[i])
1704                 {
1705                     ps_slice_header->s_wt_ofst.i2_luma_weight_l0[i] =
1706                         aps_ref_list[LIST_0][i]->s_weight_offset.i2_luma_weight;
1707                     ps_slice_header->s_wt_ofst.i2_luma_offset_l0[i] =
1708                         aps_ref_list[LIST_0][i]->s_weight_offset.i2_luma_offset;
1709 
1710                     {
1711                         WORD16 i2_luma_weight =
1712                             (aps_ref_list[LIST_0][i]->s_weight_offset.i2_luma_weight);
1713 
1714                         aps_ref_list[LIST_0][i]->i4_inv_luma_wt =
1715                             ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1716 
1717                         aps_ref_list[LIST_0][i]->i4_log2_wt_denom =
1718                             ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1719                     }
1720                 }
1721                 else
1722                 {
1723                     WORD16 i2_luma_weight = (1 << ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom);
1724 
1725                     /* set to default values */
1726                     aps_ref_list[LIST_0][i]->s_weight_offset.i2_luma_weight = (i2_luma_weight);
1727 
1728                     aps_ref_list[LIST_0][i]->s_weight_offset.i2_luma_offset = 0;
1729 
1730                     aps_ref_list[LIST_0][i]->i4_inv_luma_wt =
1731                         ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1732 
1733                     aps_ref_list[LIST_0][i]->i4_log2_wt_denom =
1734                         ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1735                 }
1736 
1737                 ps_slice_header->s_wt_ofst.i1_chroma_weight_l0_flag[i] =
1738                     aps_ref_list[LIST_0][i]->s_weight_offset.u1_chroma_weight_enable_flag;
1739 
1740                 /* if weights are enabled then copy to slice header */
1741                 if(1 == ps_slice_header->s_wt_ofst.i1_chroma_weight_l0_flag[i])
1742                 {
1743                     ps_slice_header->s_wt_ofst.i2_chroma_weight_l0_cb[i] =
1744                         aps_ref_list[LIST_0][i]->s_weight_offset.i2_cb_weight;
1745                     ps_slice_header->s_wt_ofst.i2_chroma_offset_l0_cb[i] =
1746                         aps_ref_list[LIST_0][i]->s_weight_offset.i2_cb_offset;
1747 
1748                     ps_slice_header->s_wt_ofst.i2_chroma_weight_l0_cr[i] =
1749                         aps_ref_list[LIST_0][i]->s_weight_offset.i2_cr_weight;
1750                     ps_slice_header->s_wt_ofst.i2_chroma_offset_l0_cr[i] =
1751                         aps_ref_list[LIST_0][i]->s_weight_offset.i2_cr_offset;
1752                 }
1753                 else
1754                 {
1755                     /* set to default values */
1756                     aps_ref_list[LIST_0][i]->s_weight_offset.i2_cb_weight =
1757                         (1 << ps_curr_inp->s_lap_out.i4_log2_chroma_wght_denom);
1758                     aps_ref_list[LIST_0][i]->s_weight_offset.i2_cr_weight =
1759                         (1 << ps_curr_inp->s_lap_out.i4_log2_chroma_wght_denom);
1760                     aps_ref_list[LIST_0][i]->s_weight_offset.i2_cb_offset = 0;
1761                     aps_ref_list[LIST_0][i]->s_weight_offset.i2_cr_offset = 0;
1762                 }
1763             }
1764         }
1765 
1766         for(i = 0; i < (num_ref_pics_list0 + num_ref_pics_list1); i++)
1767         {
1768             /* populate the weights and offsets if weighted prediction is enabled */
1769             if(1 == wp_flag)
1770             {
1771                 ps_slice_header->s_wt_ofst.i1_luma_weight_l1_flag[i] =
1772                     aps_ref_list[LIST_1][i]->s_weight_offset.u1_luma_weight_enable_flag;
1773 
1774                 /* if weights are enabled then copy to slice header */
1775                 if(1 == ps_slice_header->s_wt_ofst.i1_luma_weight_l1_flag[i])
1776                 {
1777                     ps_slice_header->s_wt_ofst.i2_luma_weight_l1[i] =
1778                         aps_ref_list[LIST_1][i]->s_weight_offset.i2_luma_weight;
1779                     ps_slice_header->s_wt_ofst.i2_luma_offset_l1[i] =
1780                         aps_ref_list[LIST_1][i]->s_weight_offset.i2_luma_offset;
1781 
1782                     {
1783                         WORD16 i2_luma_weight =
1784                             (aps_ref_list[LIST_1][i]->s_weight_offset.i2_luma_weight);
1785 
1786                         aps_ref_list[LIST_1][i]->i4_inv_luma_wt =
1787                             ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1788 
1789                         aps_ref_list[LIST_1][i]->i4_log2_wt_denom =
1790                             ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1791                     }
1792                 }
1793                 else
1794                 {
1795                     WORD16 i2_luma_weight = (1 << ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom);
1796 
1797                     /* set to default values */
1798                     aps_ref_list[LIST_1][i]->s_weight_offset.i2_luma_weight = (i2_luma_weight);
1799 
1800                     aps_ref_list[LIST_1][i]->s_weight_offset.i2_luma_offset = 0;
1801 
1802                     aps_ref_list[LIST_1][i]->i4_inv_luma_wt =
1803                         ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1804 
1805                     aps_ref_list[LIST_1][i]->i4_log2_wt_denom =
1806                         ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1807                 }
1808 
1809                 ps_slice_header->s_wt_ofst.i1_chroma_weight_l1_flag[i] =
1810                     aps_ref_list[LIST_1][i]->s_weight_offset.u1_chroma_weight_enable_flag;
1811 
1812                 /* if weights are enabled then copy to slice header */
1813                 if(1 == ps_slice_header->s_wt_ofst.i1_chroma_weight_l1_flag[i])
1814                 {
1815                     ps_slice_header->s_wt_ofst.i2_chroma_weight_l1_cb[i] =
1816                         aps_ref_list[LIST_1][i]->s_weight_offset.i2_cb_weight;
1817                     ps_slice_header->s_wt_ofst.i2_chroma_offset_l1_cb[i] =
1818                         aps_ref_list[LIST_1][i]->s_weight_offset.i2_cb_offset;
1819 
1820                     ps_slice_header->s_wt_ofst.i2_chroma_weight_l1_cr[i] =
1821                         aps_ref_list[LIST_1][i]->s_weight_offset.i2_cr_weight;
1822                     ps_slice_header->s_wt_ofst.i2_chroma_offset_l1_cr[i] =
1823                         aps_ref_list[LIST_1][i]->s_weight_offset.i2_cr_offset;
1824                 }
1825                 else
1826                 {
1827                     /* set to default values */
1828                     aps_ref_list[LIST_1][i]->s_weight_offset.i2_cb_weight =
1829                         (1 << ps_curr_inp->s_lap_out.i4_log2_chroma_wght_denom);
1830                     aps_ref_list[LIST_1][i]->s_weight_offset.i2_cr_weight =
1831                         (1 << ps_curr_inp->s_lap_out.i4_log2_chroma_wght_denom);
1832                     aps_ref_list[LIST_1][i]->s_weight_offset.i2_cb_offset = 0;
1833                     aps_ref_list[LIST_1][i]->s_weight_offset.i2_cr_offset = 0;
1834                 }
1835             }
1836         }
1837     }
1838 
1839     /* store the number of reference pics in the list for ME/MC etc */
1840     ps_enc_ctxt->i4_num_ref_l0 = num_ref_pics_list0;
1841     ps_enc_ctxt->i4_num_ref_l1 = num_ref_pics_list1;
1842 
1843 #define HME_USE_ONLY_2REF
1844 #ifndef HME_USE_ONLY_2REF
1845     ps_enc_ctxt->i4_num_ref_l0_active = num_ref_pics_list0;
1846     ps_enc_ctxt->i4_num_ref_l1_active = num_ref_pics_list1;
1847 #else
1848 #if MULTI_REF_ENABLE == 1
1849     if(ps_curr_inp->s_lap_out.i4_quality_preset >= IHEVCE_QUALITY_P3)
1850     {
1851         if(ps_curr_inp->s_lap_out.i4_pic_type == IV_P_FRAME)
1852         {
1853             if(ps_curr_inp->s_lap_out.i4_quality_preset == IHEVCE_QUALITY_P6)
1854             {
1855                 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1856                 {
1857                     ps_enc_ctxt->i4_num_ref_l0_active =
1858                         MIN(MAX_NUM_REFS_IN_PPICS_IN_XS25 + 1, num_ref_pics_list0);
1859                 }
1860                 else
1861                 {
1862                     ps_enc_ctxt->i4_num_ref_l0_active =
1863                         MIN(MAX_NUM_REFS_IN_PPICS_IN_XS25, num_ref_pics_list0);
1864 
1865                     ps_enc_ctxt->i4_num_ref_l0_active += i4_inc_L0_active_ref_pic;
1866                 }
1867             }
1868             else
1869             {
1870                 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1871                 {
1872                     ps_enc_ctxt->i4_num_ref_l0_active = MIN(3, num_ref_pics_list0);
1873                 }
1874                 else
1875                 {
1876                     ps_enc_ctxt->i4_num_ref_l0_active = MIN(2, num_ref_pics_list0);
1877                     ps_enc_ctxt->i4_num_ref_l0_active += i4_inc_L0_active_ref_pic;
1878                 }
1879             }
1880 
1881             ps_enc_ctxt->i4_num_ref_l1_active = 0;
1882         }
1883         else
1884         {
1885             if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1886             {
1887                 ps_enc_ctxt->i4_num_ref_l0_active = MIN(2, num_ref_pics_list0);
1888                 ps_enc_ctxt->i4_num_ref_l1_active = MIN(1, num_ref_pics_list1);
1889                 ps_enc_ctxt->i4_num_ref_l1_active += i4_inc_L1_active_ref_pic;
1890             }
1891             else
1892             {
1893                 ps_enc_ctxt->i4_num_ref_l0_active = MIN(1, num_ref_pics_list0);
1894                 ps_enc_ctxt->i4_num_ref_l1_active = MIN(1, num_ref_pics_list1);
1895 
1896                 ps_enc_ctxt->i4_num_ref_l1_active += i4_inc_L1_active_ref_pic;
1897                 ps_enc_ctxt->i4_num_ref_l0_active += i4_inc_L0_active_ref_pic;
1898             }
1899         }
1900     }
1901     else
1902     {
1903         if(ps_curr_inp->s_lap_out.i4_pic_type == IV_P_FRAME)
1904         {
1905             if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1906                 ps_enc_ctxt->i4_num_ref_l0_active = MIN(4, num_ref_pics_list0);
1907             else
1908                 ps_enc_ctxt->i4_num_ref_l0_active = MIN(4, num_ref_pics_list0);
1909 
1910             ps_enc_ctxt->i4_num_ref_l1_active = 0;
1911         }
1912         else
1913         {
1914             if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1915             {
1916                 ps_enc_ctxt->i4_num_ref_l0_active = MIN(4, num_ref_pics_list0);
1917                 ps_enc_ctxt->i4_num_ref_l1_active = MIN(4, num_ref_pics_list1);
1918             }
1919             else
1920             {
1921                 ps_enc_ctxt->i4_num_ref_l0_active = MIN(4, num_ref_pics_list0);
1922                 ps_enc_ctxt->i4_num_ref_l1_active = MIN(4, num_ref_pics_list1);
1923             }
1924         }
1925     }
1926 #else
1927     if(ps_curr_inp->s_lap_out.i4_pic_type == IV_P_FRAME)
1928     {
1929         if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1930             ps_enc_ctxt->i4_num_ref_l0_active = MIN(3, num_ref_pics_list0);
1931         else
1932             ps_enc_ctxt->i4_num_ref_l0_active = MIN(2, num_ref_pics_list0);
1933 
1934         ps_enc_ctxt->i4_num_ref_l1_active = 0;
1935     }
1936     else
1937     {
1938         if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1939         {
1940             ps_enc_ctxt->i4_num_ref_l0_active = MIN(2, num_ref_pics_list0);
1941             ps_enc_ctxt->i4_num_ref_l1_active = MIN(1, num_ref_pics_list1);
1942         }
1943         else
1944         {
1945             ps_enc_ctxt->i4_num_ref_l0_active = MIN(1, num_ref_pics_list0);
1946             ps_enc_ctxt->i4_num_ref_l1_active = MIN(1, num_ref_pics_list1);
1947         }
1948     }
1949 #endif
1950 
1951 #endif
1952 
1953     ps_slice_header->i1_num_ref_idx_l0_active = MAX(1, ps_enc_ctxt->i4_num_ref_l0_active);
1954     if(BSLICE == slice_type)
1955     {
1956         /* i1_num_ref_idx_l1_active applicable only for B pics */
1957         ps_slice_header->i1_num_ref_idx_l1_active = MAX(1, ps_enc_ctxt->i4_num_ref_l1_active);
1958     }
1959     if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1960     {
1961         /* If Interlace field is enabled,  p field following an cra I field should have only one ref frame */
1962         WORD32 cra_second_poc = cra_poc + 1;
1963 
1964         if(curr_poc == cra_second_poc)
1965         {
1966             /*   set number of active references used for l0 and l1 for me  */
1967             ps_enc_ctxt->i4_num_ref_l0_active = 1;
1968             ps_enc_ctxt->i4_num_ref_l1_active = 0;
1969 
1970             /*   set number of active references used for l0 and l1 in slice hdr */
1971             ps_slice_header->i1_num_ref_idx_active_override_flag = 1;
1972             ps_slice_header->i1_num_ref_idx_l0_active =
1973                 ps_enc_ctxt->i4_num_ref_l0 + ps_enc_ctxt->i4_num_ref_l1;
1974         }
1975     }
1976     return;
1977 }
1978 
1979 /*!
1980 ******************************************************************************
1981 * \if Function name : ihevce_get_frame_lambda_prms \endif
1982 *
1983 * \brief
1984 *    Function whihc calculates the Lambda params for current picture
1985 *
1986 * \param[in] ps_enc_ctxt : encoder ctxt pointer
1987 * \param[in] ps_cur_pic_ctxt : current pic ctxt
1988 * \param[in] i4_cur_frame_qp : current pic QP
1989 * \param[in] first_field : is first field flag
1990 * \param[in] i4_temporal_lyr_id : Current picture layer id
1991 *
1992 * \return
1993 *    None
1994 *
1995 * \author
1996 *  Ittiam
1997 *
1998 *****************************************************************************
1999 */
ihevce_get_frame_lambda_prms(enc_ctxt_t * ps_enc_ctxt,pre_enc_me_ctxt_t * ps_cur_pic_ctxt,WORD32 i4_cur_frame_qp,WORD32 first_field,WORD32 i4_is_ref_pic,WORD32 i4_temporal_lyr_id,double f_i_pic_lamda_modifier,WORD32 i4_inst_id,WORD32 i4_lambda_type)2000 void ihevce_get_frame_lambda_prms(
2001     enc_ctxt_t *ps_enc_ctxt,
2002     pre_enc_me_ctxt_t *ps_cur_pic_ctxt,
2003     WORD32 i4_cur_frame_qp,
2004     WORD32 first_field,
2005     WORD32 i4_is_ref_pic,
2006     WORD32 i4_temporal_lyr_id,
2007     double f_i_pic_lamda_modifier,
2008     WORD32 i4_inst_id,
2009     WORD32 i4_lambda_type)
2010 {
2011     double lambda_modifier = CONST_LAMDA_MOD_VAL;
2012     double lambda_uv_modifier = CONST_LAMDA_MOD_VAL;
2013     double lambda = 0;
2014     double lambda_uv;
2015     WORD32 i4_use_const_lamda_modifier;
2016 
2017     /* initialize lambda based on frm qp, slice type, num b and temporal id */
2018     /* This lamba calculation mimics the jctvc doc (TODO add doc number     */
2019 
2020     WORD32 num_b_frms =
2021         (1 << ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_max_temporal_layers) - 1;
2022     WORD32 chroma_qp = (ps_enc_ctxt->ps_stat_prms->s_src_prms.i4_chr_format == IV_YUV_422SP_UV)
2023                            ? MIN(i4_cur_frame_qp, 51)
2024                            : gai1_ihevc_chroma_qp_scale[i4_cur_frame_qp + MAX_QP_BD_OFFSET];
2025 
2026     WORD32 i4_qp_bdoffset =
2027         6 * (ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.i4_internal_bit_depth - 8);
2028     WORD32 slice_type = ps_cur_pic_ctxt->s_slice_hdr.i1_slice_type;
2029 
2030     (void)first_field;
2031     (void)i4_is_ref_pic;
2032     (void)i4_temporal_lyr_id;
2033     i4_use_const_lamda_modifier = USE_CONSTANT_LAMBDA_MODIFIER;
2034     i4_use_const_lamda_modifier = i4_use_const_lamda_modifier ||
2035                                   ((ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_vqet &
2036                                     (1 << BITPOS_IN_VQ_TOGGLE_FOR_CONTROL_TOGGLER)) &&
2037                                    ((ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_vqet &
2038                                      (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_NOISE_PRESERVATION)) ||
2039                                     (ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_vqet &
2040                                      (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_PSYRDOPT_1)) ||
2041                                     (ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_vqet &
2042                                      (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_PSYRDOPT_2)) ||
2043                                     (ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_vqet &
2044                                      (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_PSYRDOPT_3))));
2045 
2046     /* lambda modifier is the dependent on slice type and temporal id  */
2047     if(ISLICE == slice_type)
2048     {
2049         double temporal_correction_islice = 1.0 - 0.05 * num_b_frms;
2050         temporal_correction_islice = MAX(0.5, temporal_correction_islice);
2051 
2052         lambda_modifier = 0.57 * temporal_correction_islice;
2053         lambda_uv_modifier = lambda_modifier;
2054         if(i4_use_const_lamda_modifier)
2055         {
2056             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_modifier = f_i_pic_lamda_modifier;
2057             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_uv_modifier = f_i_pic_lamda_modifier;
2058         }
2059         else
2060         {
2061             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_modifier = lambda_modifier;
2062             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_uv_modifier = lambda_uv_modifier;
2063         }
2064     }
2065     else if(PSLICE == slice_type)
2066     {
2067         if(first_field)
2068             lambda_modifier = 0.442;  //0.442*0.8;
2069         else
2070             lambda_modifier = 0.442;
2071         lambda_uv_modifier = lambda_modifier;
2072         if(i4_use_const_lamda_modifier)
2073         {
2074             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_modifier = CONST_LAMDA_MOD_VAL;
2075             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_uv_modifier = CONST_LAMDA_MOD_VAL;
2076         }
2077         else
2078         {
2079             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_modifier = lambda_modifier;
2080             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_uv_modifier = lambda_uv_modifier;
2081         }
2082     }
2083     else
2084     {
2085         /* BSLICE */
2086         if(1 == i4_is_ref_pic)
2087         {
2088             lambda_modifier = 0.3536;
2089         }
2090         else if(2 == i4_is_ref_pic)
2091         {
2092             lambda_modifier = 0.45;
2093         }
2094         else
2095         {
2096             lambda_modifier = 0.68;
2097         }
2098         lambda_uv_modifier = lambda_modifier;
2099         if(i4_use_const_lamda_modifier)
2100         {
2101             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_modifier = CONST_LAMDA_MOD_VAL;
2102             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_uv_modifier = CONST_LAMDA_MOD_VAL;
2103         }
2104         else
2105         {
2106             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_modifier = lambda_modifier;
2107             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_uv_modifier = lambda_uv_modifier;
2108         }
2109         /* TODO: Disable lambda modification for interlace encode to match HM runs */
2110         //if(0 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
2111         {
2112             /* modify b lambda further based on temporal id */
2113             if(i4_temporal_lyr_id)
2114             {
2115                 lambda_modifier *= CLIP3((((double)(i4_cur_frame_qp - 12)) / 6.0), 2.00, 4.00);
2116                 lambda_uv_modifier *= CLIP3((((double)(chroma_qp - 12)) / 6.0), 2.00, 4.00);
2117             }
2118         }
2119     }
2120     if(i4_use_const_lamda_modifier)
2121     {
2122         if(ISLICE == slice_type)
2123         {
2124             lambda_modifier = f_i_pic_lamda_modifier;
2125             lambda_uv_modifier = f_i_pic_lamda_modifier;
2126         }
2127         else
2128         {
2129             lambda_modifier = CONST_LAMDA_MOD_VAL;
2130             lambda_uv_modifier = CONST_LAMDA_MOD_VAL;
2131         }
2132     }
2133 
2134     switch(i4_lambda_type)
2135     {
2136     case 0:
2137     {
2138         i4_qp_bdoffset = 0;
2139 
2140         lambda = pow(2.0, (((double)(i4_cur_frame_qp + i4_qp_bdoffset - 12)) / 3.0));
2141         lambda_uv = pow(2.0, (((double)(chroma_qp + i4_qp_bdoffset - 12)) / 3.0));
2142 
2143         /* modify the base lambda according to lambda modifier */
2144         lambda *= lambda_modifier;
2145         lambda_uv *= lambda_uv_modifier;
2146 
2147         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].u4_chroma_cost_weighing_factor =
2148             (UWORD32)((lambda / lambda_uv) * (1 << CHROMA_COST_WEIGHING_FACTOR_Q_SHIFT));
2149 
2150         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_qf =
2151             (LWORD64)(lambda * (1 << LAMBDA_Q_SHIFT));
2152 
2153         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_chroma_qf =
2154             (LWORD64)(lambda_uv * (1 << LAMBDA_Q_SHIFT));
2155 
2156         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_sad_lambda_qf =
2157             (WORD32)(sqrt(lambda) * (1 << LAMBDA_Q_SHIFT));
2158         if(i4_use_const_lamda_modifier)
2159         {
2160             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_lambda_qf =
2161                 (WORD32)((sqrt(lambda)) * (1 << LAMBDA_Q_SHIFT));
2162 
2163             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf =
2164                 (WORD32)(sqrt(lambda) * (1 << LAMBDA_Q_SHIFT));
2165 
2166             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf =
2167                 (WORD32)((sqrt(lambda)) * (1 << (LAMBDA_Q_SHIFT)));
2168         }
2169         else
2170         {
2171             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_lambda_qf =
2172                 (WORD32)((sqrt(lambda) / 1.5) * (1 << LAMBDA_Q_SHIFT));
2173 
2174             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf =
2175                 (WORD32)(sqrt(lambda * 1.5) * (1 << LAMBDA_Q_SHIFT));
2176 
2177             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf =
2178                 (WORD32)((sqrt(lambda * 1.5)) * (1 << (LAMBDA_Q_SHIFT)));
2179         }
2180         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_type2_lambda_qf =
2181             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_qf;
2182 
2183         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_type2_lambda_chroma_qf =
2184             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_chroma_qf;
2185 
2186         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_sad_type2_lambda_qf =
2187             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_sad_lambda_qf;
2188 
2189         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_type2_lambda_qf =
2190             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_lambda_qf;
2191 
2192         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_type2_lambda_qf =
2193             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf;
2194 
2195         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_type2_lambda_qf =
2196             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf;
2197 
2198         break;
2199     }
2200     case 1:
2201     {
2202         lambda = pow(2.0, (((double)(i4_cur_frame_qp + i4_qp_bdoffset - 12)) / 3.0));
2203         lambda_uv = pow(2.0, (((double)(chroma_qp + i4_qp_bdoffset - 12)) / 3.0));
2204 
2205         /* modify the base lambda according to lambda modifier */
2206         lambda *= lambda_modifier;
2207         lambda_uv *= lambda_uv_modifier;
2208 
2209         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].u4_chroma_cost_weighing_factor =
2210             (UWORD32)((lambda / lambda_uv) * (1 << CHROMA_COST_WEIGHING_FACTOR_Q_SHIFT));
2211 
2212         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_qf =
2213             (LWORD64)(lambda * (1 << LAMBDA_Q_SHIFT));
2214 
2215         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_chroma_qf =
2216             (LWORD64)(lambda_uv * (1 << LAMBDA_Q_SHIFT));
2217 
2218         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_sad_lambda_qf =
2219             (WORD32)(sqrt(lambda) * (1 << LAMBDA_Q_SHIFT));
2220         if(i4_use_const_lamda_modifier)
2221         {
2222             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_lambda_qf =
2223                 (WORD32)((sqrt(lambda)) * (1 << LAMBDA_Q_SHIFT));
2224 
2225             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf =
2226                 (WORD32)(sqrt(lambda) * (1 << LAMBDA_Q_SHIFT));
2227 
2228             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf =
2229                 (WORD32)((sqrt(lambda)) * (1 << (LAMBDA_Q_SHIFT)));
2230         }
2231         else
2232         {
2233             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_lambda_qf =
2234                 (WORD32)((sqrt(lambda) / 1.5) * (1 << LAMBDA_Q_SHIFT));
2235 
2236             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf =
2237                 (WORD32)(sqrt(lambda * 1.5) * (1 << LAMBDA_Q_SHIFT));
2238 
2239             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf =
2240                 (WORD32)((sqrt(lambda * 1.5)) * (1 << (LAMBDA_Q_SHIFT)));
2241         }
2242         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_type2_lambda_qf =
2243             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_qf;
2244 
2245         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_type2_lambda_chroma_qf =
2246             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_chroma_qf;
2247 
2248         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_sad_type2_lambda_qf =
2249             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_sad_lambda_qf;
2250 
2251         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_type2_lambda_qf =
2252             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_lambda_qf;
2253 
2254         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_type2_lambda_qf =
2255             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf;
2256 
2257         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_type2_lambda_qf =
2258             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf;
2259 
2260         break;
2261     }
2262     case 2:
2263     {
2264         lambda = pow(2.0, (((double)(i4_cur_frame_qp + i4_qp_bdoffset - 12)) / 3.0));
2265         lambda_uv = pow(2.0, (((double)(chroma_qp + i4_qp_bdoffset - 12)) / 3.0));
2266 
2267         /* modify the base lambda according to lambda modifier */
2268         lambda *= lambda_modifier;
2269         lambda_uv *= lambda_uv_modifier;
2270 
2271         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].u4_chroma_cost_weighing_factor =
2272             (UWORD32)((lambda / lambda_uv) * (1 << CHROMA_COST_WEIGHING_FACTOR_Q_SHIFT));
2273 
2274         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_qf =
2275             (LWORD64)(lambda * (1 << LAMBDA_Q_SHIFT));
2276 
2277         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_chroma_qf =
2278             (LWORD64)(lambda_uv * (1 << LAMBDA_Q_SHIFT));
2279 
2280         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_sad_lambda_qf =
2281             (WORD32)(sqrt(lambda) * (1 << LAMBDA_Q_SHIFT));
2282 
2283         if(i4_use_const_lamda_modifier)
2284         {
2285             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_lambda_qf =
2286                 (WORD32)((sqrt(lambda)) * (1 << LAMBDA_Q_SHIFT));
2287 
2288             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf =
2289                 (WORD32)(sqrt(lambda) * (1 << LAMBDA_Q_SHIFT));
2290 
2291             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf =
2292                 (WORD32)((sqrt(lambda)) * (1 << (LAMBDA_Q_SHIFT)));
2293         }
2294         else
2295         {
2296             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_lambda_qf =
2297                 (WORD32)((sqrt(lambda) / 1.5) * (1 << LAMBDA_Q_SHIFT));
2298 
2299             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf =
2300                 (WORD32)(sqrt(lambda * 1.5) * (1 << LAMBDA_Q_SHIFT));
2301 
2302             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf =
2303                 (WORD32)((sqrt(lambda * 1.5)) * (1 << (LAMBDA_Q_SHIFT)));
2304         }
2305         /* lambda corresponding to 8- bit, for metrics based on 8- bit ( Example 8bit SAD in encloop)*/
2306 
2307         lambda = pow(2.0, (((double)(i4_cur_frame_qp - 12)) / 3.0));
2308         lambda_uv = pow(2.0, (((double)(chroma_qp - 12)) / 3.0));
2309 
2310         /* modify the base lambda according to lambda modifier */
2311         lambda *= lambda_modifier;
2312         lambda_uv *= lambda_uv_modifier;
2313 
2314         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].u4_chroma_cost_weighing_factor =
2315             (UWORD32)((lambda / lambda_uv) * (1 << CHROMA_COST_WEIGHING_FACTOR_Q_SHIFT));
2316 
2317         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_type2_lambda_qf =
2318             (LWORD64)(lambda * (1 << LAMBDA_Q_SHIFT));
2319 
2320         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_type2_lambda_chroma_qf =
2321             (LWORD64)(lambda_uv * (1 << LAMBDA_Q_SHIFT));
2322 
2323         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_sad_type2_lambda_qf =
2324             (WORD32)(sqrt(lambda) * (1 << LAMBDA_Q_SHIFT));
2325         if(i4_use_const_lamda_modifier)
2326         {
2327             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_type2_lambda_qf =
2328                 (WORD32)((sqrt(lambda)) * (1 << LAMBDA_Q_SHIFT));
2329 
2330             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_type2_lambda_qf =
2331                 (WORD32)(sqrt(lambda) * (1 << LAMBDA_Q_SHIFT));
2332 
2333             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_type2_lambda_qf =
2334                 (WORD32)((sqrt(lambda)) * (1 << (LAMBDA_Q_SHIFT)));
2335         }
2336         else
2337         {
2338             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_type2_lambda_qf =
2339                 (WORD32)((sqrt(lambda) / 1.5) * (1 << LAMBDA_Q_SHIFT));
2340 
2341             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_type2_lambda_qf =
2342                 (WORD32)(sqrt(lambda * 1.5) * (1 << LAMBDA_Q_SHIFT));
2343 
2344             ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_type2_lambda_qf =
2345                 (WORD32)((sqrt(lambda * 1.5)) * (1 << (LAMBDA_Q_SHIFT)));
2346         }
2347 
2348         break;
2349     }
2350     default:
2351     {
2352         /* Intended to be a barren wasteland! */
2353         ASSERT(0);
2354     }
2355     }
2356 
2357     /* Assign the final lambdas after up shifting to its q format */
2358 
2359     /* closed loop ssd lambda is same as final lambda */
2360 
2361     /* --- Initialized the lambda for SATD computations --- */
2362     if(i4_use_const_lamda_modifier)
2363     {
2364         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf =
2365             (WORD32)(sqrt(lambda) * (1 << LAMBDA_Q_SHIFT));
2366 
2367         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf =
2368             (WORD32)((sqrt(lambda)) * (1 << (LAMBDA_Q_SHIFT)));
2369     }
2370     else
2371     {
2372         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf =
2373             (WORD32)(sqrt(lambda * 1.5) * (1 << LAMBDA_Q_SHIFT));
2374 
2375         ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf =
2376             (WORD32)((sqrt(lambda * 1.5)) * (1 << (LAMBDA_Q_SHIFT)));
2377     }
2378 }
2379 
2380 /*!
2381 ******************************************************************************
2382 * \if Function name : ihevce_update_qp_L1_sad_based \endif
2383 *
2384 * \brief
2385 *    Function which recalculates qp in case of scene cut based on L1 satd/act
2386 *
2387 * \param[in] ps_enc_ctxt : encoder ctxt pointer
2388 * \param[in] ps_cur_pic_ctxt : current pic ctxt
2389 * \param[in] i4_cur_frame_qp : current pic QP
2390 * \param[in] first_field : is first field flag
2391 * \param[in] i4_temporal_lyr_id : Current picture layer id
2392 *
2393 * \return
2394 *    None
2395 *
2396 * \author
2397 *  Ittiam
2398 *
2399 *****************************************************************************
2400 */
ihevce_update_qp_L1_sad_based(enc_ctxt_t * ps_enc_ctxt,ihevce_lap_enc_buf_t * ps_curr_inp,ihevce_lap_enc_buf_t * ps_prev_inp,pre_enc_me_ctxt_t * ps_curr_out,WORD32 i4_is_last_thread)2401 void ihevce_update_qp_L1_sad_based(
2402     enc_ctxt_t *ps_enc_ctxt,
2403     ihevce_lap_enc_buf_t *ps_curr_inp,
2404     ihevce_lap_enc_buf_t *ps_prev_inp,
2405     pre_enc_me_ctxt_t *ps_curr_out,
2406     WORD32 i4_is_last_thread)
2407 {
2408     WORD32 i4_l1_ht, i4_l1_wd;
2409     ihevce_ed_blk_t *ps_ed_4x4 = ps_curr_out->ps_layer1_buf;
2410     WORD32 best_satd_16x16;
2411     //LWORD64 acc_satd = 0;
2412     LWORD64 acc_sad = 0; /*SAD accumulated to compare with coarse me sad*/
2413     WORD32 i4_tot_4x4block_l1_x, i4_tot_4x4block_l1_y;
2414     WORD32 i4_tot_ctb_l1_x, i4_tot_ctb_l1_y;
2415     WORD32 i;
2416     WORD32 i4_act_factor;
2417     UWORD8 u1_cu_possible_qp;
2418     WORD32 i4_q_scale_mod;
2419     LWORD64 i8_best_satd_16x16;
2420     LWORD64 i8_frame_satd_by_act_L1_accum;
2421     LWORD64 i8_frame_acc_sadt_L1, i8_frame_acc_sadt_L1_squared;
2422     WORD32 i4_new_frame_qp = 0, i4_qp_for_I_pic = 0;
2423     LWORD64 pre_intra_satd_act_evaluated = 0;
2424     ihevce_ed_ctb_l1_t *ps_ed_ctb_l1 = ps_curr_out->ps_ed_ctb_l1;
2425     WORD32 i4_j;
2426     double scale_factor_cmplx_change_detection;
2427     WORD32 i4_cmplx_change_detection_thrsh;
2428     long double ld_frame_avg_satd_L1;
2429 
2430     if(i4_is_last_thread)
2431     {
2432         ihevce_decomp_pre_intra_master_ctxt_t *ps_master_ctxt =
2433             (ihevce_decomp_pre_intra_master_ctxt_t *)
2434                 ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt;
2435         ihevce_decomp_pre_intra_ctxt_t *ps_ctxt = ps_master_ctxt->aps_decomp_pre_intra_thrd_ctxt[0];
2436 
2437         i4_l1_wd = ps_ctxt->as_layers[1].i4_actual_wd;
2438         i4_l1_ht = ps_ctxt->as_layers[1].i4_actual_ht;
2439 
2440         if((ps_curr_inp->s_lap_out.i4_quality_preset == IHEVCE_QUALITY_P6) &&
2441            (ps_curr_inp->s_lap_out.i4_temporal_lyr_id > TEMPORAL_LAYER_DISABLE))
2442         {
2443             i8_frame_acc_sadt_L1 = -1;
2444         }
2445         else
2446         {
2447             /*the accumulation of intra satd and calculation of new qp happens for all thread
2448     It must be made sure every thread returns same value of intra satd and qp*/
2449             i8_frame_acc_sadt_L1 = ihevce_decomp_pre_intra_get_frame_satd(
2450                 ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt, &i4_l1_wd, &i4_l1_ht);
2451         }
2452 
2453 #if USE_SQRT_AVG_OF_SATD_SQR
2454         if((ps_curr_inp->s_lap_out.i4_quality_preset == IHEVCE_QUALITY_P6) &&
2455            (ps_curr_inp->s_lap_out.i4_temporal_lyr_id > TEMPORAL_LAYER_DISABLE))
2456         {
2457             i8_frame_acc_sadt_L1_squared = 0x7fffffff;
2458         }
2459         else
2460         {
2461             i8_frame_acc_sadt_L1_squared = ihevce_decomp_pre_intra_get_frame_satd_squared(
2462                 ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt, &i4_l1_wd, &i4_l1_ht);
2463         }
2464 #else
2465         i8_frame_acc_sadt_L1_squared = i8_frame_acc_sadt_L1;
2466 #endif
2467         if((i4_l1_wd * i4_l1_ht) > (245760 /*640 * 384*/))
2468         {
2469             scale_factor_cmplx_change_detection =
2470                 (double)0.12 * ((i4_l1_wd * i4_l1_ht) / (640.0 * 384.0));
2471             i4_cmplx_change_detection_thrsh =
2472                 (WORD32)(HME_HIGH_SAD_BLK_THRESH * (1 - scale_factor_cmplx_change_detection));
2473         }
2474         else
2475         {
2476             scale_factor_cmplx_change_detection =
2477                 (double)0.12 * ((640.0 * 384.0) / (i4_l1_wd * i4_l1_ht));
2478             i4_cmplx_change_detection_thrsh =
2479                 (WORD32)(HME_HIGH_SAD_BLK_THRESH * (1 + scale_factor_cmplx_change_detection));
2480         }
2481         i4_tot_4x4block_l1_x =
2482             ((i4_l1_wd + ((MAX_CTB_SIZE >> 1) - 1)) & 0xFFFFFFE0) /
2483             4;  //((i4_l1_wd + 31) & 0xFFFFFFE0)/4;//(i4_l1_wd + (i4_l1_wd % 32 )) / 4;
2484         i4_tot_4x4block_l1_y =
2485             ((i4_l1_ht + ((MAX_CTB_SIZE >> 1) - 1)) & 0xFFFFFFE0) /
2486             4;  //((i4_l1_ht + 31) & 0xFFFFFFE0)/4;//(i4_l1_ht + (i4_l1_ht % 32 )) / 4;
2487         ld_frame_avg_satd_L1 =
2488             (WORD32)log(
2489                 1 + (long double)i8_frame_acc_sadt_L1_squared /
2490                         ((long double)((i4_tot_4x4block_l1_x * i4_tot_4x4block_l1_y) >> 2))) /
2491             log(2.0);
2492         /* L1 satd accumalated for computing qp */
2493         i8_frame_satd_by_act_L1_accum = 0;
2494         i4_tot_ctb_l1_x =
2495             ((i4_l1_wd + ((MAX_CTB_SIZE >> 1) - 1)) & 0xFFFFFFE0) / (MAX_CTB_SIZE >> 1);
2496         i4_tot_ctb_l1_y =
2497             ((i4_l1_ht + ((MAX_CTB_SIZE >> 1) - 1)) & 0xFFFFFFE0) / (MAX_CTB_SIZE >> 1);
2498 
2499         for(i = 0; i < (i4_tot_ctb_l1_x * i4_tot_ctb_l1_y); i += 1)
2500         {
2501             for(i4_j = 0; i4_j < 16; i4_j++)
2502             {
2503                 if(ps_ed_ctb_l1->i4_best_satd_8x8[i4_j] != -1)
2504                 {
2505                     ASSERT(ps_ed_ctb_l1->i4_best_satd_8x8[i4_j] >= 0);
2506                     ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j] >= 0);
2507 
2508                     if((ps_curr_inp->s_lap_out.i4_quality_preset == IHEVCE_QUALITY_P6) &&
2509                        (ps_curr_inp->s_lap_out.i4_temporal_lyr_id > TEMPORAL_LAYER_DISABLE))
2510                     {
2511                         best_satd_16x16 = 0;
2512                     }
2513                     else
2514                     {
2515                         best_satd_16x16 = ps_ed_ctb_l1->i4_best_satd_8x8[i4_j];
2516                     }
2517 
2518                     acc_sad += (WORD32)ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j];
2519                     //acc_satd += (WORD32)best_satd_16x16;
2520                     u1_cu_possible_qp = ihevce_cu_level_qp_mod(
2521                         32,
2522                         best_satd_16x16,
2523                         ld_frame_avg_satd_L1,
2524                         REF_MOD_STRENGTH,  // To be changed later
2525                         &i4_act_factor,
2526                         &i4_q_scale_mod,
2527                         &ps_enc_ctxt->s_rc_quant);
2528                     i8_best_satd_16x16 = best_satd_16x16 << QP_LEVEL_MOD_ACT_FACTOR;
2529 
2530                     if((ps_curr_inp->s_lap_out.i4_quality_preset == IHEVCE_QUALITY_P6) &&
2531                        (ps_curr_inp->s_lap_out.i4_temporal_lyr_id > TEMPORAL_LAYER_DISABLE))
2532                     {
2533                         i4_act_factor = (1 << QP_LEVEL_MOD_ACT_FACTOR);
2534                     }
2535 
2536                     if(0 != i4_act_factor)
2537                     {
2538                         i8_frame_satd_by_act_L1_accum +=
2539                             ((WORD32)(i8_best_satd_16x16 / i4_act_factor));
2540                         /*Accumulate SAD for those regions which will undergo evaluation in L0 stage*/
2541                         if(ps_ed_4x4->intra_or_inter != 2)
2542                             pre_intra_satd_act_evaluated +=
2543                                 ((WORD32)(i8_best_satd_16x16 / i4_act_factor));
2544                     }
2545                 }
2546                 ps_ed_4x4 += 4;
2547             }
2548             ps_ed_ctb_l1 += 1;
2549         }
2550         /** store the L1 satd in context struct
2551     Note: this variable is common across all thread. it must be made sure all threads write same value*/
2552         if((ps_curr_inp->s_lap_out.i4_quality_preset == IHEVCE_QUALITY_P6) &&
2553            (ps_curr_inp->s_lap_out.i4_temporal_lyr_id > TEMPORAL_LAYER_DISABLE))
2554         {
2555             i8_frame_satd_by_act_L1_accum = ps_prev_inp->s_rc_lap_out.i8_frame_satd_by_act_L1_accum;
2556             ps_curr_inp->s_rc_lap_out.i8_frame_satd_by_act_L1_accum = i8_frame_satd_by_act_L1_accum;
2557             ps_curr_inp->s_rc_lap_out.i8_satd_by_act_L1_accum_evaluated = -1;
2558         }
2559         else
2560         {
2561             ps_curr_inp->s_rc_lap_out.i8_frame_satd_by_act_L1_accum = i8_frame_satd_by_act_L1_accum;
2562             ps_curr_inp->s_rc_lap_out.i8_satd_by_act_L1_accum_evaluated =
2563                 pre_intra_satd_act_evaluated;
2564         }
2565 
2566         ps_curr_inp->s_rc_lap_out.i8_pre_intra_satd = i8_frame_acc_sadt_L1;
2567         /*accumulate raw intra sad without subtracting non coded sad*/
2568         ps_curr_inp->s_rc_lap_out.i8_raw_pre_intra_sad = acc_sad;
2569     }
2570     /*update pre-enc qp using data from L1 to use better qp in L0 in case of cbr mode*/
2571     if(i4_is_last_thread)
2572     {
2573         /* acquire mutex lock for rate control calls */
2574         osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
2575         {
2576             LWORD64 i8_est_L0_satd_by_act;
2577             WORD32 i4_cur_q_scale;
2578             if(ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode != CONST_QP)
2579             {
2580                 /*RCTODO :This needs to be reviewed in the context of 10/12 bit encoding as the Qp seems to be sub-optimal*/
2581                 if(ps_enc_ctxt->ps_stat_prms->s_pass_prms.i4_pass != 2)
2582                     i4_cur_q_scale =
2583                         ps_enc_ctxt->s_rc_quant.pi4_qp_to_qscale
2584                             [ps_curr_out->i4_curr_frm_qp];  // + ps_enc_ctxt->s_rc_quant.i1_qp_offset];
2585                 else
2586                     i4_cur_q_scale = ps_enc_ctxt->s_rc_quant
2587                                          .pi4_qp_to_qscale[MAX(ps_curr_out->i4_curr_frm_qp, 0)];
2588             }
2589             else
2590                 i4_cur_q_scale =
2591                     ps_enc_ctxt->s_rc_quant.pi4_qp_to_qscale
2592                         [ps_curr_out->i4_curr_frm_qp + ps_enc_ctxt->s_rc_quant.i1_qp_offset];
2593 
2594             i4_cur_q_scale = (i4_cur_q_scale + (1 << (QSCALE_Q_FAC_3 - 1))) >> QSCALE_Q_FAC_3;
2595 
2596             i8_est_L0_satd_by_act = ihevce_get_L0_satd_based_on_L1(
2597                 i8_frame_satd_by_act_L1_accum,
2598                 ps_curr_inp->s_rc_lap_out.i4_num_pels_in_frame_considered,
2599                 i4_cur_q_scale);
2600             /*HEVC_RC query rate control for qp*/
2601             if(ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode != 3)
2602             {
2603                 i4_new_frame_qp = ihevce_get_L0_est_satd_based_scd_qp(
2604                     ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
2605                     &ps_curr_inp->s_rc_lap_out,
2606                     i8_est_L0_satd_by_act,
2607                     8.00);
2608             }
2609             else
2610                 i4_new_frame_qp = ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms
2611                                       .as_tgt_params[ps_enc_ctxt->i4_resolution_id]
2612                                       .ai4_frame_qp[0];
2613             i4_new_frame_qp = CLIP3(i4_new_frame_qp, 1, 51);
2614             i4_qp_for_I_pic = CLIP3(i4_qp_for_I_pic, 1, 51);
2615             ps_curr_inp->s_rc_lap_out.i4_L1_qp = i4_new_frame_qp;
2616             /*I frame qp = qp-3 due to effect of lambda modifier*/
2617             i4_qp_for_I_pic = i4_new_frame_qp - 3;
2618 
2619             /*use new qp get possible qp even for inter pictures assuming default offset*/
2620             if(ps_curr_inp->s_lap_out.i4_pic_type != IV_IDR_FRAME &&
2621                ps_curr_inp->s_lap_out.i4_pic_type != IV_I_FRAME)
2622             {
2623                 i4_new_frame_qp += ps_curr_inp->s_lap_out.i4_temporal_lyr_id + 1;
2624             }
2625 
2626             /*accumulate the L1 ME sad using skip sad value based on qp*/
2627             /*accumulate this only for last thread as it ll be guranteed that L1 ME sad is completely populated*/
2628             /*The lambda modifier in encoder is tuned in such a way that the qp offsets according to lambda modifer are as follows
2629                 Note: These qp offset only account for lambda modifier, Hence this should be applied over qp offset that is already there due to picture type
2630                 relative lambda scale(these lambda diff are mapped into qp difference which is applied over and obove the qp offset)
2631                 Qi =  Iqp                         1
2632                 Qp =  Iqp                         1
2633                 Qb =  Iqp + 1.55                  1.48
2634                 Qb1 = Iqp + 3.1                   2.05
2635                 Qb2 = Iqp + 3.1                   2.05*/
2636 
2637             /*ihevce_compute_offsets_from_rc(ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],ai4_offsets,&ps_curr_inp->s_lap_out);*/
2638 
2639             if(ps_curr_inp->s_lap_out.i4_pic_type == IV_I_FRAME ||
2640                ps_curr_inp->s_lap_out.i4_pic_type == IV_IDR_FRAME)
2641             {
2642                 i4_new_frame_qp = i4_new_frame_qp - 3;
2643             }
2644             else if(ps_curr_inp->s_lap_out.i4_pic_type == IV_P_FRAME)
2645             {
2646                 i4_new_frame_qp = i4_new_frame_qp - 2;
2647             }
2648             if(ps_curr_inp->s_lap_out.i4_pic_type == IV_B_FRAME &&
2649                ps_curr_inp->s_lap_out.i4_temporal_lyr_id == 1)
2650             {
2651                 i4_new_frame_qp = i4_new_frame_qp + 2;
2652             }
2653             else if(
2654                 ps_curr_inp->s_lap_out.i4_pic_type == IV_B_FRAME &&
2655                 ps_curr_inp->s_lap_out.i4_temporal_lyr_id == 2)
2656             {
2657                 i4_new_frame_qp = i4_new_frame_qp + 6;
2658             }
2659             else if(
2660                 ps_curr_inp->s_lap_out.i4_pic_type == IV_B_FRAME &&
2661                 ps_curr_inp->s_lap_out.i4_temporal_lyr_id == 3)
2662             {
2663                 i4_new_frame_qp = i4_new_frame_qp + 7;
2664             }
2665 
2666             i4_new_frame_qp = CLIP3(i4_new_frame_qp, 1, 51);
2667             i4_qp_for_I_pic = CLIP3(i4_qp_for_I_pic, 1, 51);
2668 
2669             {
2670                 calc_l1_level_hme_intra_sad_different_qp(
2671                     ps_enc_ctxt, ps_curr_out, ps_curr_inp, i4_tot_ctb_l1_x, i4_tot_ctb_l1_y);
2672 
2673                 /** frame accumulated SAD over entire frame after accounting for dead zone SAD, this is least of intra or inter*/
2674                 /*ihevce_accum_hme_sad_subgop_rc(ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],&ps_curr_inp->s_lap_out);    */
2675                 ihevce_rc_register_L1_analysis_data(
2676                     ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
2677                     &ps_curr_inp->s_rc_lap_out,
2678                     i8_est_L0_satd_by_act,
2679                     ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad
2680                         [i4_new_frame_qp],  //since the sad passed will be used to calc complexity it should be non coded sad subtracted sad
2681                     ps_curr_inp->s_rc_lap_out.ai8_frame_acc_coarse_me_sad[i4_new_frame_qp]);
2682 
2683                 ihevce_coarse_me_get_rc_param(
2684                     ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
2685                     &ps_curr_out->i8_acc_frame_coarse_me_cost,
2686                     &ps_curr_out->i8_acc_frame_coarse_me_sad,
2687                     &ps_curr_out->i8_acc_num_blks_high_sad,
2688                     &ps_curr_out->i8_total_blks,
2689                     ps_curr_inp->s_lap_out.i4_is_prev_pic_in_Tid0_same_scene);
2690 
2691                 if(ps_curr_out->i8_total_blks)
2692                 {
2693                     ps_curr_out->i4_complexity_percentage = (WORD32)(
2694                         (ps_curr_out->i8_acc_num_blks_high_sad * 100) /
2695                         (ps_curr_out->i8_total_blks));
2696                 }
2697                 /*not for Const QP mode*/
2698                 if(ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode != 3)
2699                 {
2700                     if(ps_curr_inp->s_lap_out.i4_is_prev_pic_in_Tid0_same_scene &&
2701                        ps_curr_out->i8_total_blks &&
2702                        (((float)(ps_curr_out->i8_acc_num_blks_high_sad * 100) /
2703                          (ps_curr_out->i8_total_blks)) > (i4_cmplx_change_detection_thrsh)))
2704                     {
2705                         ps_curr_out->i4_is_high_complex_region = 1;
2706                     }
2707                     else
2708                     {
2709                         ps_curr_out->i4_is_high_complex_region = 0;
2710                     }
2711                 }
2712                 ps_curr_inp->s_rc_lap_out.i8_frame_acc_coarse_me_cost =
2713                     ps_curr_out->i8_acc_frame_coarse_me_cost;
2714                 /*check for I only reset case and Non I SCD*/
2715                 ihevce_rc_check_non_lap_scd(
2716                     ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0], &ps_curr_inp->s_rc_lap_out);
2717             }
2718         }
2719         /* release mutex lock after rate control calls */
2720         osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
2721     }
2722 }
2723 
2724 /*!
2725 ******************************************************************************
2726 * \if Function name : ihevce_frame_init \endif
2727 *
2728 * \brief
2729 *    Pre encode Frame processing slave thread entry point function
2730 *
2731 * \param[in] Frame processing thread context pointer
2732 *
2733 * \return
2734 *    None
2735 *
2736 * \author
2737 *  Ittiam
2738 *
2739 *****************************************************************************
2740 */
ihevce_frame_init(enc_ctxt_t * ps_enc_ctxt,pre_enc_me_ctxt_t * ps_curr_inp_prms,me_enc_rdopt_ctxt_t * ps_cur_out_me_prms,WORD32 i4_cur_frame_qp,WORD32 i4_me_frm_id,WORD32 i4_thrd_id)2741 void ihevce_frame_init(
2742     enc_ctxt_t *ps_enc_ctxt,
2743     pre_enc_me_ctxt_t *ps_curr_inp_prms,
2744     me_enc_rdopt_ctxt_t *ps_cur_out_me_prms,
2745     WORD32 i4_cur_frame_qp,
2746     WORD32 i4_me_frm_id,
2747     WORD32 i4_thrd_id)
2748 {
2749     ihevce_lap_enc_buf_t *ps_curr_inp;
2750     WORD32 first_field = 1;
2751     me_master_ctxt_t *ps_master_ctxt;
2752 
2753     (void)i4_thrd_id;
2754     (void)ps_cur_out_me_prms;
2755     ps_curr_inp = ps_curr_inp_prms->ps_curr_inp;
2756 
2757     ps_master_ctxt = (me_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_me_ctxt;
2758 
2759     /* get frame level lambda params */
2760     ihevce_get_frame_lambda_prms(
2761         ps_enc_ctxt,
2762         ps_curr_inp_prms,
2763         i4_cur_frame_qp,
2764         first_field,
2765         ps_curr_inp->s_lap_out.i4_is_ref_pic,
2766         ps_curr_inp->s_lap_out.i4_temporal_lyr_id,
2767         ps_curr_inp->s_lap_out.f_i_pic_lamda_modifier,
2768         0,
2769         ENC_LAMBDA_TYPE);
2770 
2771     if(1 == ps_curr_inp_prms->i4_frm_proc_valid_flag)
2772     {
2773         UWORD8 i1_cu_qp_delta_enabled_flag =
2774             ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_cu_level_rc;
2775 
2776         /* picture level init of ME */
2777         ihevce_me_frame_init(
2778             ps_enc_ctxt->s_module_ctxt.pv_me_ctxt,
2779             ps_cur_out_me_prms,
2780             ps_enc_ctxt->ps_stat_prms,
2781             &ps_enc_ctxt->s_frm_ctb_prms,
2782             &ps_curr_inp_prms->as_lambda_prms[0],
2783             ps_enc_ctxt->i4_num_ref_l0,
2784             ps_enc_ctxt->i4_num_ref_l1,
2785             ps_enc_ctxt->i4_num_ref_l0_active,
2786             ps_enc_ctxt->i4_num_ref_l1_active,
2787             &ps_cur_out_me_prms->aps_ref_list[0][LIST_0][0],
2788             &ps_cur_out_me_prms->aps_ref_list[0][LIST_1][0],
2789             ps_cur_out_me_prms->aps_ref_list[0],
2790             &ps_enc_ctxt->s_func_selector,
2791             ps_curr_inp,
2792             ps_curr_inp_prms->pv_me_lyr_ctxt,
2793             i4_me_frm_id,
2794             i4_thrd_id,
2795             i4_cur_frame_qp,
2796             ps_curr_inp->s_lap_out.i4_temporal_lyr_id,
2797             i1_cu_qp_delta_enabled_flag,
2798             ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id]->pv_dep_mngr_encloop_dep_me);
2799 
2800         /* -------------------------------------------------------- */
2801         /* Preparing Job Queue for ME and each instance of enc_loop */
2802         /* -------------------------------------------------------- */
2803         ihevce_prepare_job_queue(ps_enc_ctxt, ps_curr_inp, i4_me_frm_id);
2804 
2805         /* Dep. Mngr : Reset the num ctb processed in every row  for ENC sync */
2806         ihevce_dmgr_rst_row_row_sync(
2807             ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id]->pv_dep_mngr_encloop_dep_me);
2808     }
2809 }
2810 
2811 /****************************************************************************
2812 Function Name : ihevce_rc_close
2813 Description   : closing the Rate control by passing the stored data in to the stat file for 2 pass encoding.
2814 Inputs        :
2815 Globals       :
2816 Processing    :
2817 Outputs       :
2818 Returns       :
2819 Issues        :
2820 Revision History:
2821 DD MM YYYY   Author(s)       Changes (Describe the changes made)
2822 *****************************************************************************/
2823 
ihevce_rc_close(enc_ctxt_t * ps_enc_ctxt,WORD32 i4_enc_frm_id_rc,WORD32 i4_store_retrive,WORD32 i4_update_cnt,WORD32 i4_bit_rate_idx)2824 void ihevce_rc_close(
2825     enc_ctxt_t *ps_enc_ctxt,
2826     WORD32 i4_enc_frm_id_rc,
2827     WORD32 i4_store_retrive,
2828     WORD32 i4_update_cnt,
2829     WORD32 i4_bit_rate_idx)
2830 {
2831     rc_bits_sad_t s_rc_frame_stat;
2832     WORD32 out_buf_id;
2833     WORD32 i4_pic_type, k;
2834     WORD32 cur_qp;
2835     ihevce_lap_output_params_t s_lap_out;
2836     rc_lap_out_params_t s_rc_lap_out;
2837 
2838     for(k = 0; k < i4_update_cnt; k++)  //ELP_RC
2839     {
2840         ihevce_rc_store_retrive_update_info(
2841             (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i4_bit_rate_idx],
2842             &s_rc_frame_stat,
2843             i4_enc_frm_id_rc,
2844             i4_bit_rate_idx,
2845             2,
2846             &out_buf_id,
2847             &i4_pic_type,
2848             &cur_qp,
2849             (void *)&s_lap_out,
2850             (void *)&s_rc_lap_out);
2851 
2852         ihevce_rc_update_pic_info(
2853             (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i4_bit_rate_idx],
2854             (s_rc_frame_stat.u4_total_texture_bits +
2855              s_rc_frame_stat.u4_total_header_bits),  //pass total bits
2856             s_rc_frame_stat.u4_total_header_bits,
2857             s_rc_frame_stat.u4_total_sad,
2858             s_rc_frame_stat.u4_total_intra_sad,
2859             (IV_PICTURE_CODING_TYPE_T)i4_pic_type,
2860             cur_qp,
2861             0,
2862             s_rc_frame_stat.i4_qp_normalized_8x8_cu_sum,
2863             s_rc_frame_stat.i4_8x8_cu_sum,
2864             s_rc_frame_stat.i8_sad_by_qscale,
2865             &s_lap_out,
2866             &s_rc_lap_out,
2867             out_buf_id,
2868             s_rc_frame_stat.u4_open_loop_intra_sad,
2869             s_rc_frame_stat.i8_total_ssd_frame,
2870             i4_enc_frm_id_rc);  //ps_curr_out->i4_inp_timestamp_low)
2871         i4_enc_frm_id_rc++;
2872         i4_enc_frm_id_rc = (i4_enc_frm_id_rc % ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc);
2873     }
2874 }
2875 
2876 /*!
2877 ******************************************************************************
2878 * \if Function name : ihevce_enc_frm_proc_slave_thrd \endif
2879 *
2880 * \brief
2881 *    Enocde Frame processing slave thread entry point function
2882 *
2883 * \param[in] Frame processing thread context pointer
2884 *
2885 * \return
2886 *    None
2887 *
2888 * \author
2889 *  Ittiam
2890 *
2891 *****************************************************************************
2892 */
ihevce_enc_frm_proc_slave_thrd(void * pv_frm_proc_thrd_ctxt)2893 WORD32 ihevce_enc_frm_proc_slave_thrd(void *pv_frm_proc_thrd_ctxt)
2894 {
2895     frm_proc_thrd_ctxt_t *ps_thrd_ctxt;
2896     enc_ctxt_t *ps_enc_ctxt;
2897     WORD32 i4_me_end_flag, i4_enc_end_flag;
2898     WORD32 i4_thrd_id;
2899     ihevce_hle_ctxt_t *ps_hle_ctxt;
2900     WORD32 i4_num_bitrates;  //number of bit-rates instances running
2901     WORD32 i;  //ctr
2902     void *pv_dep_mngr_prev_frame_me_done;
2903     void *pv_dep_mngr_prev_frame_done;
2904     WORD32 i4_resolution_id;
2905     WORD32 i4_enc_frm_id_rc = 0;
2906     WORD32 i4_enc_frm_id = 0;
2907     WORD32 i4_me_frm_id = 0;
2908 
2909     ps_thrd_ctxt = (frm_proc_thrd_ctxt_t *)pv_frm_proc_thrd_ctxt;
2910     ps_hle_ctxt = ps_thrd_ctxt->ps_hle_ctxt;
2911     ps_enc_ctxt = (enc_ctxt_t *)ps_thrd_ctxt->pv_enc_ctxt; /*Changed for mres*/
2912     i4_thrd_id = ps_thrd_ctxt->i4_thrd_id;
2913     i4_me_end_flag = 0;
2914     i4_enc_end_flag = 0;
2915     i4_num_bitrates = ps_enc_ctxt->i4_num_bitrates;
2916     i4_resolution_id = ps_enc_ctxt->i4_resolution_id;
2917 
2918     /*pv_dep_mngr_prev_frame_me_done  =
2919         ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_me_done;*/
2920 
2921     while((0 == i4_me_end_flag) && (0 == i4_enc_end_flag))
2922     {
2923         WORD32 result;
2924         WORD32 ai4_in_buf_id[MAX_NUM_ME_PARALLEL];
2925         me_enc_rdopt_ctxt_t *ps_curr_out_me;
2926 
2927         if(1 == ps_enc_ctxt->s_multi_thrd.i4_num_me_frm_pllel)
2928         {
2929             pv_dep_mngr_prev_frame_me_done =
2930                 ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_prev_frame_me_done[0];
2931         }
2932         else
2933         {
2934             pv_dep_mngr_prev_frame_me_done =
2935                 ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_prev_frame_me_done[i4_me_frm_id];
2936         }
2937 
2938         /* Wait till the previous frame ME is completly done*/
2939         {
2940             ihevce_dmgr_chk_frm_frm_sync(pv_dep_mngr_prev_frame_me_done, ps_thrd_ctxt->i4_thrd_id);
2941         }
2942 
2943         /****** Lock the critical section ******/
2944         if(NULL != ps_enc_ctxt->s_multi_thrd.apv_mutex_handle[i4_me_frm_id])
2945         {
2946             result = osal_mutex_lock(ps_enc_ctxt->s_multi_thrd.apv_mutex_handle[i4_me_frm_id]);
2947 
2948             if(OSAL_SUCCESS != result)
2949                 return 0;
2950         }
2951 
2952         {
2953             /************************************/
2954             /****** ENTER CRITICAL SECTION ******/
2955             /************************************/
2956 
2957             /* First slave getting the mutex lock will act as master and does ME init
2958             * of current frame and other slaves skip it
2959             */
2960             if(ps_enc_ctxt->s_multi_thrd.ai4_me_master_done_flag[i4_me_frm_id] == 0)
2961             {
2962                 WORD32 i4_ref_cur_qp;  //current frame Qp for reference bit-rate instance
2963                 ihevce_lap_enc_buf_t *ps_curr_inp = NULL;
2964 
2965                 if(0 == i4_me_end_flag)
2966                 {
2967                     /* ------- get the input prms buffer from pre encode que ------------ */
2968                     ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id] =
2969                         (pre_enc_me_ctxt_t *)ihevce_q_get_filled_buff(
2970                             (void *)ps_enc_ctxt,
2971                             IHEVCE_PRE_ENC_ME_Q,
2972                             &ai4_in_buf_id[i4_me_frm_id],
2973                             BUFF_QUE_BLOCKING_MODE);
2974                     /*always buffer must be available*/
2975                     ASSERT(ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id] != NULL);
2976 
2977                     ps_enc_ctxt->s_multi_thrd.is_in_buf_freed[i4_enc_frm_id] = 0;
2978 
2979                     /* ------- get the input prms buffer from L0 IPE queue ------------ */
2980                     ps_enc_ctxt->s_multi_thrd.aps_cur_L0_ipe_inp_prms[i4_me_frm_id] =
2981                         (pre_enc_L0_ipe_encloop_ctxt_t *)ihevce_q_get_filled_buff(
2982                             (void *)ps_enc_ctxt,
2983                             IHEVCE_L0_IPE_ENC_Q,
2984                             &ps_enc_ctxt->s_multi_thrd.ai4_in_frm_l0_ipe_id[i4_me_frm_id],
2985                             BUFF_QUE_BLOCKING_MODE);
2986 
2987                     /*always buffer must be available*/
2988                     ASSERT(ps_enc_ctxt->s_multi_thrd.aps_cur_L0_ipe_inp_prms[i4_me_frm_id] != NULL);
2989 
2990                     /* ------- get the free buffer from me_enc que ------------ */
2991                     ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id] =
2992                         (me_enc_rdopt_ctxt_t *)ihevce_q_get_free_buff(
2993                             ps_enc_ctxt,
2994                             IHEVCE_ME_ENC_RDOPT_Q,
2995                             &ps_enc_ctxt->s_multi_thrd.ai4_me_out_buf_id[i4_me_frm_id],
2996                             BUFF_QUE_BLOCKING_MODE);
2997 
2998                     /*always buffer must be available*/
2999                     ASSERT(ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id] != NULL);
3000                 }
3001                 if(NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id] &&
3002                    NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id] &&
3003                    NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_L0_ipe_inp_prms[i4_me_frm_id])
3004                 {
3005                     ps_curr_inp =
3006                         ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->ps_curr_inp;
3007 
3008                     ps_curr_out_me = ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id];
3009 
3010                     ps_curr_out_me->ps_curr_inp_from_l0_ipe_prms =
3011                         ps_enc_ctxt->s_multi_thrd.aps_cur_L0_ipe_inp_prms[i4_me_frm_id];
3012 
3013                     /*initialization of curr out me*/
3014                     ps_curr_out_me->ps_curr_inp_from_me_prms =
3015                         ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id];
3016 
3017                     ps_curr_out_me->curr_inp_from_me_buf_id = ai4_in_buf_id[i4_me_frm_id];
3018 
3019                     ps_curr_out_me->i4_buf_id =
3020                         ps_enc_ctxt->s_multi_thrd.ai4_me_out_buf_id[i4_me_frm_id];
3021 
3022                     ps_curr_out_me->ps_curr_inp =
3023                         ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->ps_curr_inp;
3024 
3025                     ps_curr_out_me->curr_inp_buf_id =
3026                         ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->curr_inp_buf_id;
3027 
3028                     ps_curr_out_me->curr_inp_from_l0_ipe_buf_id =
3029                         ps_enc_ctxt->s_multi_thrd.ai4_in_frm_l0_ipe_id[i4_me_frm_id];
3030 
3031                     ps_curr_out_me->i4_frm_proc_valid_flag =
3032                         ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]
3033                             ->i4_frm_proc_valid_flag;
3034 
3035                     ps_curr_out_me->i4_end_flag =
3036                         ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->i4_end_flag;
3037 
3038                     /* do the processing if input frm data is valid */
3039                     if(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag)
3040                     {
3041                         /* slice header will be populated in pre-enocde stage */
3042                         memcpy(
3043                             &ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id]
3044                                  ->s_slice_hdr,
3045                             &ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]
3046                                  ->s_slice_hdr,
3047                             sizeof(slice_header_t));
3048 
3049                         if(ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]
3050                                ->i4_frm_proc_valid_flag)
3051                         {
3052                             WORD32 ctr;
3053                             recon_pic_buf_t *ps_frm_recon;
3054                             for(i = 0; i < i4_num_bitrates; i++)
3055                             {
3056                                 /* run a loop to free the non used reference pics */
3057                                 /* This is done here because its assured that recon buf
3058                                 * between app and encode loop is set as produced
3059                                 */
3060                                 {
3061                                     WORD32 i4_free_id;
3062                                     i4_free_id = ihevce_find_free_indx(
3063                                         ps_enc_ctxt->pps_recon_buf_q[i],
3064                                         ps_enc_ctxt->ai4_num_buf_recon_q[i]);
3065 
3066                                     if(i4_free_id != -1)
3067                                     {
3068                                         ps_enc_ctxt->pps_recon_buf_q[i][i4_free_id]->i4_is_free = 1;
3069                                         ps_enc_ctxt->pps_recon_buf_q[i][i4_free_id]->i4_poc = -1;
3070                                     }
3071                                 }
3072 
3073                                 ps_frm_recon = NULL;
3074                                 for(ctr = 0; ctr < ps_enc_ctxt->ai4_num_buf_recon_q[i]; ctr++)
3075                                 {
3076                                     if(ps_enc_ctxt->pps_recon_buf_q[i][ctr]->i4_is_free)
3077                                     {
3078                                         ps_frm_recon = ps_enc_ctxt->pps_recon_buf_q[i][ctr];
3079                                         break;
3080                                     }
3081                                 }
3082                                 ASSERT(ps_frm_recon != NULL);
3083 
3084                                 ps_frm_recon->i4_is_free = 0;
3085                                 ps_frm_recon->i4_non_ref_free_flag = 0;
3086                                 ps_frm_recon->i4_topfield_first =
3087                                     ps_curr_inp->s_input_buf.i4_topfield_first;
3088                                 ps_frm_recon->i4_poc = ps_curr_inp->s_lap_out.i4_poc;
3089                                 ps_frm_recon->i4_pic_type = ps_curr_inp->s_lap_out.i4_pic_type;
3090                                 ps_frm_recon->i4_display_num =
3091                                     ps_curr_inp->s_lap_out.i4_display_num;
3092                                 ps_frm_recon->i4_idr_gop_num =
3093                                     ps_curr_inp->s_lap_out.i4_idr_gop_num;
3094                                 ps_frm_recon->i4_bottom_field =
3095                                     ps_curr_inp->s_input_buf.i4_bottom_field;
3096                                 ps_frm_recon->i4_is_reference =
3097                                     ps_curr_inp->s_lap_out.i4_is_ref_pic;
3098 
3099                                 {
3100                                     WORD32 sei_hash_enabled;
3101 #ifndef DISABLE_SEI
3102                                     sei_hash_enabled = (ps_enc_ctxt->ps_stat_prms->s_out_strm_prms
3103                                              .i4_sei_enable_flag == 1) &&
3104                                         (ps_enc_ctxt->ps_stat_prms->s_out_strm_prms
3105                                              .i4_decoded_pic_hash_sei_flag != 0);
3106 #else
3107                                     sei_hash_enabled = 0;
3108 #endif
3109                                     /* Deblock a picture for all reference frames unconditionally. */
3110                                     /* Deblock non ref if psnr compute or save recon is enabled    */
3111                                     ps_frm_recon->i4_deblk_pad_hpel_cur_pic =
3112                                         ps_frm_recon->i4_is_reference ||
3113                                         (ps_enc_ctxt->ps_stat_prms->i4_save_recon) ||
3114                                         (1 == sei_hash_enabled);
3115                                 }
3116 
3117                                 ps_frm_recon->s_yuv_buf_desc.i4_y_ht =
3118                                     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht;
3119                                 ps_frm_recon->s_yuv_buf_desc.i4_uv_ht =
3120                                     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht >>
3121                                     ((ps_enc_ctxt->s_runtime_src_prms.i4_chr_format ==
3122                                       IV_YUV_422SP_UV)
3123                                          ? 0
3124                                          : 1);
3125                                 ps_frm_recon->s_yuv_buf_desc.i4_y_wd =
3126                                     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd;
3127                                 ps_frm_recon->s_yuv_buf_desc.i4_uv_wd =
3128                                     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd;
3129                                 ps_frm_recon->s_yuv_buf_desc.i4_y_strd =
3130                                     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd +
3131                                     (PAD_HORZ << 1);
3132                                 ps_frm_recon->s_yuv_buf_desc.i4_uv_strd =
3133                                     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd +
3134                                     (PAD_HORZ << 1);
3135 
3136                                 /* reset the row_frm dep mngr for ME reverse sync for reference bitrate */
3137                                 if(i == 0)
3138                                 {
3139                                     ihevce_dmgr_map_rst_sync(ps_frm_recon->pv_dep_mngr_recon);
3140                                 }
3141 
3142                                 ps_enc_ctxt->s_multi_thrd.ps_frm_recon[i4_enc_frm_id][i] =
3143                                     ps_frm_recon;
3144                             }
3145                         }
3146                         /* Reference buffer management and reference list creation */
3147                         /* This needs to be created for each bit-rate since the reconstructed output is
3148                         different for all bit-rates. ME uses only 0th instnace ref list */
3149                         for(i = i4_num_bitrates - 1; i >= 0; i--)
3150                         {
3151                             ihevce_manage_ref_pics(
3152                                 ps_enc_ctxt,
3153                                 ps_curr_inp,
3154                                 &ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id]
3155                                      ->s_slice_hdr,
3156                                 i4_me_frm_id,
3157                                 i4_thrd_id,
3158                                 i); /* bitrate instance ID */
3159                         }
3160                         /*query of qp to be moved just before encoding starts*/
3161                         i4_ref_cur_qp = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]
3162                                             ->i4_curr_frm_qp;
3163                         /* The Qp populated in Pre enc stage needs to overwritten with Qp
3164                         queried from rate control*/
3165                     }
3166                     else
3167                     {
3168                         i4_ref_cur_qp = 0;
3169                     }
3170 
3171                     /* call the core encoding loop */
3172                     ihevce_frame_init(
3173                         ps_enc_ctxt,
3174                         ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id],
3175                         ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id],
3176                         i4_ref_cur_qp,
3177                         i4_me_frm_id,
3178                         i4_thrd_id);
3179                 }
3180 
3181                 ps_enc_ctxt->s_multi_thrd.ai4_me_master_done_flag[i4_me_frm_id] = 1;
3182             }
3183         }
3184 
3185         /************************************/
3186         /******  EXIT CRITICAL SECTION ******/
3187         /************************************/
3188 
3189         /****** Unlock the critical section ******/
3190         if(NULL != ps_enc_ctxt->s_multi_thrd.apv_mutex_handle[i4_me_frm_id])
3191         {
3192             result = osal_mutex_unlock(ps_enc_ctxt->s_multi_thrd.apv_mutex_handle[i4_me_frm_id]);
3193             if(OSAL_SUCCESS != result)
3194                 return 0;
3195         }
3196 
3197         if((1 == ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.i4_mres_single_out) &&
3198            (1 == ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]
3199                      ->ps_curr_inp->s_lap_out.i4_first_frm_new_res))
3200         {
3201             /* Reset the enc frame rc id whenver change in resolution happens */
3202             i4_enc_frm_id_rc = 0;
3203         }
3204 
3205         /*update end flag for each thread */
3206         i4_me_end_flag = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->i4_end_flag;
3207         if(NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id] &&
3208            NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id] &&
3209            NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_L0_ipe_inp_prms[i4_me_frm_id])
3210         {
3211             pre_enc_me_ctxt_t *ps_curr_inp_prms;
3212             pre_enc_L0_ipe_encloop_ctxt_t *ps_curr_L0_IPE_inp_prms;
3213             ihevce_lap_enc_buf_t *ps_curr_inp;
3214 
3215             /* get the current  buffer pointer  */
3216             ps_curr_inp_prms = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id];
3217             ps_curr_L0_IPE_inp_prms =
3218                 ps_enc_ctxt->s_multi_thrd.aps_cur_L0_ipe_inp_prms[i4_me_frm_id];
3219             ps_curr_inp = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->ps_curr_inp;
3220             if(i4_thrd_id == 0)
3221             {
3222                 PROFILE_START(&ps_hle_ctxt->profile_enc_me[ps_enc_ctxt->i4_resolution_id]);
3223             }
3224 
3225             /* -------------------------------------------------- */
3226             /*    Motion estimation (enc layer) of entire frame   */
3227             /* -------------------------------------------------- */
3228             if((i4_me_end_flag == 0) &&
3229                (1 ==
3230                 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->i4_frm_proc_valid_flag))
3231             {
3232                 /* Init i4_is_prev_frame_reference for the next P-frame */
3233                 me_master_ctxt_t *ps_master_ctxt =
3234                     (me_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_me_ctxt;
3235 
3236                 /* get the current thread ctxt pointer */
3237                 me_ctxt_t *ps_ctxt = ps_master_ctxt->aps_me_ctxt[i4_thrd_id];
3238 
3239                 me_frm_ctxt_t *ps_frm_ctxt = ps_ctxt->aps_me_frm_prms[i4_me_frm_id];
3240 
3241                 if(ISLICE != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]
3242                                  ->s_slice_hdr.i1_slice_type)
3243                 {
3244                     ihevce_me_process(
3245                         ps_enc_ctxt->s_module_ctxt.pv_me_ctxt,
3246                         ps_curr_inp,
3247                         ps_curr_inp_prms->ps_ctb_analyse,
3248                         ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id],
3249                         ps_curr_inp_prms->plf_intra_8x8_cost,
3250                         ps_curr_L0_IPE_inp_prms->ps_ipe_analyse_ctb,
3251                         ps_curr_L0_IPE_inp_prms,
3252                         ps_curr_inp_prms->pv_me_lyr_ctxt,
3253                         &ps_enc_ctxt->s_multi_thrd,
3254                         ((ps_enc_ctxt->s_multi_thrd.i4_num_me_frm_pllel == 1) ? 0 : 1),
3255                         i4_thrd_id,
3256                         i4_me_frm_id);
3257                 }
3258                 else
3259                 {
3260                     /* Init i4_is_prev_frame_reference for the next P-frame */
3261                     me_master_ctxt_t *ps_master_ctxt =
3262                         (me_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_me_ctxt;
3263 
3264                     /* get the current thread ctxt pointer */
3265                     me_ctxt_t *ps_ctxt = ps_master_ctxt->aps_me_ctxt[i4_thrd_id];
3266 
3267                     me_frm_ctxt_t *ps_frm_ctxt = ps_ctxt->aps_me_frm_prms[i4_me_frm_id];
3268 
3269                     multi_thrd_ctxt_t *ps_multi_thrd_ctxt = &ps_enc_ctxt->s_multi_thrd;
3270 
3271                     if(ps_enc_ctxt->s_multi_thrd.i4_num_me_frm_pllel != 1)
3272                     {
3273                         ps_frm_ctxt->i4_is_prev_frame_reference = 0;
3274                     }
3275                     else
3276                     {
3277                         ps_frm_ctxt->i4_is_prev_frame_reference =
3278                             ps_multi_thrd_ctxt->aps_cur_inp_me_prms[i4_me_frm_id]
3279                                 ->ps_curr_inp->s_lap_out.i4_is_ref_pic;
3280                     }
3281                 }
3282             }
3283             if(i4_thrd_id == 0)
3284             {
3285                 PROFILE_STOP(&ps_hle_ctxt->profile_enc_me[ps_enc_ctxt->i4_resolution_id], NULL);
3286             }
3287         }
3288         /************************************/
3289         /******  ENTER CRITICAL SECTION *****/
3290         /************************************/
3291         {
3292             WORD32 result_frame_init;
3293             void *pv_mutex_handle_frame_init;
3294 
3295             /* Create mutex for locking non-reentrant sections      */
3296             pv_mutex_handle_frame_init =
3297                 ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_me_end[i4_me_frm_id];
3298 
3299             /****** Lock the critical section ******/
3300             if(NULL != pv_mutex_handle_frame_init)
3301             {
3302                 result_frame_init = osal_mutex_lock(pv_mutex_handle_frame_init);
3303 
3304                 if(OSAL_SUCCESS != result_frame_init)
3305                     return 0;
3306             }
3307         }
3308 
3309         if(0 == ps_enc_ctxt->s_multi_thrd.ai4_me_enc_buff_prod_flag[i4_me_frm_id])
3310         {
3311             /* ------- set buffer produced from me_enc que ------------ */
3312             ihevce_q_set_buff_prod(
3313                 ps_enc_ctxt,
3314                 IHEVCE_ME_ENC_RDOPT_Q,
3315                 ps_enc_ctxt->s_multi_thrd.ai4_me_out_buf_id[i4_me_frm_id]);
3316 
3317             ps_enc_ctxt->s_multi_thrd.ai4_me_enc_buff_prod_flag[i4_me_frm_id] = 1;
3318         }
3319         if(NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id] &&
3320            NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id])
3321         {
3322             ihevce_lap_enc_buf_t *ps_curr_inp;
3323 
3324             WORD32 first_field = 1;
3325 
3326             /* Increment the counter to keep track of no of threads exiting the current mutex*/
3327             ps_enc_ctxt->s_multi_thrd.me_num_thrds_exited[i4_me_frm_id]++;
3328 
3329             ps_curr_inp = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->ps_curr_inp;
3330             /* Last slave thread will reset the master done frame init flag and set the prev
3331             * frame me done flag for curr frame
3332             */
3333             if(ps_enc_ctxt->s_multi_thrd.me_num_thrds_exited[i4_me_frm_id] ==
3334                ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds)
3335             {
3336                 ps_enc_ctxt->s_multi_thrd.me_num_thrds_exited[i4_me_frm_id] = 0;
3337 
3338                 ps_enc_ctxt->s_multi_thrd.ai4_me_master_done_flag[i4_me_frm_id] = 0;
3339 
3340                 /* Update Dyn. Vert. Search prms for P Pic. */
3341                 if(IV_P_FRAME == ps_curr_inp->s_lap_out.i4_pic_type)
3342                 {
3343                     WORD32 i4_idx_dvsr_p = ps_enc_ctxt->s_multi_thrd.i4_idx_dvsr_p;
3344                     /* Sanity Check */
3345                     ASSERT(ps_curr_inp->s_lap_out.i4_pic_type < IV_IP_FRAME);
3346 
3347                     /*  Frame END processing for Dynamic Vertival Search    */
3348                     ihevce_l0_me_frame_end(
3349                         ps_enc_ctxt->s_module_ctxt.pv_me_ctxt,
3350                         i4_idx_dvsr_p,
3351                         ps_curr_inp->s_lap_out.i4_display_num,
3352                         i4_me_frm_id);
3353 
3354                     ps_enc_ctxt->s_multi_thrd.i4_idx_dvsr_p++;
3355                     if(ps_enc_ctxt->s_multi_thrd.i4_idx_dvsr_p == NUM_SG_INTERLEAVED)
3356                     {
3357                         ps_enc_ctxt->s_multi_thrd.i4_idx_dvsr_p = 0;
3358                     }
3359                 }
3360                 if(1 == ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]
3361                             ->i4_frm_proc_valid_flag)
3362                 {
3363                     /* Init i4_is_prev_frame_reference for the next P-frame */
3364                     me_master_ctxt_t *ps_master_ctxt =
3365                         (me_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_me_ctxt;
3366 
3367                     /* get the current thread ctxt pointer */
3368                     me_ctxt_t *ps_ctxt = ps_master_ctxt->aps_me_ctxt[i4_thrd_id];
3369 
3370                     me_frm_ctxt_t *ps_frm_ctxt = ps_ctxt->aps_me_frm_prms[i4_me_frm_id];
3371 
3372                     ps_frm_ctxt->ps_curr_descr->aps_layers[0]->i4_non_ref_free = 1;
3373                 }
3374                 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id] = NULL;
3375                 ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id] = NULL;
3376                 ps_enc_ctxt->s_multi_thrd.aps_cur_L0_ipe_inp_prms[i4_me_frm_id] = NULL;
3377                 ps_enc_ctxt->s_multi_thrd.ai4_me_enc_buff_prod_flag[i4_me_frm_id] = 0;
3378                 ps_enc_ctxt->s_multi_thrd.ai4_me_master_done_flag[i4_me_frm_id] = 0;
3379 
3380                 /* Set me processing done for curr frame in the dependency manager */
3381                 ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_me_done);
3382             }
3383         }
3384         /************************************/
3385         /******  EXIT CRITICAL SECTION ******/
3386         /************************************/
3387 
3388         {
3389             void *pv_mutex_handle_frame_init;
3390 
3391             /* Create mutex for locking non-reentrant sections      */
3392             pv_mutex_handle_frame_init =
3393                 ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_me_end[i4_me_frm_id];
3394             /****** Unlock the critical section ******/
3395             if(NULL != pv_mutex_handle_frame_init)
3396             {
3397                 result = osal_mutex_unlock(pv_mutex_handle_frame_init);
3398                 if(OSAL_SUCCESS != result)
3399                     return 0;
3400             }
3401         }
3402         /* -------------------------------------------- */
3403         /*        Encode Loop of entire frame           */
3404         /* -------------------------------------------- */
3405         ASSERT(ps_enc_ctxt->s_multi_thrd.i4_num_enc_loop_frm_pllel <= MAX_NUM_ENC_LOOP_PARALLEL);
3406 
3407         if(1 == ps_enc_ctxt->s_multi_thrd.i4_num_enc_loop_frm_pllel)
3408         {
3409             pv_dep_mngr_prev_frame_done = ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_prev_frame_done[0];
3410         }
3411         else
3412         {
3413             pv_dep_mngr_prev_frame_done =
3414                 ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_prev_frame_done[i4_enc_frm_id];
3415         }
3416         /* Wait till the prev frame enc loop is completed*/
3417         {
3418             ihevce_dmgr_chk_frm_frm_sync(pv_dep_mngr_prev_frame_done, ps_thrd_ctxt->i4_thrd_id);
3419         }
3420 
3421         /************************************/
3422         /****** ENTER CRITICAL SECTION ******/
3423         /************************************/
3424         {
3425             WORD32 result_frame_init;
3426             void *pv_mutex_handle_frame_init;
3427 
3428             /* Create mutex for locking non-reentrant sections      */
3429             pv_mutex_handle_frame_init =
3430                 ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_frame_init[i4_enc_frm_id];
3431 
3432             /****** Lock the critical section ******/
3433             if(NULL != pv_mutex_handle_frame_init)
3434             {
3435                 result_frame_init = osal_mutex_lock(pv_mutex_handle_frame_init);
3436 
3437                 if(OSAL_SUCCESS != result_frame_init)
3438                     return 0;
3439             }
3440         }
3441 
3442         {
3443             ihevce_lap_enc_buf_t *ps_curr_inp = NULL;
3444             pre_enc_me_ctxt_t *ps_curr_inp_from_me = NULL;
3445             me_enc_rdopt_ctxt_t *ps_curr_inp_enc = NULL;
3446             pre_enc_L0_ipe_encloop_ctxt_t *ps_curr_L0_IPE_inp_prms = NULL;
3447             recon_pic_buf_t *(*aps_ref_list)[HEVCE_MAX_REF_PICS * 2];
3448             WORD32 ai4_cur_qp[IHEVCE_MAX_NUM_BITRATES] = { 0 };
3449             WORD32 i4_field_pic = ps_enc_ctxt->s_runtime_src_prms.i4_field_pic;
3450             WORD32 first_field = 1;
3451             WORD32 result_frame_init;
3452             void *pv_mutex_handle_frame_init;
3453 
3454             /* Create mutex for locking non-reentrant sections      */
3455             pv_mutex_handle_frame_init =
3456                 ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_frame_init[i4_enc_frm_id];
3457 
3458             //aquire and initialize -> output and recon buffers
3459             if(ps_enc_ctxt->s_multi_thrd.enc_master_done_frame_init[i4_enc_frm_id] == 0)
3460             {
3461                 WORD32
3462                     i4_bitrate_ctr;  //bit-rate instance counter (for loop variable) [0->reference bit-rate, 1,2->auxiliarty bit-rates]
3463                 /* ------- get the input prms buffer from me que ------------ */
3464                 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] =
3465                     (me_enc_rdopt_ctxt_t *)ihevce_q_get_filled_buff(
3466                         ps_enc_ctxt,
3467                         IHEVCE_ME_ENC_RDOPT_Q,
3468                         &ps_enc_ctxt->s_multi_thrd.i4_enc_in_buf_id[i4_enc_frm_id],
3469                         BUFF_QUE_BLOCKING_MODE);
3470                 i4_enc_end_flag =
3471                     ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]->i4_end_flag;
3472 
3473                 ASSERT(ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] != NULL);
3474 
3475                 if(ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] != NULL)
3476                 {
3477                     ps_curr_inp =
3478                         ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]->ps_curr_inp;
3479                     ps_curr_inp_from_me =
3480                         ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3481                             ->ps_curr_inp_from_me_prms;
3482                     ps_curr_inp_enc = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id];
3483                     ps_curr_L0_IPE_inp_prms =
3484                         ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3485                             ->ps_curr_inp_from_l0_ipe_prms;
3486 
3487                     for(i4_bitrate_ctr = 0; i4_bitrate_ctr < i4_num_bitrates; i4_bitrate_ctr++)
3488                     {
3489                         iv_enc_recon_data_buffs_t
3490                             *ps_recon_out[MAX_NUM_ENC_LOOP_PARALLEL][IHEVCE_MAX_NUM_BITRATES] = {
3491                                 { NULL }
3492                             };
3493                         frm_proc_ent_cod_ctxt_t *ps_curr_out[MAX_NUM_ENC_LOOP_PARALLEL]
3494                                                             [IHEVCE_MAX_NUM_BITRATES] = { { NULL } };
3495 
3496                         /* ------- get free output buffer from Frame buffer que ---------- */
3497                         /* There is a separate queue for each bit-rate instnace. The output
3498                     buffer is acquired from the corresponding queue based on the
3499                     bitrate instnace */
3500                         ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr] =
3501                             (frm_proc_ent_cod_ctxt_t *)ihevce_q_get_free_buff(
3502                                 (void *)ps_enc_ctxt,
3503                                 IHEVCE_FRM_PRS_ENT_COD_Q +
3504                                     i4_bitrate_ctr, /*decides the buffer queue */
3505                                 &ps_enc_ctxt->s_multi_thrd.out_buf_id[i4_enc_frm_id][i4_bitrate_ctr],
3506                                 BUFF_QUE_BLOCKING_MODE);
3507                         ps_enc_ctxt->s_multi_thrd.is_out_buf_freed[i4_enc_frm_id][i4_bitrate_ctr] =
3508                             0;
3509                         ps_enc_ctxt->s_multi_thrd
3510                             .ps_curr_out_enc_grp[i4_enc_frm_id][i4_bitrate_ctr] =
3511                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr];
3512                         //ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_enc_order_num = ps_curr_inp->s_lap_out.i4_enc_order_num;
3513                         /*registered User Data Call*/
3514 #ifndef DISABLE_SEI
3515                         if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_payload_enable_flag)
3516                         {
3517                             ihevce_fill_sei_payload(
3518                                 ps_enc_ctxt,
3519                                 ps_curr_inp,
3520                                 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]);
3521                         }
3522 
3523 #endif
3524                         /*derive end flag and input valid flag in output buffer */
3525                         if(NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id])
3526                         {
3527                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_end_flag =
3528                                 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3529                                     ->i4_end_flag;
3530                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_frm_proc_valid_flag =
3531                                 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3532                                     ->i4_frm_proc_valid_flag;
3533 
3534                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_out_flush_flag =
3535                                 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3536                                     ->ps_curr_inp->s_lap_out.i4_out_flush_flag;
3537                         }
3538 
3539                         /*derive other parameters in output buffer */
3540                         if(NULL != ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr] &&
3541                            (NULL != ps_curr_inp_from_me) &&
3542                            (1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag) &&
3543                            (i4_enc_end_flag == 0))
3544                         {
3545                             /* copy the time stamps from inp to entropy inp */
3546                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_inp_timestamp_low =
3547                                 ps_curr_inp_from_me->i4_inp_timestamp_low;
3548                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_inp_timestamp_high =
3549                                 ps_curr_inp_from_me->i4_inp_timestamp_high;
3550                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->pv_app_frm_ctxt =
3551                                 ps_curr_inp_from_me->pv_app_frm_ctxt;
3552 
3553                             /*copy slice header params from temp structure to output buffer */
3554                             memcpy(
3555                                 &ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->s_slice_hdr,
3556                                 &ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3557                                      ->s_slice_hdr,
3558                                 sizeof(slice_header_t));
3559 
3560                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]
3561                                 ->s_slice_hdr.pu4_entry_point_offset =
3562                                 &ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]
3563                                      ->ai4_entry_point_offset[0];
3564 
3565                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_slice_nal_type =
3566                                 ps_curr_inp_from_me->i4_slice_nal_type;
3567 
3568                             /* populate sps, vps and pps pointers for the entropy input params */
3569                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->ps_pps =
3570                                 &ps_enc_ctxt->as_pps[i4_bitrate_ctr];
3571                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->ps_sps =
3572                                 &ps_enc_ctxt->as_sps[i4_bitrate_ctr];
3573                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->ps_vps =
3574                                 &ps_enc_ctxt->as_vps[i4_bitrate_ctr];
3575 
3576 #ifndef DISABLE_SEI
3577                             /* SEI header will be populated in pre-enocde stage */
3578                             memcpy(
3579                                 &ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->s_sei,
3580                                 &ps_curr_inp_from_me->s_sei,
3581                                 sizeof(sei_params_t));
3582 
3583 #endif
3584                             /*AUD and EOS presnt flags are populated*/
3585                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i1_aud_present_flag =
3586                                 ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_aud_enable_flags;
3587 
3588                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i1_eos_present_flag =
3589                                 ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_eos_enable_flags;
3590 
3591                             /* Information required for SEI Picture timing info */
3592                             {
3593                                 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_display_num =
3594                                     ps_curr_inp->s_lap_out.i4_display_num;
3595                             }
3596 
3597                             /* The Qp populated in Pre enc stage needs to overwritten with Qp
3598                         queried from rate control*/
3599                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]
3600                                 ->s_slice_hdr.i1_slice_qp_delta =
3601                                 (WORD8)ps_curr_inp_from_me->i4_curr_frm_qp -
3602                                 ps_enc_ctxt->as_pps[i4_bitrate_ctr].i1_pic_init_qp;
3603                         }
3604 
3605                         /* ------- get a filled descriptor from output Que ------------ */
3606                         if(/*(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag) &&*/
3607                            (ps_enc_ctxt->ps_stat_prms->i4_save_recon != 0))
3608                         {
3609                             /*swaping of buf_id for 0th and reference bitrate location, as encoder
3610                         assumes always 0th loc for reference bitrate and app must receive in
3611                         the configured order*/
3612                             WORD32 i4_recon_buf_id = i4_bitrate_ctr;
3613                             if(i4_bitrate_ctr == 0)
3614                             {
3615                                 i4_recon_buf_id = ps_enc_ctxt->i4_ref_mbr_id;
3616                             }
3617                             else if(i4_bitrate_ctr == ps_enc_ctxt->i4_ref_mbr_id)
3618                             {
3619                                 i4_recon_buf_id = 0;
3620                             }
3621 
3622                             /* ------- get free Recon buffer from Frame buffer que ---------- */
3623                             /* There is a separate queue for each bit-rate instnace. The recon
3624                         buffer is acquired from the corresponding queue based on the
3625                         bitrate instnace */
3626                             ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr] =
3627                                 (iv_enc_recon_data_buffs_t *)ihevce_q_get_filled_buff(
3628                                     (void *)ps_enc_ctxt,
3629                                     IHEVCE_RECON_DATA_Q +
3630                                         i4_recon_buf_id, /*decides the buffer queue */
3631                                     &ps_enc_ctxt->s_multi_thrd
3632                                          .recon_buf_id[i4_enc_frm_id][i4_bitrate_ctr],
3633                                     BUFF_QUE_BLOCKING_MODE);
3634 
3635                             ps_enc_ctxt->s_multi_thrd
3636                                 .is_recon_dumped[i4_enc_frm_id][i4_bitrate_ctr] = 0;
3637                             ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr] =
3638                                 ps_enc_ctxt->s_multi_thrd
3639                                     .ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr];
3640 
3641                             ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_end_flag =
3642                                 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3643                                     ->i4_end_flag;
3644                         }
3645 
3646                     }  //bitrate ctr
3647                 }
3648             }
3649             if(ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] != NULL)
3650             {
3651                 ps_curr_inp =
3652                     ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]->ps_curr_inp;
3653                 ps_curr_inp_from_me = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3654                                           ->ps_curr_inp_from_me_prms;
3655                 ps_curr_inp_enc = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id];
3656                 ps_curr_L0_IPE_inp_prms =
3657                     ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3658                         ->ps_curr_inp_from_l0_ipe_prms;
3659             }
3660             if((NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]) &&
3661                ((1 == ps_curr_inp_enc->i4_frm_proc_valid_flag) &&
3662                 (ps_enc_ctxt->s_multi_thrd.enc_master_done_frame_init[i4_enc_frm_id] == 0)))
3663             {
3664                 for(i = 0; i < i4_num_bitrates; i++)
3665                 {
3666                     aps_ref_list = ps_curr_inp_enc->aps_ref_list[i];
3667                     /* acquire mutex lock for rate control calls */
3668                     osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
3669 
3670                     /*utlize the satd data from pre enc stage to get more accurate estimate SAD for I pic*/
3671                     if(ps_curr_inp->s_lap_out.i4_pic_type == IV_I_FRAME ||
3672                        ps_curr_inp->s_lap_out.i4_pic_type == IV_IDR_FRAME)
3673                     {
3674                         ihevce_rc_update_cur_frm_intra_satd(
3675                             (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
3676                             ps_curr_inp_from_me->i8_frame_acc_satd_cost,
3677                             ps_enc_ctxt->i4_active_enc_frame_id);
3678                     }
3679 
3680                     /*pels assuming satd/act is obtained for entire frame*/
3681                     ps_curr_inp->s_rc_lap_out.i4_num_pels_in_frame_considered =
3682                         ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht *
3683                         ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd;
3684 
3685                     /*Service pending request to change average bitrate if any*/
3686                     {
3687                         LWORD64 i8_new_bitrate =
3688                             ihevce_rc_get_new_bitrate(ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0]);
3689                         LWORD64 i8_new_peak_bitrate = ihevce_rc_get_new_peak_bitrate(
3690                             ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0]);
3691                         ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3692                             ->i8_buf_level_bitrate_change = -1;
3693                         if((i8_new_bitrate != -1) &&
3694                            (i8_new_peak_bitrate != -1)) /*-1 indicates no pending request*/
3695                         {
3696                             LWORD64 buffer_level = ihevce_rc_change_avg_bitrate(
3697                                 ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0]);
3698                             ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3699                                 ->i8_buf_level_bitrate_change = buffer_level;
3700                         }
3701                     }
3702 
3703                     if((1 == ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.i4_mres_single_out) &&
3704                        (1 == ps_curr_inp->s_lap_out.i4_first_frm_new_res))
3705                     {
3706                         /* Whenver change in resolution happens change the buffer level */
3707                         ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3708                             ->i8_buf_level_bitrate_change = 0;
3709                     }
3710 #if 1  //KISH ELP
3711                     {
3712                         rc_bits_sad_t as_rc_frame_stat[IHEVCE_MAX_NUM_BITRATES];
3713 
3714                         if(ps_enc_ctxt->ai4_rc_query[i] ==
3715                            ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc)  //KISH
3716                         {
3717                             WORD32 out_buf_id[IHEVCE_MAX_NUM_BITRATES];
3718                             WORD32 i4_pic_type;
3719                             WORD32 cur_qp[IHEVCE_MAX_NUM_BITRATES];
3720                             ihevce_lap_output_params_t s_lap_out;
3721 
3722                             rc_lap_out_params_t s_rc_lap_out;
3723                             WORD32 i4_suppress_bpic_update;
3724 
3725                             ihevce_rc_store_retrive_update_info(
3726                                 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
3727                                 &as_rc_frame_stat[i],
3728                                 ps_enc_ctxt->i4_active_enc_frame_id,
3729                                 i,
3730                                 2,
3731                                 &out_buf_id[i],
3732                                 &i4_pic_type,
3733                                 &cur_qp[i],
3734                                 (void *)&s_lap_out,
3735                                 (void *)&s_rc_lap_out);
3736 
3737                             i4_suppress_bpic_update =
3738                                 (WORD32)(s_rc_lap_out.i4_rc_temporal_lyr_id > 1);
3739                             /*RC inter face update before update to happen only for ELP disabled */
3740                             if(1 == ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc)
3741                             {
3742                                 /* SGI & Enc Loop Parallelism related changes*/
3743                                 ihevce_rc_interface_update(
3744                                     (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
3745                                     (IV_PICTURE_CODING_TYPE_T)s_rc_lap_out.i4_rc_pic_type,
3746                                     &s_rc_lap_out,
3747                                     cur_qp[i],
3748                                     i4_enc_frm_id_rc);
3749                             }
3750 
3751                             ihevce_rc_update_pic_info(
3752                                 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
3753                                 (as_rc_frame_stat[i].u4_total_texture_bits +
3754                                  as_rc_frame_stat[i].u4_total_header_bits),  //pass total bits
3755                                 as_rc_frame_stat[i].u4_total_header_bits,
3756                                 as_rc_frame_stat[i].u4_total_sad,
3757                                 as_rc_frame_stat[i].u4_total_intra_sad,
3758                                 (IV_PICTURE_CODING_TYPE_T)i4_pic_type,
3759                                 cur_qp[i],
3760                                 i4_suppress_bpic_update,
3761                                 as_rc_frame_stat[i].i4_qp_normalized_8x8_cu_sum,
3762                                 as_rc_frame_stat[i].i4_8x8_cu_sum,
3763                                 as_rc_frame_stat[i].i8_sad_by_qscale,
3764                                 &s_lap_out,
3765                                 &s_rc_lap_out,
3766                                 out_buf_id[i],
3767                                 as_rc_frame_stat[i].u4_open_loop_intra_sad,
3768                                 as_rc_frame_stat[i].i8_total_ssd_frame,
3769                                 ps_enc_ctxt
3770                                     ->i4_active_enc_frame_id);  //ps_curr_out->i4_inp_timestamp_low)
3771 
3772                             //DBG_PRINTF("\n Sad = %d \t total bits = %d ", s_rc_frame_stat.u4_total_sad, (s_rc_frame_stat.u4_total_texture_bits + s_rc_frame_stat.u4_total_header_bits));
3773                             /*populate qp for pre enc*/
3774 
3775                             //g_count--;
3776                             ps_enc_ctxt->ai4_rc_query[i]--;
3777 
3778                             if(i == (i4_num_bitrates - 1))
3779                             {
3780                                 ihevce_rc_cal_pre_enc_qp(
3781                                     (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0]);
3782 
3783                                 ps_enc_ctxt->i4_active_enc_frame_id++;
3784                                 ps_enc_ctxt->i4_active_enc_frame_id =
3785                                     (ps_enc_ctxt->i4_active_enc_frame_id %
3786                                      ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc);
3787                             }
3788                         }
3789                     }
3790 #endif
3791                     if(ps_enc_ctxt->ai4_rc_query[i] < ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc)
3792                     {
3793                         /*HEVC_RC query rate control for qp*/
3794                         ai4_cur_qp[i] = ihevce_rc_get_pic_quant(
3795                             (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
3796                             &ps_curr_inp->s_rc_lap_out,
3797                             ENC_GET_QP,
3798                             i4_enc_frm_id_rc,
3799                             0,
3800                             &ps_curr_inp->s_lap_out.ai4_frame_bits_estimated[i]);
3801 
3802                         ps_curr_inp->s_rc_lap_out.i4_orig_rc_qp = ai4_cur_qp[i];
3803 
3804                         ps_enc_ctxt->s_multi_thrd.i4_in_frame_rc_enabled = 0;
3805                         ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3806                             ->i4_sub_pic_level_rc = 0;
3807                         ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3808                             ->ai4_frame_bits_estimated =
3809                             ps_curr_inp->s_lap_out.ai4_frame_bits_estimated[i];
3810 
3811                         {
3812                             ps_enc_ctxt->ai4_rc_query[i]++;
3813                         }
3814                     }
3815 
3816                     /* SGI & Enc Loop Parallelism related changes*/
3817                     ihevce_rc_interface_update(
3818                         (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
3819                         (IV_PICTURE_CODING_TYPE_T)ps_curr_inp->s_lap_out.i4_pic_type,
3820                         &ps_curr_inp->s_rc_lap_out,
3821                         ai4_cur_qp[i],
3822                         i4_enc_frm_id_rc);
3823 
3824                     //DBG_PRINTF("HEVC_QP = %d  MPEG2_QP = %d\n",cur_qp,gu1_HEVCToMpeg2Quant[cur_qp]);//i_model_print
3825 
3826                     /* release mutex lock after rate control calls */
3827                     osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
3828 
3829                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3830                         ->s_slice_hdr.i1_slice_qp_delta =
3831                         (WORD8)ai4_cur_qp[i] - ps_enc_ctxt->as_pps[i].i1_pic_init_qp;
3832 
3833                     ps_enc_ctxt->s_multi_thrd.cur_qp[i4_enc_frm_id][i] = ai4_cur_qp[i];
3834 
3835                     /* For interlace pictures, first_field depends on topfield_first and bottom field */
3836                     if(i4_field_pic)
3837                     {
3838                         first_field =
3839                             (ps_curr_inp->s_input_buf.i4_topfield_first ^
3840                              ps_curr_inp->s_input_buf.i4_bottom_field);
3841                     }
3842                     /* get frame level lambda params */
3843                     ihevce_get_frame_lambda_prms(
3844                         ps_enc_ctxt,
3845                         ps_curr_inp_from_me,
3846                         ai4_cur_qp[i],
3847                         first_field,
3848                         ps_curr_inp->s_lap_out.i4_is_ref_pic,
3849                         ps_curr_inp->s_lap_out.i4_temporal_lyr_id,
3850                         ps_curr_inp->s_lap_out.f_i_pic_lamda_modifier,
3851                         i,
3852                         ENC_LOOP_LAMBDA_TYPE);
3853 
3854 #if ADAPT_COLOCATED_FROM_L0_FLAG
3855                     ps_enc_ctxt->s_multi_thrd.ps_frm_recon[i4_enc_frm_id][i]->i4_frame_qp =
3856                         ai4_cur_qp[i];
3857 #endif
3858                 }  //bitrate counter ends
3859 
3860                 /* Reset the Dependency Mngrs local to EncLoop., ie CU_TopRight and Dblk */
3861                 ihevce_enc_loop_dep_mngr_frame_reset(
3862                     ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt, i4_enc_frm_id);
3863             }
3864 
3865             {
3866                 /*Set the master done flag for frame init so that other
3867                 * threads can skip it
3868                 */
3869                 ps_enc_ctxt->s_multi_thrd.enc_master_done_frame_init[i4_enc_frm_id] = 1;
3870             }
3871 
3872             /************************************/
3873             /******  EXIT CRITICAL SECTION ******/
3874             /************************************/
3875 
3876             /****** Unlock the critical section ******/
3877             if(NULL != pv_mutex_handle_frame_init)
3878             {
3879                 result_frame_init = osal_mutex_unlock(pv_mutex_handle_frame_init);
3880                 if(OSAL_SUCCESS != result_frame_init)
3881                     return 0;
3882             }
3883             ps_enc_ctxt->s_multi_thrd.i4_encode = 1;
3884             ps_enc_ctxt->s_multi_thrd.i4_num_re_enc = 0;
3885             /************************************/
3886             /******  Do Enc loop process   ******/
3887             /************************************/
3888             /* Each thread will run the enc-loop.
3889             Each thread will initialize it's own enc_loop context and do the processing.
3890             Each thread will run all the bit-rate instances one after another */
3891             if((i4_enc_end_flag == 0) &&
3892                (NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]) &&
3893                (1 == ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3894                          ->i4_frm_proc_valid_flag))
3895             {
3896                 while(1)
3897                 {
3898                     ctb_enc_loop_out_t *ps_ctb_enc_loop_frm[IHEVCE_MAX_NUM_BITRATES];
3899                     cu_enc_loop_out_t *ps_cu_enc_loop_frm[IHEVCE_MAX_NUM_BITRATES];
3900                     tu_enc_loop_out_t *ps_tu_frm[IHEVCE_MAX_NUM_BITRATES];
3901                     pu_t *ps_pu_frm[IHEVCE_MAX_NUM_BITRATES];
3902                     UWORD8 *pu1_frm_coeffs[IHEVCE_MAX_NUM_BITRATES];
3903                     me_master_ctxt_t *ps_master_me_ctxt =
3904                         (me_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_me_ctxt;
3905                     ihevce_enc_loop_master_ctxt_t *ps_master_ctxt =
3906                         (ihevce_enc_loop_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt;
3907 
3908                     for(i = 0; i < i4_num_bitrates; i++)
3909                     {
3910                         if(i4_thrd_id == 0)
3911                         {
3912                             PROFILE_START(
3913                                 &ps_hle_ctxt->profile_enc[ps_enc_ctxt->i4_resolution_id][i]);
3914                         }
3915                         if(NULL != ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id])
3916                         {
3917                             ps_ctb_enc_loop_frm[i] =
3918                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3919                                     ->ps_frm_ctb_data;
3920                             ps_cu_enc_loop_frm[i] =
3921                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3922                                     ->ps_frm_cu_data;
3923                             ps_tu_frm[i] =
3924                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3925                                     ->ps_frm_tu_data;
3926                             ps_pu_frm[i] =
3927                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3928                                     ->ps_frm_pu_data;
3929                             pu1_frm_coeffs[i] = (UWORD8 *)ps_enc_ctxt->s_multi_thrd
3930                                                     .ps_curr_out_enc_grp[i4_enc_frm_id][i]
3931                                                     ->pv_coeff_data;
3932                         }
3933                         /*derive reference picture list based on ping or pong instnace */
3934                         aps_ref_list = ps_curr_inp_enc->aps_ref_list[i];
3935 
3936                         /* Always consider chroma cost when computing cost for derived instance */
3937                         ps_master_ctxt->aps_enc_loop_thrd_ctxt[i4_thrd_id]->i4_consider_chroma_cost =
3938                             1;
3939 
3940                         /*************************
3941                         * MULTI BITRATE CODE START
3942                         **************************/
3943                         if(i4_num_bitrates > 1)
3944                         {
3945                             ihevce_mbr_quality_tool_set_configuration(
3946                                 ps_master_ctxt->aps_enc_loop_thrd_ctxt[i4_thrd_id],
3947                                 ps_enc_ctxt->ps_stat_prms);
3948                         }
3949                         /************************
3950                         * MULTI BITRATE CODE END
3951                         *************************/
3952                         /* picture level init of Encode loop module */
3953                         ihevce_enc_loop_frame_init(
3954                             ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt,
3955                             ps_enc_ctxt->s_multi_thrd.cur_qp[i4_enc_frm_id][i],
3956                             aps_ref_list,
3957                             ps_enc_ctxt->s_multi_thrd.ps_frm_recon[i4_enc_frm_id][i],
3958                             &ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3959                                  ->s_slice_hdr,
3960                             ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]->ps_pps,
3961                             ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]->ps_sps,
3962                             ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]->ps_vps,
3963                             ps_curr_inp_enc->ps_curr_inp->s_lap_out.i1_weighted_pred_flag,
3964                             ps_curr_inp_enc->ps_curr_inp->s_lap_out.i1_weighted_bipred_flag,
3965                             ps_curr_inp_enc->ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom,
3966                             ps_curr_inp_enc->ps_curr_inp->s_lap_out.i4_log2_chroma_wght_denom,
3967                             ps_curr_inp_enc->ps_curr_inp->s_lap_out.i4_poc,
3968                             ps_curr_inp_enc->ps_curr_inp->s_lap_out.i4_display_num,
3969                             ps_enc_ctxt,
3970                             ps_curr_inp_enc,
3971                             i,
3972                             i4_thrd_id,
3973                             i4_enc_frm_id,  // update this to enc_loop_ctxt struct
3974                             i4_num_bitrates,
3975                             ps_curr_inp_enc->ps_curr_inp->s_lap_out.i4_quality_preset,
3976                             ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3977                                 ->pv_dep_mngr_encloop_dep_me);
3978 
3979                         ihevce_enc_loop_process(
3980                             ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt,
3981                             ps_curr_inp,
3982                             ps_curr_inp_from_me->ps_ctb_analyse,
3983                             ps_curr_L0_IPE_inp_prms->ps_ipe_analyse_ctb,
3984                             ps_enc_ctxt->s_multi_thrd.ps_frm_recon[i4_enc_frm_id][i],
3985                             ps_curr_inp_enc->ps_cur_ctb_cu_tree,
3986                             ps_ctb_enc_loop_frm[i],
3987                             ps_cu_enc_loop_frm[i],
3988                             ps_tu_frm[i],
3989                             ps_pu_frm[i],
3990                             pu1_frm_coeffs[i],
3991                             &ps_enc_ctxt->s_frm_ctb_prms,
3992                             &ps_curr_inp_from_me->as_lambda_prms[i],
3993                             &ps_enc_ctxt->s_multi_thrd,
3994                             i4_thrd_id,
3995                             i4_enc_frm_id,
3996                             ps_enc_ctxt->ps_stat_prms->s_pass_prms.i4_pass);
3997                         if(i4_thrd_id == 0)
3998                         {
3999                             PROFILE_STOP(
4000                                 &ps_hle_ctxt->profile_enc[ps_enc_ctxt->i4_resolution_id][i], NULL);
4001                         }
4002                     }  //loop over bitrate ends
4003                     {
4004                         break;
4005                     }
4006                 } /*end of while(ps_enc_ctxt->s_multi_thrd.ai4_encode[i4_enc_frm_id] == 1)*/
4007             }
4008 
4009             /************************************/
4010             /****** ENTER CRITICAL SECTION ******/
4011             /************************************/
4012 
4013             /****** Lock the critical section ******/
4014             if(NULL != ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id])
4015             {
4016                 result = osal_mutex_lock(
4017                     ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id]);
4018 
4019                 if(OSAL_SUCCESS != result)
4020                     return 0;
4021             }
4022             if(ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] != NULL)
4023             {
4024                 /* Increment the counter to keep track of no of threads exiting the current mutex*/
4025                 ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id]++;
4026 
4027                 /* If the end frame is reached force the last slave to enter the next critical section*/
4028                 if(i4_enc_end_flag == 1)
4029                 {
4030                     if(ps_enc_ctxt->s_multi_thrd.num_thrds_done ==
4031                        ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds - 1)
4032                     {
4033                         ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id] =
4034                             ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds;
4035                     }
4036                 }
4037 
4038                 {
4039                     /*Last slave thread comming out of enc loop will execute next critical section*/
4040                     if(ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id] ==
4041                        ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds)
4042                     {
4043                         iv_enc_recon_data_buffs_t *ps_recon_out_temp = NULL;
4044                         recon_pic_buf_t *ps_frm_recon_temp = NULL;
4045                         ihevce_lap_enc_buf_t *ps_curr_inp;
4046                         rc_lap_out_params_t *ps_rc_lap_out_next_encode;
4047 
4048                         WORD32 ai4_act_qp[IHEVCE_MAX_NUM_BITRATES];
4049                         ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id] = 0;
4050 
4051                         ps_curr_inp = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
4052                                           ->ps_curr_inp;
4053 
4054                         for(i = 0; i < i4_num_bitrates; i++)
4055                         {
4056                             {
4057                                 WORD32 j, i4_avg_QP;
4058                                 ihevce_enc_loop_master_ctxt_t *ps_master_ctxt =
4059                                     (ihevce_enc_loop_master_ctxt_t *)
4060                                         ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt;
4061                                 ihevce_enc_loop_ctxt_t *ps_ctxt, *ps_ctxt_temp;
4062                                 ihevce_enc_loop_ctxt_t *ps_ctxt_last_thrd;
4063                                 LWORD64 i8_total_cu_bits_into_qscale = 0, i8_total_cu_bits = 0;
4064                                 UWORD32 total_frame_intra_sad = 0;
4065                                 UWORD32 total_frame_inter_sad = 0;
4066                                 UWORD32 total_frame_sad = 0;
4067 
4068                                 LWORD64 total_frame_intra_cost = 0;
4069                                 LWORD64 total_frame_inter_cost = 0;
4070                                 LWORD64 total_frame_cost = 0;
4071 
4072                                 ps_ctxt_last_thrd =
4073                                     ps_master_ctxt->aps_enc_loop_thrd_ctxt[i4_thrd_id];
4074                                 if(ps_enc_ctxt->s_multi_thrd.i4_in_frame_rc_enabled)
4075                                 {
4076                                     WORD32 i4_total_ctb =
4077                                         ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz *
4078                                         ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_vert;
4079 
4080                                     ai4_act_qp[i] =
4081                                         ps_enc_ctxt->s_multi_thrd
4082                                             .ai4_curr_qp_acc[ps_ctxt_last_thrd->i4_enc_frm_id][i] /
4083                                         i4_total_ctb;
4084                                 }
4085                                 else
4086                                 {
4087                                     ai4_act_qp[i] =
4088                                         ps_enc_ctxt->s_multi_thrd.cur_qp[i4_enc_frm_id][i];
4089                                 }
4090 
4091                                 ps_enc_ctxt->s_multi_thrd
4092                                     .ai4_curr_qp_acc[ps_ctxt_last_thrd->i4_enc_frm_id][i] = 0;
4093 
4094                                 /*Reset all the values of sub pic rc to default after the frame is completed */
4095                                 {
4096                                     ps_enc_ctxt->s_multi_thrd
4097                                         .ai4_acc_ctb_ctr[ps_ctxt_last_thrd->i4_enc_frm_id][i] = 0;
4098                                     ps_enc_ctxt->s_multi_thrd
4099                                         .ai4_ctb_ctr[ps_ctxt_last_thrd->i4_enc_frm_id][i] = 0;
4100 
4101                                     ps_enc_ctxt->s_multi_thrd
4102                                         .ai4_threshold_reached[ps_ctxt_last_thrd->i4_enc_frm_id][i] =
4103                                         0;
4104 
4105                                     ps_enc_ctxt->s_multi_thrd
4106                                         .ai4_curr_qp_estimated[ps_ctxt_last_thrd->i4_enc_frm_id][i] =
4107                                         (1 << QP_LEVEL_MOD_ACT_FACTOR);
4108 
4109                                     ps_enc_ctxt->s_multi_thrd
4110                                         .af_acc_hdr_bits_scale_err[ps_ctxt_last_thrd->i4_enc_frm_id]
4111                                                                   [i] = 0;
4112                                 }
4113                                 for(j = 0; j < ps_master_ctxt->i4_num_proc_thrds; j++)
4114                                 {
4115                                     /* ENC_LOOP state structure */
4116                                     ps_ctxt = ps_master_ctxt->aps_enc_loop_thrd_ctxt[j];
4117 
4118                                     total_frame_intra_sad +=
4119                                         ps_ctxt
4120                                             ->aaps_enc_loop_rc_params[ps_ctxt_last_thrd
4121                                                                           ->i4_enc_frm_id][i]
4122                                             ->u4_frame_intra_sad_acc;
4123                                     total_frame_inter_sad +=
4124                                         ps_ctxt
4125                                             ->aaps_enc_loop_rc_params[ps_ctxt_last_thrd
4126                                                                           ->i4_enc_frm_id][i]
4127                                             ->u4_frame_inter_sad_acc;
4128                                     total_frame_sad +=
4129                                         ps_ctxt
4130                                             ->aaps_enc_loop_rc_params[ps_ctxt_last_thrd
4131                                                                           ->i4_enc_frm_id][i]
4132                                             ->u4_frame_sad_acc;
4133 
4134                                     total_frame_intra_cost +=
4135                                         ps_ctxt
4136                                             ->aaps_enc_loop_rc_params[ps_ctxt_last_thrd
4137                                                                           ->i4_enc_frm_id][i]
4138                                             ->i8_frame_intra_cost_acc;
4139                                     total_frame_inter_cost +=
4140                                         ps_ctxt
4141                                             ->aaps_enc_loop_rc_params[ps_ctxt_last_thrd
4142                                                                           ->i4_enc_frm_id][i]
4143                                             ->i8_frame_inter_cost_acc;
4144                                     total_frame_cost +=
4145                                         ps_ctxt
4146                                             ->aaps_enc_loop_rc_params[ps_ctxt_last_thrd
4147                                                                           ->i4_enc_frm_id][i]
4148                                             ->i8_frame_cost_acc;
4149                                     /*Reset thrd id flag once the frame is completed */
4150                                     ps_enc_ctxt->s_multi_thrd
4151                                         .ai4_thrd_id_valid_flag[ps_ctxt_last_thrd->i4_enc_frm_id][i]
4152                                                                [j] = -1;
4153                                 }
4154                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4155                                     ->s_pic_level_info.u4_frame_sad = total_frame_sad;
4156                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4157                                     ->s_pic_level_info.u4_frame_intra_sad = total_frame_intra_sad;
4158                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4159                                     ->s_pic_level_info.u4_frame_inter_sad = total_frame_inter_sad;
4160 
4161                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4162                                     ->s_pic_level_info.i8_frame_cost = total_frame_cost;
4163                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4164                                     ->s_pic_level_info.i8_frame_intra_cost = total_frame_intra_cost;
4165                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4166                                     ->s_pic_level_info.i8_frame_inter_cost = total_frame_inter_cost;
4167                             }
4168                             ps_enc_ctxt->s_multi_thrd.ai4_produce_outbuf[i4_enc_frm_id][i] = 1;
4169                             ps_recon_out_temp =
4170                                 ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i];
4171                             ps_frm_recon_temp =
4172                                 ps_enc_ctxt->s_multi_thrd.ps_frm_recon[i4_enc_frm_id][i];
4173 
4174                             /* end of frame processing only if current input is valid */
4175                             if(1 == ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
4176                                         ->i4_frm_proc_valid_flag)
4177                             {
4178 #ifndef DISABLE_SEI
4179                                 /* Calculate the SEI Hash if enabled */
4180                                 if(0 !=
4181                                    ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4182                                        ->s_sei.i1_decoded_pic_hash_sei_flag)
4183                                 {
4184                                     void *pv_y_buf;
4185                                     void *pv_u_buf;
4186 
4187                                     {
4188                                         pv_y_buf = ps_frm_recon_temp->s_yuv_buf_desc.pv_y_buf;
4189                                         pv_u_buf = ps_frm_recon_temp->s_yuv_buf_desc.pv_u_buf;
4190                                     }
4191 
4192                                     ihevce_populate_hash_sei(
4193                                         &ps_enc_ctxt->s_multi_thrd
4194                                              .ps_curr_out_enc_grp[i4_enc_frm_id][i]
4195                                              ->s_sei,
4196                                         ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms
4197                                             .i4_internal_bit_depth,
4198                                         pv_y_buf,
4199                                         ps_frm_recon_temp->s_yuv_buf_desc.i4_y_wd,
4200                                         ps_frm_recon_temp->s_yuv_buf_desc.i4_y_ht,
4201                                         ps_frm_recon_temp->s_yuv_buf_desc.i4_y_strd,
4202                                         pv_u_buf,
4203                                         ps_frm_recon_temp->s_yuv_buf_desc.i4_uv_wd,
4204                                         ps_frm_recon_temp->s_yuv_buf_desc.i4_uv_ht,
4205                                         ps_frm_recon_temp->s_yuv_buf_desc.i4_uv_strd,
4206                                         0,
4207                                         0);
4208                                 }
4209 #endif
4210                                 /* Sending qp, poc and pic-type to entropy thread for printing on console */
4211                                 if(ps_enc_ctxt->ps_stat_prms->i4_log_dump_level != 0)
4212                                 {
4213                                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4214                                         ->i4_qp =
4215                                         ps_enc_ctxt->s_multi_thrd.cur_qp[i4_enc_frm_id][i];
4216                                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4217                                         ->i4_poc = ps_curr_inp->s_lap_out.i4_poc;
4218                                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4219                                         ->i4_pic_type = ps_curr_inp->s_lap_out.i4_pic_type;
4220                                 }
4221 
4222                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4223                                     ->i4_is_I_scenecut =
4224                                     ((ps_curr_inp->s_lap_out.i4_scene_type == 1) &&
4225                                      (ps_curr_inp->s_lap_out.i4_pic_type == IV_IDR_FRAME ||
4226                                       ps_curr_inp->s_lap_out.i4_pic_type == IV_I_FRAME));
4227 
4228                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4229                                     ->i4_is_non_I_scenecut =
4230                                     ((ps_curr_inp->s_lap_out.i4_scene_type ==
4231                                       SCENE_TYPE_SCENE_CUT) &&
4232                                      (ps_enc_ctxt->s_multi_thrd
4233                                           .ps_curr_out_enc_grp[i4_enc_frm_id][i]
4234                                           ->i4_is_I_scenecut == 0));
4235 
4236                                 /*ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]->i4_is_I_only_scd   = ps_curr_inp->s_lap_out.i4_is_I_only_scd;
4237                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]->i4_is_non_I_scd    = ps_curr_inp->s_lap_out.i4_is_non_I_scd;
4238 
4239                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]->i4_is_model_valid    = ps_curr_inp->s_lap_out.i4_is_model_valid;*/
4240 
4241                                 /* -------------------------------------------- */
4242                                 /*        MSE Computation for PSNR              */
4243                                 /* -------------------------------------------- */
4244                                 if(ps_enc_ctxt->ps_stat_prms->i4_log_dump_level != 0)
4245                                 {
4246                                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4247                                         ->i4_qp =
4248                                         ps_enc_ctxt->s_multi_thrd.cur_qp[i4_enc_frm_id][i];
4249                                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4250                                         ->i4_poc = ps_curr_inp->s_lap_out.i4_poc;
4251                                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4252                                         ->i4_pic_type = ps_curr_inp->s_lap_out.i4_pic_type;
4253                                 }
4254 
4255                                 /* if non reference B picture */
4256                                 if(0 == ps_frm_recon_temp->i4_is_reference)
4257                                 {
4258                                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4259                                         ->i4_pic_type += 2;
4260                                 }
4261 
4262 #define FORCE_EXT_REF_PIC 0
4263 
4264                                 /* -------------------------------------------- */
4265                                 /*        Dumping of recon to App Queue         */
4266                                 /* -------------------------------------------- */
4267                                 if(1 == ps_enc_ctxt->ps_stat_prms->i4_save_recon)
4268                                 {
4269                                     {
4270                                         WORD32 i, j;
4271                                         UWORD8 *pu1_recon;
4272                                         UWORD8 *pu1_chrm_buf_u;
4273                                         UWORD8 *pu1_chrm_buf_v;
4274                                         UWORD8 *pu1_curr_recon;
4275 
4276                                         pu1_recon =
4277                                             (UWORD8 *)ps_frm_recon_temp->s_yuv_buf_desc.pv_y_buf;
4278 
4279                                         /** Copying Luma into recon buffer  **/
4280                                         pu1_curr_recon = (UWORD8 *)ps_recon_out_temp->pv_y_buf;
4281 
4282                                         for(j = 0; j < ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht;
4283                                             j++)
4284                                         {
4285                                             memcpy(
4286                                                 pu1_curr_recon,
4287                                                 pu1_recon,
4288                                                 ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd);
4289 
4290                                             pu1_recon +=
4291                                                 ps_frm_recon_temp->s_yuv_buf_desc.i4_y_strd;
4292                                             pu1_curr_recon +=
4293                                                 ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd;
4294                                         }
4295 
4296                                         /* recon chroma is converted from Semiplanar to Planar for dumping */
4297                                         pu1_recon =
4298                                             (UWORD8 *)ps_frm_recon_temp->s_yuv_buf_desc.pv_u_buf;
4299                                         pu1_chrm_buf_u = (UWORD8 *)ps_recon_out_temp->pv_cb_buf;
4300                                         pu1_chrm_buf_v =
4301                                             pu1_chrm_buf_u +
4302                                             ((ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd >> 1) *
4303                                              ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht);
4304 
4305                                         for(j = 0; j < ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht;
4306                                             j++)
4307                                         {
4308                                             for(i = 0;
4309                                                 i<ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd>> 1;
4310                                                 i++)
4311                                             {
4312                                                 *pu1_chrm_buf_u++ = *pu1_recon++;
4313                                                 *pu1_chrm_buf_v++ = *pu1_recon++;
4314                                             }
4315 
4316                                             pu1_recon -=
4317                                                 ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd;
4318                                             pu1_recon +=
4319                                                 ps_frm_recon_temp->s_yuv_buf_desc.i4_uv_strd;
4320                                         }
4321 
4322                                         /* set the POC and number of bytes in Y & UV buf */
4323                                         ps_recon_out_temp->i4_poc = ps_frm_recon_temp->i4_poc;
4324                                         ps_recon_out_temp->i4_y_pixels =
4325                                             ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht *
4326                                             ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd;
4327                                         ps_recon_out_temp->i4_uv_pixels =
4328                                             ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd *
4329                                             ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht;
4330                                     }
4331                                 }
4332                                 ps_frm_recon_temp->i4_non_ref_free_flag = 1;
4333                                 /* -------------------------------------------- */
4334                                 /*        End of picture updates                */
4335                                 /* -------------------------------------------- */
4336                             }
4337 
4338                             /* After the MSE (or PSNR) computation is done we will update
4339                     these data in output buffer structure and then signal entropy
4340                     thread that the buffer is produced. */
4341                             if(ps_enc_ctxt->s_multi_thrd.ai4_produce_outbuf[i4_enc_frm_id][i] == 1)
4342                             {
4343                                 /* set the output buffer as produced */
4344                                 ihevce_q_set_buff_prod(
4345                                     (void *)ps_enc_ctxt,
4346                                     IHEVCE_FRM_PRS_ENT_COD_Q + i,
4347                                     ps_enc_ctxt->s_multi_thrd.out_buf_id[i4_enc_frm_id][i]);
4348 
4349                                 ps_enc_ctxt->s_multi_thrd.is_out_buf_freed[i4_enc_frm_id][i] = 1;
4350                                 ps_enc_ctxt->s_multi_thrd.ai4_produce_outbuf[i4_enc_frm_id][i] = 0;
4351                             }
4352 
4353                         }  //bit-rate counter ends
4354                         /* -------------------------------------------- */
4355                         /*        Frame level RC update                 */
4356                         /* -------------------------------------------- */
4357                         /* Query enc_loop to get the Parameters for Rate control */
4358                         if(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag)
4359                         {
4360                             frm_proc_ent_cod_ctxt_t *ps_curr_out = NULL;
4361                             /*HEVC_RC*/
4362                             rc_bits_sad_t as_rc_frame_stat[IHEVCE_MAX_NUM_BITRATES];
4363                             osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4364 
4365                             for(i = 0; i < i4_num_bitrates; i++)
4366                             {
4367                                 /*each bit-rate RC params are collated by master thread */
4368                                 ihevce_enc_loop_get_frame_rc_prms(
4369                                     ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt,
4370                                     &as_rc_frame_stat[i],
4371                                     i,
4372                                     i4_enc_frm_id);
4373 
4374                                 /*update bits estimate on rd opt thread so that mismatch between rdopt and entropy can be taken care of*/
4375                                 ps_curr_out =
4376                                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i];
4377 
4378                                 ps_rc_lap_out_next_encode =
4379                                     (rc_lap_out_params_t *)
4380                                         ps_curr_inp->s_rc_lap_out.ps_rc_lap_out_next_encode;
4381 
4382                                 ps_curr_out->i4_is_end_of_idr_gop = 0;
4383 
4384                                 if(NULL != ps_rc_lap_out_next_encode)
4385                                 {
4386                                     if(ps_rc_lap_out_next_encode->i4_rc_pic_type == IV_IDR_FRAME)
4387                                     {
4388                                         /*If the next pic is IDR, then signal end of gopf for current frame*/
4389                                         ps_curr_out->i4_is_end_of_idr_gop = 1;
4390                                     }
4391                                 }
4392                                 else if(NULL == ps_rc_lap_out_next_encode)
4393                                 {
4394                                     /*If the lap out next is NULL, then end of sequence reached*/
4395                                     ps_curr_out->i4_is_end_of_idr_gop = 1;
4396                                 }
4397 
4398                                 if(NULL == ps_curr_out)
4399                                 {
4400                                     DBG_PRINTF("error in getting curr out in encode loop\n");
4401                                 }
4402 
4403                                 //DBG_PRINTF("\nRDOPT head = %d RDOPT text = %d\n",s_rc_frame_stat.u4_total_header_bits,s_rc_frame_stat.u4_total_texture_bits);
4404                                 /* acquire mutex lock for rate control calls */
4405 
4406                                 /* Note : u4_total_intra_sad coming out of enc_loop */
4407                                 /* will not be accurate becos of intra gating       */
4408                                 /* need to access the importance of this sad in RC  */
4409 
4410                                 //Store the rc update parameters for deterministic Enc loop parallelism
4411 
4412                                 {
4413                                     ihevce_rc_store_retrive_update_info(
4414                                         (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
4415                                         &as_rc_frame_stat[i],
4416                                         i4_enc_frm_id_rc,
4417                                         i,
4418                                         1,
4419                                         &ps_enc_ctxt->s_multi_thrd.out_buf_id[i4_enc_frm_id][i],
4420                                         &ps_curr_inp->s_lap_out.i4_pic_type,
4421                                         &ai4_act_qp[i],
4422                                         (void *)&ps_curr_inp->s_lap_out,
4423                                         (void *)&ps_curr_inp->s_rc_lap_out);  // STORE
4424                                 }
4425                             }
4426 
4427                             /* release mutex lock after rate control calls */
4428                             osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4429                         }
4430                         if((ps_enc_ctxt->ps_stat_prms->i4_save_recon != 0) /*&&
4431                                                                    (1 == ps_curr_inp->s_input_buf.s_input_buf.i4_inp_frm_data_valid_flag)*/)
4432                         {
4433                             WORD32 i4_bitrate_ctr;
4434                             for(i4_bitrate_ctr = 0; i4_bitrate_ctr < i4_num_bitrates;
4435                                 i4_bitrate_ctr++)
4436                             {
4437                                 /*swaping of buf_id for 0th and reference bitrate location, as encoder
4438                         assumes always 0th loc for reference bitrate and app must receive in
4439                         the configured order*/
4440                                 WORD32 i4_recon_buf_id = i4_bitrate_ctr;
4441                                 if(i4_bitrate_ctr == 0)
4442                                 {
4443                                     i4_recon_buf_id = ps_enc_ctxt->i4_ref_mbr_id;
4444                                 }
4445                                 else if(i4_bitrate_ctr == ps_enc_ctxt->i4_ref_mbr_id)
4446                                 {
4447                                     i4_recon_buf_id = 0;
4448                                 }
4449 
4450                                 /* Call back to Apln. saying recon buffer is produced */
4451                                 ps_hle_ctxt->ihevce_output_recon_fill_done(
4452                                     ps_hle_ctxt->pv_recon_cb_handle,
4453                                     ps_enc_ctxt->s_multi_thrd
4454                                         .ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr],
4455                                     i4_recon_buf_id, /* br instance */
4456                                     i4_resolution_id /* res_intance */);
4457 
4458                                 /* --- release the current recon buffer ---- */
4459                                 ihevce_q_rel_buf(
4460                                     (void *)ps_enc_ctxt,
4461                                     (IHEVCE_RECON_DATA_Q + i4_recon_buf_id),
4462                                     ps_enc_ctxt->s_multi_thrd
4463                                         .recon_buf_id[i4_enc_frm_id][i4_bitrate_ctr]);
4464 
4465                                 ps_enc_ctxt->s_multi_thrd
4466                                     .is_recon_dumped[i4_enc_frm_id][i4_bitrate_ctr] = 1;
4467                             }
4468                         }
4469 
4470                         if(i4_enc_end_flag == 1)
4471                         {
4472                             if(ps_enc_ctxt->s_multi_thrd.is_in_buf_freed[i4_enc_frm_id] == 0)
4473                             {
4474                                 /* release the pre_enc/enc queue buffer */
4475                                 ihevce_q_rel_buf(
4476                                     (void *)ps_enc_ctxt,
4477                                     IHEVCE_PRE_ENC_ME_Q,
4478                                     ps_curr_inp_enc->curr_inp_from_me_buf_id);
4479 
4480                                 ps_enc_ctxt->s_multi_thrd.is_in_buf_freed[i4_enc_frm_id] = 1;
4481                             }
4482                         }
4483                         /* release encoder owned input buffer*/
4484                         ihevce_q_rel_buf(
4485                             (void *)ps_enc_ctxt,
4486                             IHEVCE_INPUT_DATA_CTRL_Q,
4487                             ps_curr_inp_enc->curr_inp_buf_id);
4488                         /* release the pre_enc/enc queue buffer */
4489                         ihevce_q_rel_buf(
4490                             ps_enc_ctxt,
4491                             IHEVCE_PRE_ENC_ME_Q,
4492                             ps_curr_inp_enc->curr_inp_from_me_buf_id);
4493 
4494                         ps_enc_ctxt->s_multi_thrd.is_in_buf_freed[i4_enc_frm_id] = 1;
4495 
4496                         /* release the pre_enc/enc queue buffer */
4497                         ihevce_q_rel_buf(
4498                             ps_enc_ctxt,
4499                             IHEVCE_L0_IPE_ENC_Q,
4500                             ps_curr_inp_enc->curr_inp_from_l0_ipe_buf_id);
4501 
4502                         ps_enc_ctxt->s_multi_thrd.is_L0_ipe_in_buf_freed[i4_enc_frm_id] = 1;
4503                         /* release the me/enc queue buffer */
4504                         ihevce_q_rel_buf(
4505                             ps_enc_ctxt,
4506                             IHEVCE_ME_ENC_RDOPT_Q,
4507                             ps_enc_ctxt->s_multi_thrd.i4_enc_in_buf_id[i4_enc_frm_id]);
4508 
4509                         /* reset the pointers to NULL */
4510                         ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] = NULL;
4511                         ps_enc_ctxt->s_multi_thrd.enc_master_done_frame_init[i4_enc_frm_id] = 0;
4512                         for(i = 0; i < i4_num_bitrates; i++)
4513                             ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i] = NULL;
4514 
4515                         /* Set the prev_frame_done variable to 1 to indicate that
4516                 *prev frame is done */
4517                         ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_done);
4518                     }
4519                 }
4520             }
4521             else
4522             {
4523                 /* Increment the counter to keep track of no of threads exiting the current mutex*/
4524                 ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id]++;
4525                 /*Last slave thread comming out of enc loop will execute next critical section*/
4526                 if(ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id] ==
4527                    ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds)
4528                 {
4529                     ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id] = 0;
4530 
4531                     /* reset the pointers to NULL */
4532                     ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] = NULL;
4533 
4534                     ps_enc_ctxt->s_multi_thrd.enc_master_done_frame_init[i4_enc_frm_id] = 0;
4535 
4536                     for(i = 0; i < i4_num_bitrates; i++)
4537                         ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i] = NULL;
4538 
4539                     /* Set the prev_frame_done variable to 1 to indicate that
4540                         *prev frame is done
4541                         */
4542                     ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_done);
4543                 }
4544             }
4545 
4546             /* Toggle the ping pong flag of the thread exiting curr frame*/
4547             /*ps_enc_ctxt->s_multi_thrd.ping_pong[ps_thrd_ctxt->i4_thrd_id] =
4548                 !ps_enc_ctxt->s_multi_thrd.ping_pong[ps_thrd_ctxt->i4_thrd_id];*/
4549         }
4550 
4551         /************************************/
4552         /******  EXIT CRITICAL SECTION ******/
4553         /************************************/
4554         /****** Unlock the critical section ******/
4555         if(NULL != ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id])
4556         {
4557             result = osal_mutex_unlock(
4558                 ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id]);
4559             if(OSAL_SUCCESS != result)
4560                 return 0;
4561         }
4562 
4563         if((0 == i4_me_end_flag) && (0 == i4_enc_end_flag))
4564         {
4565             i4_enc_frm_id++;
4566             i4_enc_frm_id_rc++;
4567 
4568             if(i4_enc_frm_id == NUM_ME_ENC_BUFS)
4569             {
4570                 i4_enc_frm_id = 0;
4571             }
4572 
4573             if(i4_enc_frm_id_rc == ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc)
4574             {
4575                 i4_enc_frm_id_rc = 0;
4576             }
4577             i4_me_frm_id++;
4578 
4579             if(i4_me_frm_id == NUM_ME_ENC_BUFS)
4580                 i4_me_frm_id = 0;
4581         }
4582         if(1 == ps_enc_ctxt->s_multi_thrd.i4_force_end_flag)
4583         {
4584             i4_me_end_flag = 1;
4585             i4_enc_end_flag = 1;
4586         }
4587     }
4588 
4589     /****** Lock the critical section ******/
4590 
4591     if(NULL != ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id])
4592     {
4593         WORD32 result;
4594 
4595         result =
4596             osal_mutex_lock(ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id]);
4597 
4598         if(OSAL_SUCCESS != result)
4599             return 0;
4600     }
4601 
4602     if(ps_enc_ctxt->s_multi_thrd.num_thrds_done ==
4603        (ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds - 1))
4604     {
4605         if(1 != ps_enc_ctxt->s_multi_thrd.i4_force_end_flag)
4606         {
4607             osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4608             for(i = 0; i < ps_enc_ctxt->i4_num_bitrates; i++)
4609             {
4610                 ihevce_rc_close(
4611                     ps_enc_ctxt,
4612                     ps_enc_ctxt->i4_active_enc_frame_id,
4613                     2,
4614                     MIN(ps_enc_ctxt->ai4_rc_query[i], ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc),
4615                     i);
4616             }
4617             osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4618         }
4619     }
4620 
4621     ps_enc_ctxt->s_multi_thrd.num_thrds_done++;
4622 
4623     /****** UnLock the critical section ******/
4624     if(NULL != ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id])
4625     {
4626         WORD32 result;
4627 
4628         result =
4629             osal_mutex_unlock(ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id]);
4630 
4631         if(OSAL_SUCCESS != result)
4632             return 0;
4633     }
4634 
4635     /****** Lock the critical section ******/
4636     if(NULL != ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id])
4637     {
4638         WORD32 result;
4639         result =
4640             osal_mutex_lock(ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id]);
4641 
4642         if(OSAL_SUCCESS != result)
4643             return 0;
4644     }
4645     if((ps_enc_ctxt->s_multi_thrd.num_thrds_done ==
4646         ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds) &&
4647        (ps_enc_ctxt->s_multi_thrd.i4_force_end_flag))
4648     {
4649         WORD32 num_bufs_preenc_me_que, num_bufs_L0_ipe_enc;
4650         WORD32 buf_id_ctr, frm_id_ctr;
4651         frm_proc_ent_cod_ctxt_t *ps_curr_out_enc_ent[IHEVCE_MAX_NUM_BITRATES];
4652         WORD32 out_buf_id_enc_ent[IHEVCE_MAX_NUM_BITRATES];
4653 
4654         if(ps_enc_ctxt->s_multi_thrd.i4_num_enc_loop_frm_pllel > 1)
4655         {
4656             num_bufs_preenc_me_que = (MAX_L0_IPE_ENC_STAGGER - 1) + MIN_L1_L0_STAGGER_NON_SEQ +
4657                                      NUM_BUFS_DECOMP_HME +
4658                                      ps_enc_ctxt->ps_stat_prms->s_lap_prms.i4_rc_look_ahead_pics;
4659 
4660             num_bufs_L0_ipe_enc = MAX_L0_IPE_ENC_STAGGER;
4661         }
4662         else
4663         {
4664             num_bufs_preenc_me_que = (MIN_L0_IPE_ENC_STAGGER - 1) + MIN_L1_L0_STAGGER_NON_SEQ +
4665                                      NUM_BUFS_DECOMP_HME +
4666                                      ps_enc_ctxt->ps_stat_prms->s_lap_prms.i4_rc_look_ahead_pics;
4667 
4668             num_bufs_L0_ipe_enc = MIN_L0_IPE_ENC_STAGGER;
4669         }
4670         for(buf_id_ctr = 0; buf_id_ctr < num_bufs_preenc_me_que; buf_id_ctr++)
4671         {
4672             /* release encoder owned input buffer*/
4673             ihevce_q_rel_buf((void *)ps_enc_ctxt, IHEVCE_PRE_ENC_ME_Q, buf_id_ctr);
4674         }
4675         for(buf_id_ctr = 0; buf_id_ctr < num_bufs_L0_ipe_enc; buf_id_ctr++)
4676         {
4677             /* release encoder owned input buffer*/
4678             ihevce_q_rel_buf((void *)ps_enc_ctxt, IHEVCE_L0_IPE_ENC_Q, buf_id_ctr);
4679         }
4680         for(frm_id_ctr = 0; frm_id_ctr < NUM_ME_ENC_BUFS; frm_id_ctr++)
4681         {
4682             for(i = 0; i < ps_enc_ctxt->i4_num_bitrates; i++)
4683             {
4684                 if(NULL != ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[frm_id_ctr][i])
4685                 {
4686                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[frm_id_ctr][i]
4687                         ->i4_frm_proc_valid_flag = 0;
4688                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[frm_id_ctr][i]->i4_end_flag = 1;
4689                     /* set the output buffer as produced */
4690                     ihevce_q_set_buff_prod(
4691                         (void *)ps_enc_ctxt,
4692                         IHEVCE_FRM_PRS_ENT_COD_Q + i,
4693                         ps_enc_ctxt->s_multi_thrd.out_buf_id[frm_id_ctr][i]);
4694                 }
4695             }
4696         }
4697         for(buf_id_ctr = 0; buf_id_ctr < NUM_FRMPROC_ENTCOD_BUFS;
4698             buf_id_ctr++) /*** Set buffer produced for NUM_FRMPROC_ENTCOD_BUFS buffers for entropy to exit ***/
4699         {
4700             for(i = 0; i < ps_enc_ctxt->i4_num_bitrates; i++)
4701             {
4702                 ps_curr_out_enc_ent[i] = (frm_proc_ent_cod_ctxt_t *)ihevce_q_get_free_buff(
4703                     (void *)ps_enc_ctxt,
4704                     IHEVCE_FRM_PRS_ENT_COD_Q + i, /*decides the buffer queue */
4705                     &out_buf_id_enc_ent[i],
4706                     BUFF_QUE_NON_BLOCKING_MODE);
4707                 if(NULL != ps_curr_out_enc_ent[i])
4708                 {
4709                     ps_curr_out_enc_ent[i]->i4_frm_proc_valid_flag = 0;
4710                     ps_curr_out_enc_ent[i]->i4_end_flag = 1;
4711                     /* set the output buffer as produced */
4712                     ihevce_q_set_buff_prod(
4713                         (void *)ps_enc_ctxt, IHEVCE_FRM_PRS_ENT_COD_Q + i, out_buf_id_enc_ent[i]);
4714                 }
4715             }
4716         }
4717     }
4718 
4719     /* The last thread coming out of Enc. Proc. */
4720     /* Release all the Recon buffers the application might have queued in */
4721     if((ps_enc_ctxt->s_multi_thrd.num_thrds_done ==
4722         ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds) &&
4723        (ps_enc_ctxt->ps_stat_prms->i4_save_recon != 0) &&
4724        (ps_enc_ctxt->s_multi_thrd.i4_is_recon_free_done == 0))
4725     {
4726         WORD32 i4_bitrate_ctr;
4727 
4728         for(i4_bitrate_ctr = 0; i4_bitrate_ctr < i4_num_bitrates; i4_bitrate_ctr++)
4729         {
4730             WORD32 end_flag = 0;
4731             while(0 == end_flag)
4732             {
4733                 /*swaping of buf_id for 0th and reference bitrate location, as encoder
4734                 assumes always 0th loc for reference bitrate and app must receive in
4735                 the configured order*/
4736                 WORD32 i4_recon_buf_id = i4_bitrate_ctr;
4737                 if(i4_bitrate_ctr == 0)
4738                 {
4739                     i4_recon_buf_id = ps_enc_ctxt->i4_ref_mbr_id;
4740                 }
4741                 else if(i4_bitrate_ctr == ps_enc_ctxt->i4_ref_mbr_id)
4742                 {
4743                     i4_recon_buf_id = 0;
4744                 }
4745 
4746                 /* ------- get free Recon buffer from Frame buffer que ---------- */
4747                 /* There is a separate queue for each bit-rate instnace. The recon
4748                 buffer is acquired from the corresponding queue based on the
4749                 bitrate instnace */
4750                 ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr] =
4751                     (iv_enc_recon_data_buffs_t *)ihevce_q_get_filled_buff(
4752                         (void *)ps_enc_ctxt,
4753                         IHEVCE_RECON_DATA_Q + i4_recon_buf_id, /*decides the buffer queue */
4754                         &ps_enc_ctxt->s_multi_thrd.recon_buf_id[i4_enc_frm_id][i4_bitrate_ctr],
4755                         BUFF_QUE_BLOCKING_MODE);
4756 
4757                 /* Update the end_flag from application */
4758                 end_flag = ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr]
4759                                ->i4_is_last_buf;
4760 
4761                 ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_end_flag =
4762                     1;
4763                 ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_y_pixels =
4764                     0;
4765                 ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_uv_pixels =
4766                     0;
4767 
4768                 /* Call back to Apln. saying recon buffer is produced */
4769                 ps_hle_ctxt->ihevce_output_recon_fill_done(
4770                     ps_hle_ctxt->pv_recon_cb_handle,
4771                     ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr],
4772                     i4_recon_buf_id, /* br instance */
4773                     i4_resolution_id /* res_intance */);
4774 
4775                 /* --- release the current recon buffer ---- */
4776                 ihevce_q_rel_buf(
4777                     (void *)ps_enc_ctxt,
4778                     (IHEVCE_RECON_DATA_Q + i4_recon_buf_id),
4779                     ps_enc_ctxt->s_multi_thrd.recon_buf_id[i4_enc_frm_id][i4_bitrate_ctr]);
4780             }
4781         }
4782         /* Set the recon free done flag */
4783         ps_enc_ctxt->s_multi_thrd.i4_is_recon_free_done = 1;
4784     }
4785 
4786     /****** UnLock the critical section ******/
4787     if(NULL != ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id])
4788     {
4789         WORD32 result;
4790         result =
4791             osal_mutex_unlock(ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id]);
4792 
4793         if(OSAL_SUCCESS != result)
4794             return 0;
4795     }
4796 
4797     return (0);
4798 }
4799 
4800 /*!
4801 ******************************************************************************
4802 * \if Function name : ihevce_set_pre_enc_prms \endif
4803 *
4804 * \brief
4805 *    Set CTB parameters
4806 *    Set ME params
4807 *    Set pps, sps, vps, vui params
4808 *    Do RC init
4809 *
4810 * \param[in] Encoder context pointer
4811 *
4812 * \return
4813 *    None
4814 *
4815 * \author
4816 *  Ittiam
4817 *
4818 *****************************************************************************
4819 */
ihevce_set_pre_enc_prms(enc_ctxt_t * ps_enc_ctxt)4820 void ihevce_set_pre_enc_prms(enc_ctxt_t *ps_enc_ctxt)
4821 {
4822     WORD32 i;
4823     WORD32 i4_num_instance,
4824         i4_resolution_id = ps_enc_ctxt->i4_resolution_id;  //number of bit-rate instances
4825 
4826     i4_num_instance = ps_enc_ctxt->i4_num_bitrates;
4827 
4828 #if PIC_ALIGN_CTB_SIZE
4829 
4830     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd =
4831         ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width +
4832         SET_CTB_ALIGN(
4833             ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width,
4834             ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size);
4835 
4836     ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz =
4837         ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd / ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size;
4838 
4839     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht =
4840         ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height +
4841         SET_CTB_ALIGN(
4842             ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height,
4843             ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size);
4844 
4845     ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_vert =
4846         ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht / ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size;
4847 #else  // PIC_ALIGN_CTB_SIZE
4848     /* Allign the frame width to min CU size */
4849     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd =
4850         ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width +
4851         SET_CTB_ALIGN(
4852             ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width,
4853             ps_enc_ctxt->s_frm_ctb_prms.i4_min_cu_size);
4854 
4855     ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz =
4856         ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd / ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size;
4857 
4858     if((ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd %
4859         ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size) != 0)
4860         ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz =
4861             ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz + 1;
4862 
4863     /* Allign the frame hieght to min CU size */
4864     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht =
4865         ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height +
4866         SET_CTB_ALIGN(
4867             ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height,
4868             ps_enc_ctxt->s_frm_ctb_prms.i4_min_cu_size);
4869 
4870     ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_vert =
4871         ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht / ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size;
4872 
4873     if((ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht %
4874         ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size) != 0)
4875         ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_vert =
4876             ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_vert + 1;
4877 
4878 #endif  // PIC_ALIGN_CTB_SIZE
4879 
4880     ps_enc_ctxt->s_frm_ctb_prms.i4_max_cus_in_row = ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz *
4881                                                     ps_enc_ctxt->s_frm_ctb_prms.i4_num_cus_in_ctb;
4882 
4883     ps_enc_ctxt->s_frm_ctb_prms.i4_max_pus_in_row = ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz *
4884                                                     ps_enc_ctxt->s_frm_ctb_prms.i4_num_pus_in_ctb;
4885 
4886     ps_enc_ctxt->s_frm_ctb_prms.i4_max_tus_in_row = ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz *
4887                                                     ps_enc_ctxt->s_frm_ctb_prms.i4_num_tus_in_ctb;
4888     ihevce_coarse_me_set_resolution(
4889         ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
4890         1,
4891         &ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd,
4892         &ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht);
4893 
4894     /*if Resolution need to be changed dynamically then needs to go to encode group */
4895     ihevce_me_set_resolution(
4896         ps_enc_ctxt->s_module_ctxt.pv_me_ctxt,
4897         1,
4898         &ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd,
4899         &ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht);
4900     i4_num_instance = ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id]
4901                           .i4_num_bitrate_instances;
4902     for(i = 0; i < i4_num_instance; i++)
4903     {
4904         WORD32 i4_id;
4905         /*swaping of buf_id for 0th and reference bitrate location, as encoder
4906         assumes always 0th loc for reference bitrate and app must receive in
4907         the configured order*/
4908         if(i == 0)
4909         {
4910             i4_id = ps_enc_ctxt->i4_ref_mbr_id;
4911         }
4912         else if(i == ps_enc_ctxt->i4_ref_mbr_id)
4913         {
4914             i4_id = 0;
4915         }
4916         else
4917         {
4918             i4_id = i;
4919         }
4920         /* populate vps based on encoder configuration and tools */
4921         ihevce_populate_vps(
4922             ps_enc_ctxt,
4923             &ps_enc_ctxt->as_vps[i],
4924             &ps_enc_ctxt->s_runtime_src_prms,
4925             &ps_enc_ctxt->ps_stat_prms->s_out_strm_prms,
4926             &ps_enc_ctxt->s_runtime_coding_prms,
4927             &ps_enc_ctxt->ps_stat_prms->s_config_prms,
4928             ps_enc_ctxt->ps_stat_prms,
4929             i4_resolution_id);
4930 
4931         /* populate sps based on encoder configuration and tools */
4932         ihevce_populate_sps(
4933             ps_enc_ctxt,
4934             &ps_enc_ctxt->as_sps[i],
4935             &ps_enc_ctxt->as_vps[i],
4936             &ps_enc_ctxt->s_runtime_src_prms,
4937             &ps_enc_ctxt->ps_stat_prms->s_out_strm_prms,
4938             &ps_enc_ctxt->s_runtime_coding_prms,
4939             &ps_enc_ctxt->ps_stat_prms->s_config_prms,
4940             &ps_enc_ctxt->s_frm_ctb_prms,
4941             ps_enc_ctxt->ps_stat_prms,
4942             i4_resolution_id);
4943 
4944         /* populate pps based on encoder configuration and tools */
4945         ihevce_populate_pps(
4946             &ps_enc_ctxt->as_pps[i],
4947             &ps_enc_ctxt->as_sps[i],
4948             &ps_enc_ctxt->s_runtime_src_prms,
4949             &ps_enc_ctxt->ps_stat_prms->s_out_strm_prms,
4950             &ps_enc_ctxt->s_runtime_coding_prms,
4951             &ps_enc_ctxt->ps_stat_prms->s_config_prms,
4952             ps_enc_ctxt->ps_stat_prms,
4953             i4_id,
4954             i4_resolution_id,
4955             ps_enc_ctxt->ps_tile_params_base,
4956             &ps_enc_ctxt->ai4_column_width_array[0],
4957             &ps_enc_ctxt->ai4_row_height_array[0]);
4958 
4959         // if(ps_enc_ctxt->as_sps[i].i1_vui_parameters_present_flag == 1)
4960         {
4961             WORD32 error_code = ihevce_populate_vui(
4962                                     &ps_enc_ctxt->as_sps[i].s_vui_parameters,
4963                                     &ps_enc_ctxt->as_sps[i],
4964                                     &ps_enc_ctxt->s_runtime_src_prms,
4965                                     &ps_enc_ctxt->ps_stat_prms->s_vui_sei_prms,
4966                                     i4_resolution_id,
4967                                     &ps_enc_ctxt->s_runtime_tgt_params,
4968                                     ps_enc_ctxt->ps_stat_prms,
4969                                     i4_id);
4970             if (error_code)
4971             {
4972                 ((ihevce_hle_ctxt_t *)ps_enc_ctxt->pv_hle_ctxt)->i4_error_code = error_code;
4973                 return;
4974             }
4975         }
4976     }
4977 
4978     osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4979     /* run the loop over all bit-rate instnaces */
4980     for(i = 0; i < i4_num_instance; i++)
4981     {
4982         /*HEVC_RC Do one time initialization of rate control*/
4983         ihevce_rc_init(
4984             (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
4985             &ps_enc_ctxt->s_runtime_src_prms,
4986             &ps_enc_ctxt->s_runtime_tgt_params,
4987             &ps_enc_ctxt->s_rc_quant,
4988             &ps_enc_ctxt->ps_stat_prms->s_sys_api,
4989             &ps_enc_ctxt->ps_stat_prms->s_lap_prms,
4990             ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc);
4991 
4992         ihevce_vbv_complaince_init_level(
4993             (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
4994             &ps_enc_ctxt->as_sps[i].s_vui_parameters);
4995     }
4996     osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4997 }
4998 
4999 /*!
5000 ******************************************************************************
5001 * \if Function name : ihevce_pre_enc_init \endif
5002 *
5003 * \brief
5004 *   set out_buf params
5005 *   Calculate end_flag if flushmode on
5006 *   Slice initialization
5007 *   Populate SIE params
5008 *   reference list creation
5009 *
5010 * \param[in] Encoder context pointer
5011 *
5012 * \return
5013 *    None
5014 *
5015 * \author
5016 *  Ittiam
5017 *
5018 *****************************************************************************
5019 */
ihevce_pre_enc_init(enc_ctxt_t * ps_enc_ctxt,ihevce_lap_enc_buf_t * ps_curr_inp,pre_enc_me_ctxt_t * ps_curr_out,WORD32 * pi4_end_flag_ret,WORD32 * pi4_cur_qp_ret,WORD32 * pi4_decomp_lyr_idx,WORD32 i4_ping_pong)5020 void ihevce_pre_enc_init(
5021     enc_ctxt_t *ps_enc_ctxt,
5022     ihevce_lap_enc_buf_t *ps_curr_inp,
5023     pre_enc_me_ctxt_t *ps_curr_out,
5024     WORD32 *pi4_end_flag_ret,
5025     WORD32 *pi4_cur_qp_ret,
5026     WORD32 *pi4_decomp_lyr_idx,
5027     WORD32 i4_ping_pong)
5028 {
5029     WORD32 end_flag = 0;
5030     WORD32 cur_qp;
5031     //recon_pic_buf_t *ps_frm_recon;
5032     WORD32 first_field = 1;
5033     WORD32 i4_field_pic = ps_enc_ctxt->s_runtime_src_prms.i4_field_pic;
5034     WORD32 i4_decomp_lyrs_idx = 0;
5035     WORD32 i4_resolution_id = ps_enc_ctxt->i4_resolution_id;
5036     WORD32 slice_type = ISLICE;
5037     WORD32 nal_type;
5038     WORD32 min_cu_size;
5039 
5040     WORD32 stasino_enabled;
5041 
5042     /* copy the time stamps from inp to entropy inp */
5043     ps_curr_out->i4_inp_timestamp_low = ps_curr_inp->s_input_buf.i4_inp_timestamp_low;
5044     ps_curr_out->i4_inp_timestamp_high = ps_curr_inp->s_input_buf.i4_inp_timestamp_high;
5045     ps_curr_out->pv_app_frm_ctxt = ps_curr_inp->s_input_buf.pv_app_frm_ctxt;
5046 
5047     /* get the min cu size from config params */
5048     min_cu_size = ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_min_log2_cu_size;
5049 
5050     min_cu_size = 1 << min_cu_size;
5051 
5052     ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd =
5053         ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd +
5054         SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd, min_cu_size);
5055 
5056     ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht =
5057         ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht +
5058         SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht, min_cu_size);
5059 
5060     ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd =
5061         ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd +
5062         SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd, min_cu_size);
5063 
5064     if(IV_YUV_420SP_UV == ps_enc_ctxt->ps_stat_prms->s_src_prms.i4_chr_format)
5065     {
5066         ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht =
5067             ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht +
5068             SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht, (min_cu_size >> 1));
5069     }
5070     else if(IV_YUV_422SP_UV == ps_enc_ctxt->ps_stat_prms->s_src_prms.i4_chr_format)
5071     {
5072         ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht =
5073             ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht +
5074             SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht, min_cu_size);
5075     }
5076 
5077     /* update the END flag from LAP out */
5078     end_flag = ps_curr_inp->s_lap_out.i4_end_flag;
5079     ps_curr_out->i4_end_flag = end_flag;
5080     ps_enc_ctxt->s_multi_thrd.i4_last_pic_flag = end_flag;
5081 
5082     /* ----------------------------------------------------------------------*/
5083     /*  Slice initialization for current frame; Required for entropy context */
5084     /* ----------------------------------------------------------------------*/
5085     {
5086         WORD32 cur_poc = ps_curr_inp->s_lap_out.i4_poc;
5087 
5088         /* max merge candidates derived based on quality preset for now */
5089         WORD32 max_merge_candidates = 2;
5090 
5091         /* pocs less than random acess poc tagged for discard as they */
5092         /* could be refering to pics before the cra.                  */
5093 
5094         /* CRA case: as the leading pictures can refer the picture precedes the associated
5095         IRAP(CRA) in decoding order, hence make it Random access skipped leading pictures (RASL)*/
5096 
5097         if((1 == ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.i4_enable_temporal_scalability) &&
5098            (ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_max_temporal_layers ==
5099             ps_curr_inp->s_lap_out.i4_temporal_lyr_id))  //TEMPORALA_SCALABILITY CHANGES
5100         {
5101             if(ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5102             {
5103                 nal_type = (cur_poc < ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5104                                ? (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_RASL_R : NAL_RASL_N)
5105                                : (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_TSA_R : NAL_TSA_N);
5106             }
5107             /* IDR case: as the leading pictures can't refer the picture precedes the associated
5108             IRAP(IDR) in decoding order, hence make it Random access decodable leading pictures (RADL)*/
5109             else
5110             {
5111                 nal_type = (cur_poc < ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5112                                ? (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_RADL_R : NAL_RADL_N)
5113                                : (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_TSA_R : NAL_TSA_N);
5114             }
5115         }
5116         else
5117         {
5118             if(ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5119             {
5120                 nal_type = (cur_poc < ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5121                                ? (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_RASL_R : NAL_RASL_N)
5122                                : (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_TRAIL_R : NAL_TRAIL_N);
5123             }
5124             /* IDR case: as the leading pictures can't refer the picture precedes the associated
5125             IRAP(IDR) in decoding order, hence make it Random access decodable leading pictures (RADL)*/
5126             else
5127             {
5128                 nal_type = (cur_poc < ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5129                                ? (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_RADL_R : NAL_RADL_N)
5130                                : (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_TRAIL_R : NAL_TRAIL_N);
5131             }
5132         }
5133 
5134         switch(ps_curr_inp->s_lap_out.i4_pic_type)
5135         {
5136         case IV_IDR_FRAME:
5137             /*  IDR pic */
5138             slice_type = ISLICE;
5139             nal_type = NAL_IDR_W_LP;
5140             cur_poc = 0;
5141             ps_enc_ctxt->i4_cra_poc = cur_poc;
5142             break;
5143 
5144         case IV_I_FRAME:
5145             slice_type = ISLICE;
5146 
5147             if(ps_curr_inp->s_lap_out.i4_is_cra_pic)
5148             {
5149                 nal_type = NAL_CRA;
5150             }
5151 
5152             ps_enc_ctxt->i4_cra_poc = cur_poc;
5153             break;
5154 
5155         case IV_P_FRAME:
5156             slice_type = PSLICE;
5157             break;
5158 
5159         case IV_B_FRAME:
5160             /* TODO : Mark the nal type as NAL_TRAIL_N for non ref pics */
5161             slice_type = BSLICE;
5162             break;
5163 
5164         default:
5165             /* This should never occur */
5166             ASSERT(0);
5167         }
5168 
5169         /* number of merge candidates and error metric chosen based on quality preset */
5170         switch(ps_curr_inp->s_lap_out.i4_quality_preset)
5171         {
5172         case IHEVCE_QUALITY_P0:
5173             max_merge_candidates = 5;
5174             break;
5175 
5176         case IHEVCE_QUALITY_P2:
5177             max_merge_candidates = 5;
5178             break;
5179 
5180         case IHEVCE_QUALITY_P3:
5181             max_merge_candidates = 3;
5182             break;
5183 
5184         case IHEVCE_QUALITY_P4:
5185         case IHEVCE_QUALITY_P5:
5186         case IHEVCE_QUALITY_P6:
5187         case IHEVCE_QUALITY_P7:
5188             max_merge_candidates = 2;
5189             break;
5190 
5191         default:
5192             ASSERT(0);
5193         }
5194 
5195         /* acquire mutex lock for rate control calls */
5196         osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
5197         {
5198             ps_curr_inp->s_rc_lap_out.i4_num_pels_in_frame_considered =
5199                 ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht *
5200                 ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd;
5201 
5202             /*initialize the frame info stat inside LAP out, Data inside this will be populated in ihevce_rc_get_bpp_based_frame_qp call*/
5203             ps_curr_inp->s_rc_lap_out.ps_frame_info = &ps_curr_inp->s_frame_info;
5204 
5205             ps_curr_inp->s_rc_lap_out.i4_is_bottom_field = ps_curr_inp->s_input_buf.i4_bottom_field;
5206             if(ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode == 3)
5207             {
5208                 /*for constant qp use same qp*/
5209                 /*HEVC_RC query rate control for qp*/
5210                 cur_qp = ihevce_rc_pre_enc_qp_query(
5211                     (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
5212                     &ps_curr_inp->s_rc_lap_out,
5213                     0);
5214             }
5215             else
5216             {
5217                 cur_qp = ihevce_rc_get_bpp_based_frame_qp(
5218                     (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0], &ps_curr_inp->s_rc_lap_out);
5219             }
5220         }
5221         /* release mutex lock after rate control calls */
5222         osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
5223 
5224         /* store the QP in output prms */
5225         /* The same qp is also used in enc thread only for ME*/
5226         ps_curr_out->i4_curr_frm_qp = cur_qp;
5227 
5228         /* slice header entropy syn memory is not valid in pre encode stage */
5229         ps_curr_out->s_slice_hdr.pu4_entry_point_offset = NULL;
5230 
5231         /* derive the flag which indicates if stasino is enabled */
5232         stasino_enabled = (ps_enc_ctxt->s_runtime_coding_prms.i4_vqet &
5233                            (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_NOISE_PRESERVATION)) &&
5234                           (ps_enc_ctxt->s_runtime_coding_prms.i4_vqet &
5235                            (1 << BITPOS_IN_VQ_TOGGLE_FOR_CONTROL_TOGGLER));
5236 
5237         /* initialize the slice header */
5238         ihevce_populate_slice_header(
5239             &ps_curr_out->s_slice_hdr,
5240             &ps_enc_ctxt->as_pps[0],
5241             &ps_enc_ctxt->as_sps[0],
5242             nal_type,
5243             slice_type,
5244             0,
5245             0,
5246             ps_curr_inp->s_lap_out.i4_poc,
5247             cur_qp,
5248             max_merge_candidates,
5249             ps_enc_ctxt->ps_stat_prms->s_pass_prms.i4_pass,
5250             ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id]
5251                 .i4_quality_preset,
5252             stasino_enabled);
5253 
5254         ps_curr_out->i4_slice_nal_type = nal_type;
5255 
5256         ps_curr_out->s_slice_hdr.u4_nuh_temporal_id = 0;
5257 
5258         if(1 == ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.i4_enable_temporal_scalability)
5259         {
5260             ps_curr_out->s_slice_hdr.u4_nuh_temporal_id =
5261                 (ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_max_temporal_layers ==
5262                  ps_curr_inp->s_lap_out.i4_temporal_lyr_id);  //TEMPORALA_SCALABILITY CHANGES
5263         }
5264 
5265         /* populate sps, vps and pps pointers for the entropy input params */
5266         ps_curr_out->ps_pps = &ps_enc_ctxt->as_pps[0];
5267         ps_curr_out->ps_sps = &ps_enc_ctxt->as_sps[0];
5268         ps_curr_out->ps_vps = &ps_enc_ctxt->as_vps[0];
5269     }
5270 
5271 #ifndef DISABLE_SEI
5272     /* By default, Sei messages are set to 0, to avoid unintialised memory access */
5273     memset(&ps_curr_out->s_sei, 0, sizeof(sei_params_t));
5274 
5275     /* VUI, SEI flags reset */
5276     ps_curr_out->s_sei.i1_sei_parameters_present_flag = 0;
5277     ps_curr_out->s_sei.i1_buf_period_params_present_flag = 0;
5278     ps_curr_out->s_sei.i1_pic_timing_params_present_flag = 0;
5279     ps_curr_out->s_sei.i1_recovery_point_params_present_flag = 0;
5280     ps_curr_out->s_sei.i1_decoded_pic_hash_sei_flag = 0;
5281     ps_curr_out->s_sei.i4_sei_mastering_disp_colour_vol_params_present_flags = 0;
5282 
5283     if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_enable_flag == 1)
5284     {
5285         /* insert buffering period, display volume, recovery point only at irap points */
5286         WORD32 insert_per_irap =
5287             ((slice_type == ISLICE) &&
5288              (((NAL_IDR_N_LP == nal_type) || (NAL_CRA == nal_type)) || (NAL_IDR_W_LP == nal_type)));
5289 
5290         ps_curr_out->s_sei.i1_sei_parameters_present_flag = 1;
5291 
5292         /* populate Sei buffering period based on encoder configuration and tools */
5293         if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_buffer_period_flags == 1)
5294         {
5295             ihevce_populate_buffering_period_sei(
5296                 &ps_curr_out->s_sei,
5297                 &ps_enc_ctxt->as_sps[0].s_vui_parameters,
5298                 &ps_enc_ctxt->as_sps[0],
5299                 &ps_enc_ctxt->ps_stat_prms->s_vui_sei_prms);
5300 
5301             ps_curr_out->s_sei.i1_buf_period_params_present_flag = insert_per_irap;
5302 
5303             ihevce_populate_active_parameter_set_sei(
5304                 &ps_curr_out->s_sei, &ps_enc_ctxt->as_vps[0], &ps_enc_ctxt->as_sps[0]);
5305         }
5306 
5307         /* populate Sei picture timing based on encoder configuration and tools */
5308         if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_pic_timing_flags == 1)
5309         {
5310             ihevce_populate_picture_timing_sei(
5311                 &ps_curr_out->s_sei,
5312                 &ps_enc_ctxt->as_sps[0].s_vui_parameters,
5313                 &ps_enc_ctxt->s_runtime_src_prms,
5314                 ps_curr_inp->s_input_buf.i4_bottom_field);
5315             ps_curr_out->s_sei.i1_pic_timing_params_present_flag = 1;
5316         }
5317 
5318         /* populate Sei recovery point based on encoder configuration and tools */
5319         if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_recovery_point_flags == 1)
5320         {
5321             ihevce_populate_recovery_point_sei(
5322                 &ps_curr_out->s_sei, &ps_enc_ctxt->ps_stat_prms->s_vui_sei_prms);
5323             ps_curr_out->s_sei.i1_recovery_point_params_present_flag = insert_per_irap;
5324         }
5325 
5326         /* populate mastering_display_colour_volume parameters */
5327         if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_mastering_disp_colour_vol_flags == 1)
5328         {
5329             ihevce_populate_mastering_disp_col_vol_sei(
5330                 &ps_curr_out->s_sei, &ps_enc_ctxt->ps_stat_prms->s_out_strm_prms);
5331 
5332             ps_curr_out->s_sei.i4_sei_mastering_disp_colour_vol_params_present_flags =
5333                 insert_per_irap;
5334         }
5335 
5336         /* populate SEI Hash Flag based on encoder configuration */
5337         if(0 != ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag)
5338         {
5339             /* Sanity checks */
5340             ASSERT(0 != ps_enc_ctxt->as_sps[0].i1_chroma_format_idc);
5341 
5342             ASSERT(
5343                 (0 < ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag) &&
5344                 (4 > ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag));
5345 
5346             /* MD5 is not supported now! picture_md5[cIdx][i] pblm */
5347             ASSERT(1 != ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag);
5348 
5349             ps_curr_out->s_sei.i1_decoded_pic_hash_sei_flag =
5350                 ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag;
5351         }
5352     }
5353 #endif
5354 
5355     /* For interlace pictures, first_field depends on topfield_first and bottom field */
5356     if(i4_field_pic)
5357     {
5358         first_field =
5359             (ps_curr_inp->s_input_buf.i4_topfield_first ^ ps_curr_inp->s_input_buf.i4_bottom_field);
5360     }
5361 
5362     /* get frame level lambda params */
5363     ihevce_get_frame_lambda_prms(
5364         ps_enc_ctxt,
5365         ps_curr_out,
5366         cur_qp,
5367         first_field,
5368         ps_curr_inp->s_lap_out.i4_is_ref_pic,
5369         ps_curr_inp->s_lap_out.i4_temporal_lyr_id,
5370         lamda_modifier_for_I_pic[4] /*mean TRF*/,
5371         0,
5372         PRE_ENC_LAMBDA_TYPE);
5373     /* Coarse ME and Decomp buffers sharing */
5374     {
5375         UWORD8 *apu1_lyr_bufs[MAX_NUM_HME_LAYERS];
5376         WORD32 ai4_lyr_buf_strd[MAX_NUM_HME_LAYERS];
5377 
5378         /* get the Decomposition frame buffer from ME */
5379         i4_decomp_lyrs_idx = ihevce_coarse_me_get_lyr_buf_desc(
5380             ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt, &apu1_lyr_bufs[0], &ai4_lyr_buf_strd[0]);
5381         /* register the buffers with decomp module along with frame init */
5382         ihevce_decomp_pre_intra_frame_init(
5383             ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt,
5384             &apu1_lyr_bufs[0],
5385             &ai4_lyr_buf_strd[0],
5386             ps_curr_out->ps_layer1_buf,
5387             ps_curr_out->ps_layer2_buf,
5388             ps_curr_out->ps_ed_ctb_l1,
5389             ps_curr_out->as_lambda_prms[0].i4_ol_sad_lambda_qf,
5390             ps_curr_out->ps_ctb_analyse);
5391     }
5392 
5393     /* -------------------------------------------------------- */
5394     /*   Preparing Pre encode Passes Job Queue                  */
5395     /* -------------------------------------------------------- */
5396     ihevce_prepare_pre_enc_job_queue(ps_enc_ctxt, ps_curr_inp, i4_ping_pong);
5397 
5398     /*assign return variables */
5399     *pi4_end_flag_ret = end_flag;
5400     *pi4_cur_qp_ret = cur_qp;
5401     *pi4_decomp_lyr_idx = i4_decomp_lyrs_idx;
5402     //*pps_frm_recon_ret = ps_frm_recon;
5403 }
5404 
5405 /*!
5406 ******************************************************************************
5407 * \if Function name : ihevce_pre_enc_coarse_me_init \endif
5408 *
5409 * \brief
5410 *   set out_buf params
5411 *   Calculate end_flag if flushmode on
5412 *   Slice initialization
5413 *   Populate SIE params
5414 *   reference list creation
5415 *
5416 * \param[in] Encoder context pointer
5417 *
5418 * \return
5419 *    None
5420 *
5421 * \author
5422 *  Ittiam
5423 *
5424 *****************************************************************************
5425 */
ihevce_pre_enc_coarse_me_init(enc_ctxt_t * ps_enc_ctxt,ihevce_lap_enc_buf_t * ps_curr_inp,pre_enc_me_ctxt_t * ps_curr_out,recon_pic_buf_t ** pps_frm_recon_ret,WORD32 i4_decomp_lyrs_idx,WORD32 i4_cur_qp,WORD32 i4_ping_pong)5426 void ihevce_pre_enc_coarse_me_init(
5427     enc_ctxt_t *ps_enc_ctxt,
5428     ihevce_lap_enc_buf_t *ps_curr_inp,
5429     pre_enc_me_ctxt_t *ps_curr_out,
5430     recon_pic_buf_t **pps_frm_recon_ret,
5431     WORD32 i4_decomp_lyrs_idx,
5432     WORD32 i4_cur_qp,
5433     WORD32 i4_ping_pong)
5434 
5435 {
5436     /* local variables */
5437     recon_pic_buf_t *ps_frm_recon;
5438     coarse_me_master_ctxt_t *ps_ctxt = NULL;
5439     ps_ctxt = (coarse_me_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt;
5440     /* Reference buffer management and reference list creation for pre enc group */
5441     ihevce_pre_enc_manage_ref_pics(ps_enc_ctxt, ps_curr_inp, ps_curr_out, i4_ping_pong);
5442 
5443     /* get a free recon buffer for current picture  */
5444     {
5445         WORD32 ctr;
5446 
5447         ps_frm_recon = NULL;
5448         for(ctr = 0; ctr < ps_enc_ctxt->i4_pre_enc_num_buf_recon_q; ctr++)
5449         {
5450             if(1 == ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr]->i4_is_free)
5451             {
5452                 ps_frm_recon = ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr];
5453                 break;
5454             }
5455         }
5456     }
5457     /* should not be NULL */
5458     ASSERT(ps_frm_recon != NULL);
5459 
5460     /* populate reference /recon params based on LAP output */
5461     ps_frm_recon->i4_is_free = 0;
5462     /* top first field is set to 1 by application */
5463     ps_frm_recon->i4_topfield_first = ps_curr_inp->s_input_buf.i4_topfield_first;
5464     ps_frm_recon->i4_poc = ps_curr_inp->s_lap_out.i4_poc;
5465     ps_frm_recon->i4_pic_type = ps_curr_inp->s_lap_out.i4_pic_type;
5466     ps_frm_recon->i4_display_num = ps_curr_inp->s_lap_out.i4_display_num;
5467     /* bottom field is toggled for every field by application */
5468     ps_frm_recon->i4_bottom_field = ps_curr_inp->s_input_buf.i4_bottom_field;
5469 
5470     /* Reference picture property is given by LAP */
5471     ps_frm_recon->i4_is_reference = ps_curr_inp->s_lap_out.i4_is_ref_pic;
5472 
5473     /* Deblock a picture for all reference frames unconditionally. */
5474     /* Deblock non ref if psnr compute or save recon is enabled    */
5475     ps_frm_recon->i4_deblk_pad_hpel_cur_pic = ps_frm_recon->i4_is_reference ||
5476                                               (ps_enc_ctxt->ps_stat_prms->i4_save_recon);
5477 
5478     /* set the width, height and stride to defalut values */
5479     ps_frm_recon->s_yuv_buf_desc.i4_y_ht = 0;
5480     ps_frm_recon->s_yuv_buf_desc.i4_uv_ht = 0;
5481     ps_frm_recon->s_yuv_buf_desc.i4_y_wd = 0;
5482     ps_frm_recon->s_yuv_buf_desc.i4_uv_wd = 0;
5483     ps_frm_recon->s_yuv_buf_desc.i4_y_strd = 0;
5484     ps_frm_recon->s_yuv_buf_desc.i4_uv_strd = 0;
5485 
5486     /* register the Layer1 MV bank pointer with ME module */
5487     ihevce_coarse_me_set_lyr1_mv_bank(
5488         ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
5489         ps_curr_inp,
5490         ps_curr_out->pv_me_mv_bank,
5491         ps_curr_out->pv_me_ref_idx,
5492         i4_decomp_lyrs_idx);
5493 
5494     /* Coarse picture level init of ME */
5495     ihevce_coarse_me_frame_init(
5496         ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
5497         ps_enc_ctxt->ps_stat_prms,
5498         &ps_enc_ctxt->s_frm_ctb_prms,
5499         &ps_curr_out->as_lambda_prms[0],
5500         ps_enc_ctxt->i4_pre_enc_num_ref_l0,
5501         ps_enc_ctxt->i4_pre_enc_num_ref_l1,
5502         ps_enc_ctxt->i4_pre_enc_num_ref_l0_active,
5503         ps_enc_ctxt->i4_pre_enc_num_ref_l1_active,
5504         &ps_enc_ctxt->aps_pre_enc_ref_lists[i4_ping_pong][LIST_0][0],
5505         &ps_enc_ctxt->aps_pre_enc_ref_lists[i4_ping_pong][LIST_1][0],
5506         ps_curr_inp,
5507         i4_cur_qp,
5508         ps_curr_out->ps_layer1_buf,
5509         ps_curr_out->ps_ed_ctb_l1,
5510         ps_curr_out->pu1_me_reverse_map_info,
5511         ps_curr_inp->s_lap_out.i4_temporal_lyr_id);
5512 
5513     /*assign return variables */
5514     *pps_frm_recon_ret = ps_frm_recon;
5515 }
5516 
5517 /*!
5518 ******************************************************************************
5519 * \brief
5520 *  Function to calculate modulation based on spatial variance across lap period
5521 *
5522 *****************************************************************************
5523 */
ihevce_variance_calc_acc_activity(enc_ctxt_t * ps_enc_ctxt,WORD32 i4_cur_ipe_idx)5524 void ihevce_variance_calc_acc_activity(enc_ctxt_t *ps_enc_ctxt, WORD32 i4_cur_ipe_idx)
5525 {
5526     pre_enc_me_ctxt_t *ps_curr_out = ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[i4_cur_ipe_idx];
5527     WORD32 is_curr_bslice = (ps_curr_out->s_slice_hdr.i1_slice_type == BSLICE);
5528 #if MODULATION_OVER_LAP
5529     WORD32 loop_lap2 = MAX(1, ps_enc_ctxt->s_multi_thrd.i4_delay_pre_me_btw_l0_ipe - 1);
5530 #else
5531     WORD32 loop_lap2 = 1;
5532 #endif
5533     WORD32 i4_delay_loop = ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe;
5534     WORD32 i, j;
5535 
5536     ps_curr_out->i8_acc_frame_8x8_sum_act_sqr = 0;
5537     ps_curr_out->i8_acc_frame_8x8_sum_act_for_strength = 0;
5538     for(i = 0; i < 2; i++)
5539     {
5540         ps_curr_out->i8_acc_frame_8x8_sum_act[i] = 0;
5541         ps_curr_out->i4_acc_frame_8x8_num_blks[i] = 0;
5542         ps_curr_out->i8_acc_frame_16x16_sum_act[i] = 0;
5543         ps_curr_out->i4_acc_frame_16x16_num_blks[i] = 0;
5544         ps_curr_out->i8_acc_frame_32x32_sum_act[i] = 0;
5545         ps_curr_out->i4_acc_frame_32x32_num_blks[i] = 0;
5546     }
5547     ps_curr_out->i8_acc_frame_16x16_sum_act[i] = 0;
5548     ps_curr_out->i4_acc_frame_16x16_num_blks[i] = 0;
5549     ps_curr_out->i8_acc_frame_32x32_sum_act[i] = 0;
5550     ps_curr_out->i4_acc_frame_32x32_num_blks[i] = 0;
5551 
5552     if(!is_curr_bslice)
5553     {
5554         for(i = 0; i < loop_lap2; i++)
5555         {
5556             WORD32 ipe_idx_tmp = (i4_cur_ipe_idx + i) % i4_delay_loop;
5557             ihevce_lap_enc_buf_t *ps_in = ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[ipe_idx_tmp];
5558             pre_enc_me_ctxt_t *ps_out = ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[ipe_idx_tmp];
5559             UWORD8 is_bslice = (ps_out->s_slice_hdr.i1_slice_type == BSLICE);
5560 
5561             if(!is_bslice)
5562             {
5563                 ps_curr_out->i8_acc_frame_8x8_sum_act_sqr += ps_out->u8_curr_frame_8x8_sum_act_sqr;
5564                 ps_curr_out->i8_acc_frame_8x8_sum_act_for_strength += ps_out->i4_curr_frame_8x8_sum_act_for_strength[0];
5565                 for(j = 0; j < 2; j++)
5566                 {
5567                     ps_curr_out->i8_acc_frame_8x8_sum_act[j] += ps_out->i8_curr_frame_8x8_sum_act[j];
5568                     ps_curr_out->i4_acc_frame_8x8_num_blks[j] += ps_out->i4_curr_frame_8x8_num_blks[j];
5569                     ps_curr_out->i8_acc_frame_16x16_sum_act[j] += ps_out->i8_curr_frame_16x16_sum_act[j];
5570                     ps_curr_out->i4_acc_frame_16x16_num_blks[j] += ps_out->i4_curr_frame_16x16_num_blks[j];
5571                     ps_curr_out->i8_acc_frame_32x32_sum_act[j] += ps_out->i8_curr_frame_32x32_sum_act[j];
5572                     ps_curr_out->i4_acc_frame_32x32_num_blks[j] += ps_out->i4_curr_frame_32x32_num_blks[j];
5573                 }
5574                 ps_curr_out->i8_acc_frame_16x16_sum_act[j] += ps_out->i8_curr_frame_16x16_sum_act[j];
5575                 ps_curr_out->i4_acc_frame_16x16_num_blks[j] += ps_out->i4_curr_frame_16x16_num_blks[j];
5576                 ps_curr_out->i8_acc_frame_32x32_sum_act[j] += ps_out->i8_curr_frame_32x32_sum_act[j];
5577                 ps_curr_out->i4_acc_frame_32x32_num_blks[j] += ps_out->i4_curr_frame_32x32_num_blks[j];
5578             }
5579             if(NULL == ps_in->s_rc_lap_out.ps_rc_lap_out_next_encode)
5580                 break;
5581         }
5582 
5583         for(j = 0; j < 3; j++)
5584         {
5585             if(j < 2)
5586                 ASSERT(0 != ps_curr_out->i4_acc_frame_8x8_num_blks[j]);
5587             ASSERT(0 != ps_curr_out->i4_acc_frame_16x16_num_blks[j]);
5588             ASSERT(0 != ps_curr_out->i4_acc_frame_32x32_num_blks[j]);
5589 
5590 #define AVG_ACTIVITY(a, b, c) a = ((b + (c >> 1)) / c)
5591 
5592             if(j < 2)
5593             {
5594                 if(0 == ps_curr_out->i4_acc_frame_8x8_num_blks[j])
5595                 {
5596                     ps_curr_out->i8_curr_frame_8x8_avg_act[j] = 0;
5597                 }
5598                 else
5599                 {
5600                     AVG_ACTIVITY(ps_curr_out->i8_curr_frame_8x8_sum_act_for_strength,
5601                                  ps_curr_out->i8_acc_frame_8x8_sum_act_for_strength,
5602                                  ps_curr_out->i4_acc_frame_8x8_num_blks[j]);
5603                     AVG_ACTIVITY(ps_curr_out->i8_curr_frame_8x8_avg_act[j],
5604                                  ps_curr_out->i8_acc_frame_8x8_sum_act[j],
5605                                  ps_curr_out->i4_acc_frame_8x8_num_blks[j]);
5606                     ps_curr_out->ld_curr_frame_8x8_log_avg[j] =
5607                         fast_log2(1 + ps_curr_out->i8_curr_frame_8x8_avg_act[j]);
5608                 }
5609             }
5610 
5611             if(0 == ps_curr_out->i4_acc_frame_16x16_num_blks[j])
5612             {
5613                 ps_curr_out->i8_curr_frame_16x16_avg_act[j] = 0;
5614             }
5615             else
5616             {
5617                 AVG_ACTIVITY(ps_curr_out->i8_curr_frame_16x16_avg_act[j],
5618                              ps_curr_out->i8_acc_frame_16x16_sum_act[j],
5619                              ps_curr_out->i4_acc_frame_16x16_num_blks[j]);
5620                 ps_curr_out->ld_curr_frame_16x16_log_avg[j] =
5621                     fast_log2(1 + ps_curr_out->i8_curr_frame_16x16_avg_act[j]);
5622             }
5623 
5624             if(0 == ps_curr_out->i4_acc_frame_32x32_num_blks[j])
5625             {
5626                 ps_curr_out->i8_curr_frame_32x32_avg_act[j] = 0;
5627             }
5628             else
5629             {
5630                 AVG_ACTIVITY(ps_curr_out->i8_curr_frame_32x32_avg_act[j],
5631                              ps_curr_out->i8_acc_frame_32x32_sum_act[j],
5632                              ps_curr_out->i4_acc_frame_32x32_num_blks[j]);
5633                 ps_curr_out->ld_curr_frame_32x32_log_avg[j] =
5634                     fast_log2(1 + ps_curr_out->i8_curr_frame_32x32_avg_act[j]);
5635             }
5636         }
5637 
5638         /* store the avg activity for B pictures */
5639 #if POW_OPT
5640         ps_enc_ctxt->ald_lap2_8x8_log_avg_act_from_T0[0] = ps_curr_out->ld_curr_frame_8x8_log_avg[0];
5641         ps_enc_ctxt->ald_lap2_8x8_log_avg_act_from_T0[1] = ps_curr_out->ld_curr_frame_8x8_log_avg[1];
5642         ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[0] = ps_curr_out->ld_curr_frame_16x16_log_avg[0];
5643         ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[1] = ps_curr_out->ld_curr_frame_16x16_log_avg[1];
5644         ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[2] = ps_curr_out->ld_curr_frame_16x16_log_avg[2];
5645         ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[0] = ps_curr_out->ld_curr_frame_32x32_log_avg[0];
5646         ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[1] = ps_curr_out->ld_curr_frame_32x32_log_avg[1];
5647         ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[2] = ps_curr_out->ld_curr_frame_32x32_log_avg[2];
5648 #else
5649         ps_enc_ctxt->ai8_lap2_8x8_avg_act_from_T0[0] = ps_curr_out->i8_curr_frame_8x8_avg_act[0];
5650         ps_enc_ctxt->ai8_lap2_8x8_avg_act_from_T0[1] = ps_curr_out->i8_curr_frame_8x8_avg_act[1];
5651         ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[0] = ps_curr_out->i8_curr_frame_16x16_avg_act[0];
5652         ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[1] = ps_curr_out->i8_curr_frame_16x16_avg_act[1];
5653         ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[2] = ps_curr_out->i8_curr_frame_16x16_avg_act[2];
5654         ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[0] = ps_curr_out->i8_curr_frame_32x32_avg_act[0];
5655         ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[1] = ps_curr_out->i8_curr_frame_32x32_avg_act[1];
5656         ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[2] = ps_curr_out->i8_curr_frame_32x32_avg_act[2];
5657 #endif
5658 
5659         /* calculate modulation index */
5660         {
5661             LWORD64 i8_mean, i8_mean_sqr, i8_variance;
5662             LWORD64 i8_deviation;
5663             WORD32 i4_mod_factor;
5664             float f_strength;
5665 
5666             if(ps_curr_out->i4_acc_frame_8x8_num_blks[0] > 0)
5667             {
5668 #if STRENGTH_BASED_ON_CURR_FRM
5669                 AVG_ACTIVITY(i8_mean_sqr, ps_curr_out->i8_curr_frame_8x8_sum_act_sqr,
5670                              ps_curr_out->i4_curr_frame_8x8_num_blks[0]);
5671 #else
5672                 AVG_ACTIVITY(i8_mean_sqr, ps_curr_out->i8_acc_frame_8x8_sum_act_sqr,
5673                              ps_curr_out->i4_acc_frame_8x8_num_blks[0]);
5674 #endif
5675                 i8_mean = ps_curr_out->i8_curr_frame_8x8_sum_act_for_strength;
5676                 i8_variance = i8_mean_sqr - (i8_mean * i8_mean);
5677                 i8_deviation = sqrt(i8_variance);
5678 
5679 #if STRENGTH_BASED_ON_DEVIATION
5680                 if(i8_deviation <= REF_MOD_DEVIATION)
5681                 {
5682                     f_strength = ((i8_deviation - BELOW_REF_DEVIATION) * REF_MOD_STRENGTH) / (REF_MOD_DEVIATION - BELOW_REF_DEVIATION);
5683                 }
5684                 else
5685                 {
5686                     f_strength = ((i8_deviation - ABOVE_REF_DEVIATION) * REF_MOD_STRENGTH) / (REF_MOD_DEVIATION - ABOVE_REF_DEVIATION);
5687                 }
5688 #else
5689                 f_strength = ((i8_mean_sqr / (float)(i8_mean * i8_mean)) - 1.0) * REF_MOD_STRENGTH / REF_MOD_VARIANCE;
5690 #endif
5691                 i4_mod_factor = (WORD32)(i8_deviation / 60);
5692                 f_strength = CLIP3(f_strength, 0.0, REF_MAX_STRENGTH);
5693             }
5694             else
5695             {
5696                 /* If not sufficient blocks are present, turn modulation index to 1  */
5697                 i4_mod_factor = 1;
5698                 f_strength = 0;
5699             }
5700             ps_curr_out->ai4_mod_factor_derived_by_variance[0] = i4_mod_factor;
5701             ps_curr_out->ai4_mod_factor_derived_by_variance[1] = i4_mod_factor;
5702             ps_curr_out->f_strength = f_strength;
5703 
5704             ps_enc_ctxt->ai4_mod_factor_derived_by_variance[0] = i4_mod_factor;
5705             ps_enc_ctxt->ai4_mod_factor_derived_by_variance[1] = i4_mod_factor;
5706             ps_enc_ctxt->f_strength = f_strength;
5707         }
5708     }
5709     else
5710     {
5711         ps_curr_out->ai4_mod_factor_derived_by_variance[0] = ps_enc_ctxt->ai4_mod_factor_derived_by_variance[0];
5712         ps_curr_out->ai4_mod_factor_derived_by_variance[1] = ps_enc_ctxt->ai4_mod_factor_derived_by_variance[1];
5713         ps_curr_out->f_strength = ps_enc_ctxt->f_strength;
5714 
5715         /* copy the prev avg activity from Tid 0 for B pictures*/
5716 #if POW_OPT
5717         ps_curr_out->ld_curr_frame_8x8_log_avg[0] = ps_enc_ctxt->ald_lap2_8x8_log_avg_act_from_T0[0];
5718         ps_curr_out->ld_curr_frame_8x8_log_avg[1] = ps_enc_ctxt->ald_lap2_8x8_log_avg_act_from_T0[1];
5719         ps_curr_out->ld_curr_frame_16x16_log_avg[0] = ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[0];
5720         ps_curr_out->ld_curr_frame_16x16_log_avg[1] = ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[1];
5721         ps_curr_out->ld_curr_frame_16x16_log_avg[2] = ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[2];
5722         ps_curr_out->ld_curr_frame_32x32_log_avg[0] = ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[0];
5723         ps_curr_out->ld_curr_frame_32x32_log_avg[1] = ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[1];
5724         ps_curr_out->ld_curr_frame_32x32_log_avg[2] = ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[2];
5725 #else
5726         ps_curr_out->i8_curr_frame_8x8_avg_act[0] = ps_enc_ctxt->ai8_lap2_8x8_avg_act_from_T0[0];
5727         ps_curr_out->i8_curr_frame_8x8_avg_act[1] = ps_enc_ctxt->ai8_lap2_8x8_avg_act_from_T0[1];
5728         ps_curr_out->i8_curr_frame_16x16_avg_act[0] = ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[0];
5729         ps_curr_out->i8_curr_frame_16x16_avg_act[1] = ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[1];
5730         ps_curr_out->i8_curr_frame_16x16_avg_act[2] = ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[2];
5731         ps_curr_out->i8_curr_frame_32x32_avg_act[0] = ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[0];
5732         ps_curr_out->i8_curr_frame_32x32_avg_act[1] = ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[1];
5733         ps_curr_out->i8_curr_frame_32x32_avg_act[2] = ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[2];
5734 #endif
5735     }
5736 #undef AVG_ACTIVITY
5737 }
5738 
5739 /*!
5740 ******************************************************************************
5741 * \if Function name : ihevce_pre_enc_process_frame_thrd \endif
5742 *
5743 * \brief
5744 *    Pre-Encode Frame processing thread interface function
5745 *
5746 * \param[in] High level encoder context pointer
5747 *
5748 * \return
5749 *    None
5750 *
5751 * \author
5752 *  Ittiam
5753 *
5754 *****************************************************************************
5755 */
ihevce_pre_enc_process_frame_thrd(void * pv_frm_proc_thrd_ctxt)5756 WORD32 ihevce_pre_enc_process_frame_thrd(void *pv_frm_proc_thrd_ctxt)
5757 {
5758     frm_proc_thrd_ctxt_t *ps_thrd_ctxt = (frm_proc_thrd_ctxt_t *)pv_frm_proc_thrd_ctxt;
5759     ihevce_hle_ctxt_t *ps_hle_ctxt = ps_thrd_ctxt->ps_hle_ctxt;
5760     enc_ctxt_t *ps_enc_ctxt = (enc_ctxt_t *)ps_thrd_ctxt->pv_enc_ctxt;
5761     multi_thrd_ctxt_t *ps_multi_thrd = &ps_enc_ctxt->s_multi_thrd;
5762     WORD32 i4_thrd_id = ps_thrd_ctxt->i4_thrd_id;
5763     WORD32 i4_resolution_id = ps_enc_ctxt->i4_resolution_id;
5764     WORD32 i4_end_flag = 0;
5765     WORD32 i4_out_flush_flag = 0;
5766     WORD32 i4_cur_decomp_idx = 0;
5767     WORD32 i4_cur_coarse_me_idx = 0;
5768     WORD32 i4_cur_ipe_idx = 0;
5769     ihevce_lap_enc_buf_t *ps_lap_inp_buf = NULL;
5770     void *pv_dep_mngr_prev_frame_pre_enc_l1 = ps_multi_thrd->pv_dep_mngr_prev_frame_pre_enc_l1;
5771     void *pv_dep_mngr_prev_frame_pre_enc_l0 = ps_multi_thrd->pv_dep_mngr_prev_frame_pre_enc_l0;
5772     void *pv_dep_mngr_prev_frame_pre_enc_coarse_me =
5773         ps_multi_thrd->pv_dep_mngr_prev_frame_pre_enc_coarse_me;
5774     WORD32 i4_num_buf_prod_for_l0_ipe = 0;
5775     WORD32 i4_decomp_end_flag = 0;
5776 
5777     (void)ps_hle_ctxt;
5778     (void)i4_resolution_id;
5779 
5780     /* ---------- Processing Loop until Flush command is received --------- */
5781     while(0 == i4_end_flag)
5782     {
5783         /* Wait till previous frame(instance)'s decomp_intra is processed */
5784         {
5785             ihevce_dmgr_chk_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_l1, i4_thrd_id);
5786         }
5787 
5788         /* ----------------------------------------------------------- */
5789         /*     decomp pre_intra init                                   */
5790         /* ----------------------------------------------------------- */
5791 
5792         /****** Lock the critical section for decomp pre_intra init ******/
5793         {
5794             WORD32 i4_status;
5795 
5796             i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_init);
5797             if(OSAL_SUCCESS != i4_status)
5798                 return 0;
5799         }
5800 
5801         ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_decomp_idx] = 0;
5802 
5803         /* init */
5804         if((ps_multi_thrd->ai4_pre_enc_init_done[i4_cur_decomp_idx] == 0) &&
5805            (0 == i4_decomp_end_flag))
5806         {
5807             ihevce_lap_enc_buf_t *ps_curr_inp = NULL;
5808             pre_enc_me_ctxt_t *ps_curr_out = NULL;
5809             WORD32 in_buf_id;
5810             WORD32 out_buf_id;
5811 
5812             do
5813             {
5814                 ps_lap_inp_buf = NULL;
5815                 if(0 == ps_multi_thrd->i4_last_inp_buf)
5816                 {
5817                     /* ------- get input buffer input data que ---------- */
5818                     ps_lap_inp_buf = (ihevce_lap_enc_buf_t *)ihevce_q_get_filled_buff(
5819                         (void *)ps_enc_ctxt,
5820                         IHEVCE_INPUT_DATA_CTRL_Q,
5821                         &in_buf_id,
5822                         BUFF_QUE_BLOCKING_MODE);
5823                     ps_multi_thrd->i4_last_inp_buf = ihevce_check_last_inp_buf(
5824                         (WORD32 *)ps_lap_inp_buf->s_input_buf.pv_synch_ctrl_bufs);
5825                 }
5826 
5827                 ps_curr_inp =
5828                     ihevce_lap_process(ps_enc_ctxt->pv_lap_interface_ctxt, ps_lap_inp_buf);
5829 
5830             } while(NULL == ps_curr_inp);
5831 
5832             /* set the flag saying init is done so that other cores dont do it */
5833             ps_multi_thrd->ai4_pre_enc_init_done[i4_cur_decomp_idx] = 1;
5834 
5835             ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_decomp_idx] = ps_curr_inp;
5836             ps_multi_thrd->ai4_in_buf_id_pre_enc[i4_cur_decomp_idx] =
5837                 ps_curr_inp->s_input_buf.i4_buf_id;
5838 
5839             /* ------- get free output buffer from pre-enc/enc buffer que ---------- */
5840             ps_curr_out = (pre_enc_me_ctxt_t *)ihevce_q_get_free_buff(
5841                 (void *)ps_enc_ctxt, IHEVCE_PRE_ENC_ME_Q, &out_buf_id, BUFF_QUE_BLOCKING_MODE);
5842             ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_decomp_idx] = ps_curr_out;
5843             ps_multi_thrd->ai4_out_buf_id_pre_enc[i4_cur_decomp_idx] = out_buf_id;
5844 
5845             if((NULL != ps_curr_inp) && (NULL != ps_curr_out))
5846             {
5847                 /* by default last picture to be encoded flag is set to 0      */
5848                 /* this flag will be used by slave threads to exit at the end */
5849                 ps_multi_thrd->i4_last_pic_flag = 0;
5850 
5851                 /* store the buffer id */
5852                 ps_curr_out->i4_buf_id = out_buf_id;
5853 
5854                 ps_curr_out->i8_acc_num_blks_high_sad = 0;
5855                 ps_curr_out->i8_total_blks = 0;
5856                 ps_curr_out->i4_is_high_complex_region = -1;
5857 
5858                 /* set the parameters for sync b/w pre-encode and encode threads */
5859                 ps_curr_out->i4_end_flag = ps_curr_inp->s_lap_out.i4_end_flag;
5860                 ps_curr_out->i4_frm_proc_valid_flag = 1;
5861                 if(ps_curr_out->i4_end_flag)
5862                 {
5863                     ps_curr_out->i4_frm_proc_valid_flag =
5864                         ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag;
5865                     ps_multi_thrd->i4_last_pic_flag = 1;
5866                     ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx] = 1;
5867                 }
5868                 if(ps_curr_inp->s_lap_out.i4_out_flush_flag)
5869                 {
5870                     ps_curr_out->i4_frm_proc_valid_flag =
5871                         ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag;
5872                 }
5873 
5874                 /* do the init processing if input frm data is valid */
5875                 if(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag)
5876                 {
5877                     WORD32 end_flag = ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx];
5878                     WORD32 cur_qp = 0, count;
5879 
5880                     ihevce_pre_enc_init(
5881                         ps_enc_ctxt,
5882                         ps_curr_inp,
5883                         ps_curr_out,
5884                         &end_flag,
5885                         &cur_qp,
5886                         &ps_multi_thrd->ai4_decomp_lyr_buf_idx[i4_cur_decomp_idx],
5887                         i4_cur_decomp_idx);
5888 
5889                     ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx] = end_flag;
5890                     ps_multi_thrd->ai4_cur_frame_qp_pre_enc[i4_cur_decomp_idx] = cur_qp;
5891 
5892                     for(count = 0; count < ((HEVCE_MAX_HEIGHT >> 1) / 8); count++)
5893                     {
5894                         ps_multi_thrd->aai4_l1_pre_intra_done[i4_cur_decomp_idx][count] = 0;
5895                     }
5896                 }
5897             }
5898         }
5899         else if(1 == i4_decomp_end_flag)
5900         {
5901             /* Once end is reached all subsequent flags are set to 1 to indicate end */
5902             ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx] = 1;
5903         }
5904 
5905         /****** UnLock the critical section after decomp pre_intra init ******/
5906         {
5907             WORD32 i4_status;
5908             i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_pre_enc_init);
5909 
5910             if(OSAL_SUCCESS != i4_status)
5911                 return 0;
5912         }
5913         if(i4_thrd_id == 0)
5914         {
5915             PROFILE_START(&ps_hle_ctxt->profile_pre_enc_l1l2[i4_resolution_id]);
5916         }
5917         /* ------------------------------------------------------------ */
5918         /*        Layer Decomp and Pre Intra Analysis                   */
5919         /* ------------------------------------------------------------ */
5920         if(0 == i4_decomp_end_flag)
5921         {
5922             pre_enc_me_ctxt_t *ps_curr_out = ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_decomp_idx];
5923 
5924             if(1 == ps_curr_out->i4_frm_proc_valid_flag)
5925             {
5926                 ihevce_decomp_pre_intra_process(
5927                     ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt,
5928                     &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_decomp_idx]->s_lap_out,
5929                     &ps_enc_ctxt->s_frm_ctb_prms,
5930                     ps_multi_thrd,
5931                     i4_thrd_id,
5932                     i4_cur_decomp_idx);
5933             }
5934         }
5935 
5936         /* ------------------------------------------------------------ */
5937         /*        Layer Decomp and Pre Intra Deinit                     */
5938         /* ------------------------------------------------------------ */
5939 
5940         /****** Lock the critical section for decomp deinit ******/
5941         {
5942             WORD32 i4_status;
5943             i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_decomp_deinit);
5944 
5945             if(OSAL_SUCCESS != i4_status)
5946                 return 0;
5947         }
5948 
5949         ps_multi_thrd->ai4_num_thrds_processed_decomp[i4_cur_decomp_idx]++;
5950         i4_decomp_end_flag = ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx];
5951 
5952         /* check for last thread condition */
5953         if(ps_multi_thrd->ai4_num_thrds_processed_decomp[i4_cur_decomp_idx] ==
5954            ps_multi_thrd->i4_num_pre_enc_proc_thrds)
5955         {
5956             ps_multi_thrd->ai4_num_thrds_processed_decomp[i4_cur_decomp_idx] = 0;
5957 
5958             /* reset the init flag so that init happens by the first thread for the next frame
5959                of same ping_pong instance */
5960             ps_multi_thrd->ai4_pre_enc_init_done[i4_cur_decomp_idx] = 0;
5961 
5962             /* update the pre enc l1 done in dep manager */
5963             ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_l1);
5964         }
5965 
5966         /* index increment */
5967         i4_cur_decomp_idx = i4_cur_decomp_idx + 1;
5968 
5969         /* wrap around case */
5970         if(i4_cur_decomp_idx >= ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe)
5971         {
5972             i4_cur_decomp_idx = 0;
5973         }
5974 
5975         /****** UnLock the critical section after decomp pre_intra deinit ******/
5976         {
5977             WORD32 i4_status;
5978             i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_pre_enc_decomp_deinit);
5979 
5980             if(OSAL_SUCCESS != i4_status)
5981                 return 0;
5982         }
5983 
5984         /* ------------------------------------------------------------ */
5985         /*                     HME Init                                 */
5986         /* ------------------------------------------------------------ */
5987 
5988         /* Wait till previous frame(instance)'s coarse_me is processed */
5989         {
5990             ihevce_dmgr_chk_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_coarse_me, i4_thrd_id);
5991         }
5992 
5993         /****** Lock the critical section for hme init ******/
5994         {
5995             WORD32 i4_status;
5996 
5997             i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_hme_init);
5998             if(OSAL_SUCCESS != i4_status)
5999                 return 0;
6000         }
6001 
6002         if(0 == ps_multi_thrd->ai4_pre_enc_hme_init_done[i4_cur_coarse_me_idx])
6003         {
6004             /* do the init processing if input frm data is valid */
6005             if(1 ==
6006                ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->i4_frm_proc_valid_flag)
6007             {
6008                 recon_pic_buf_t *ps_frm_recon = NULL;
6009 
6010                 /* DPB management for coarse me + HME init */
6011                 ihevce_pre_enc_coarse_me_init(
6012                     ps_enc_ctxt,
6013                     ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx],
6014                     ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx],
6015                     &ps_frm_recon,
6016                     ps_multi_thrd->ai4_decomp_lyr_buf_idx[i4_cur_coarse_me_idx],
6017                     ps_multi_thrd->ai4_cur_frame_qp_pre_enc[i4_cur_coarse_me_idx],
6018                     i4_cur_coarse_me_idx);
6019             }
6020 
6021             ps_multi_thrd->ai4_pre_enc_hme_init_done[i4_cur_coarse_me_idx] = 1;
6022         }
6023 
6024         /****** Unlock the critical section for hme init ******/
6025         {
6026             WORD32 i4_status;
6027 
6028             i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_pre_enc_hme_init);
6029             if(OSAL_SUCCESS != i4_status)
6030                 return 0;
6031         }
6032 
6033         /* ------------------------------------------------------------ */
6034         /*  Coarse Motion estimation and early intra-inter decision     */
6035         /* ------------------------------------------------------------ */
6036         if(1 == ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->i4_frm_proc_valid_flag)
6037         {
6038             ihevce_coarse_me_process(
6039                 ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
6040                 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx],
6041                 &ps_enc_ctxt->s_multi_thrd,
6042                 i4_thrd_id,
6043                 i4_cur_coarse_me_idx);
6044         }
6045 
6046         /* update the end flag */
6047         i4_end_flag = ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_coarse_me_idx];
6048         i4_out_flush_flag =
6049             ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx]->s_lap_out.i4_out_flush_flag;
6050 
6051         /****** Lock the critical section for hme deinit ******/
6052         {
6053             WORD32 i4_status;
6054             i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_hme_deinit);
6055 
6056             if(OSAL_SUCCESS != i4_status)
6057                 return 0;
6058         }
6059 
6060         /* last thread finishing pre_enc_process will update the flag indicating
6061         decomp and coarse ME is done. So that the next frame (next ping_pong instance)
6062         can start immediately after finishing current frame's IPE */
6063         if(1 == ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->i4_frm_proc_valid_flag)
6064         {
6065             ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx]++;
6066 
6067             /* ------------------------------------------------------------ */
6068             /*  Update qp used in based in L1 satd/act in case of scene cut */
6069             /* ------------------------------------------------------------ */
6070             {
6071                 ihevce_lap_enc_buf_t *ps_curr_inp =
6072                     ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx];
6073 
6074                 if(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag)
6075                 {
6076                     WORD32 i4_prev_coarse_me_idx;
6077 
6078                     /* wrap around case */
6079                     if(i4_cur_coarse_me_idx == 0)
6080                     {
6081                         i4_prev_coarse_me_idx = ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe - 1;
6082                     }
6083                     else
6084                     {
6085                         i4_prev_coarse_me_idx = i4_cur_coarse_me_idx - 1;
6086                     }
6087 
6088                     ihevce_update_qp_L1_sad_based(
6089                         ps_enc_ctxt,
6090                         ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx],
6091                         ps_multi_thrd->aps_curr_inp_pre_enc[i4_prev_coarse_me_idx],
6092                         ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx],
6093                         ((ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx] ==
6094                           ps_multi_thrd->i4_num_pre_enc_proc_thrds)));
6095                 }
6096             }
6097             /* check for last thread condition */
6098             if(ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx] ==
6099                ps_multi_thrd->i4_num_pre_enc_proc_thrds)
6100             {
6101                 ihevce_lap_enc_buf_t *ps_curr_inp =
6102                     ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx];
6103 
6104                 /*        Frame END processing                  */
6105                 ihevce_coarse_me_frame_end(ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt);
6106 
6107                 if(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag)
6108                 {
6109                     WORD32 i4_enable_noise_detection = 0;
6110                     WORD32 i4_vqet = ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_vqet;
6111 
6112                     if(i4_vqet & (1 << BITPOS_IN_VQ_TOGGLE_FOR_CONTROL_TOGGLER))
6113                     {
6114                         if(i4_vqet & (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_NOISE_PRESERVATION))
6115                         {
6116                             i4_enable_noise_detection = 1;
6117                         }
6118                     }
6119 
6120                     if(1 != ((ps_curr_inp->s_lap_out.i4_pic_type == IV_B_FRAME) &&
6121                              (ps_enc_ctxt->s_lap_stat_prms.ai4_quality_preset[i4_resolution_id] ==
6122                               IHEVCE_QUALITY_P6)))
6123                     {
6124                         ihevce_decomp_pre_intra_curr_frame_pre_intra_deinit(
6125                             ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt,
6126                             ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx],
6127                             &ps_enc_ctxt->s_frm_ctb_prms);
6128                     }
6129                 }
6130 
6131                 ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_coarse_me_idx] = 1;
6132 
6133                 ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx] = 0;
6134 
6135                 /* get the layer 1 ctxt to be passed on to encode group */
6136                 ihevce_coarse_me_get_lyr1_ctxt(
6137                     ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
6138                     ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->pv_me_lyr_ctxt,
6139                     ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->pv_me_lyr_bnk_ctxt);
6140 
6141                 /* reset the init flag so that init happens by the first thread for the next frame
6142                     of same ping_pong instance */
6143                 ps_multi_thrd->ai4_pre_enc_hme_init_done[i4_cur_coarse_me_idx] = 0;
6144 
6145                 /* update the pre enc l1 done in dep manager */
6146                 ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_coarse_me);
6147             }
6148 
6149             i4_num_buf_prod_for_l0_ipe++;
6150 
6151             /* index increment */
6152             i4_cur_coarse_me_idx = i4_cur_coarse_me_idx + 1;
6153 
6154             /* wrap around case */
6155             if(i4_cur_coarse_me_idx >= ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe)
6156             {
6157                 i4_cur_coarse_me_idx = 0;
6158             }
6159         }
6160         else
6161         {
6162             /* for invalid frame set the processed flag to 1 for L0 IPE */
6163             ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_coarse_me_idx] = 1;
6164 
6165             if(1 == i4_out_flush_flag)
6166             {
6167                 /* update the num thrds who have finished pre-enc processing */
6168                 ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx]++;
6169 
6170                 if(ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx] ==
6171                    ps_multi_thrd->i4_num_pre_enc_proc_thrds)
6172                 {
6173                     ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_coarse_me_idx] = 1;
6174 
6175                     /* reset num thread finished counter */
6176                     ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx] = 0;
6177 
6178                     ps_multi_thrd->ai4_pre_enc_hme_init_done[i4_cur_coarse_me_idx] = 0;
6179 
6180                     /* update flag indicating coarse_me and decomp is done */
6181                     ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_coarse_me);
6182                 }
6183             }
6184 
6185             i4_num_buf_prod_for_l0_ipe++;
6186 
6187             /* index increment */
6188             i4_cur_coarse_me_idx = i4_cur_coarse_me_idx + 1;
6189 
6190             /* wrap around case */
6191             if(i4_cur_coarse_me_idx >= ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe)
6192             {
6193                 i4_cur_coarse_me_idx = 0;
6194             }
6195         }
6196 
6197         /****** UnLock the critical section after hme deinit ******/
6198         {
6199             WORD32 i4_status;
6200             i4_status =
6201                 osal_mutex_unlock(ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_hme_deinit);
6202 
6203             if(OSAL_SUCCESS != i4_status)
6204                 return 0;
6205         }
6206 
6207         if(i4_thrd_id == 0)
6208         {
6209             PROFILE_STOP(&ps_hle_ctxt->profile_pre_enc_l1l2[i4_resolution_id], NULL);
6210         }
6211 
6212         /* ----------------------------------------------------------- */
6213         /*     IPE init and process                                    */
6214         /* ----------------------------------------------------------- */
6215         if(i4_thrd_id == 0)
6216         {
6217             PROFILE_START(&ps_hle_ctxt->profile_pre_enc_l0ipe[i4_resolution_id]);
6218         }
6219         if(i4_num_buf_prod_for_l0_ipe >= ps_multi_thrd->i4_delay_pre_me_btw_l0_ipe || i4_end_flag ||
6220            i4_out_flush_flag)
6221         {
6222             do
6223             {
6224                 /* Wait till previous frame(instance)'s IPE is processed */
6225                 {
6226                     ihevce_dmgr_chk_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_l0, i4_thrd_id);
6227                 }
6228 
6229                 /* Wait till current frame(instance)'s L1 and below layers are processed */
6230                 {
6231                     volatile WORD32 *pi4_cur_l1_complete =
6232                         &ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_ipe_idx];
6233 
6234                     while(1)
6235                     {
6236                         if(*pi4_cur_l1_complete)
6237                             break;
6238                     }
6239                 }
6240 
6241                 /* ----------------------------------------------------------- */
6242                 /*     L0 IPE qp init                                          */
6243                 /* ----------------------------------------------------------- */
6244 
6245                 /****** Lock the critical section for init ******/
6246                 {
6247                     WORD32 i4_status;
6248                     i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_l0_ipe_init);
6249 
6250                     if(OSAL_SUCCESS != i4_status)
6251                         return 0;
6252                 }
6253 
6254                 /* first thread that enters will calculate qp and write that to shared variable
6255                    that will be accessed by other threads */
6256                 if(ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx] == 0)
6257                 {
6258                     volatile WORD32 i4_is_qp_valid = -1;
6259                     WORD32 i4_update_qp;
6260                     WORD32 i4_cur_q_scale;
6261 
6262                     i4_cur_q_scale =
6263                         ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->i4_curr_frm_qp;
6264                     i4_cur_q_scale = ps_enc_ctxt->s_rc_quant.pi4_qp_to_qscale[i4_cur_q_scale];
6265                     i4_cur_q_scale = (i4_cur_q_scale + (1 << (QSCALE_Q_FAC_3 - 1))) >>
6266                                      QSCALE_Q_FAC_3;
6267                     /* Get free buffer to store L0 IPE output to enc loop */
6268                     ps_multi_thrd->ps_L0_IPE_curr_out_pre_enc =
6269                         (pre_enc_L0_ipe_encloop_ctxt_t *)ihevce_q_get_free_buff(
6270                             (void *)ps_enc_ctxt,
6271                             IHEVCE_L0_IPE_ENC_Q,
6272                             &ps_multi_thrd->i4_L0_IPE_out_buf_id,
6273                             BUFF_QUE_BLOCKING_MODE);
6274                     if(ps_enc_ctxt->ps_stat_prms->s_pass_prms.i4_pass != 2 &&
6275                        ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode != 3)
6276                     {
6277                         complexity_RC_reset_marking(
6278                             ps_enc_ctxt, i4_cur_ipe_idx, (i4_end_flag || i4_out_flush_flag));
6279                     }
6280                     if(1 == ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6281                                 ->s_input_buf.i4_inp_frm_data_valid_flag)
6282                     {
6283                         while(i4_is_qp_valid == -1)
6284                         {
6285                             /*this rate control call is outside mutex lock to avoid deadlock. If this acquires mutex lock enc will not be able to
6286                             populate qp*/
6287                             i4_is_qp_valid = ihevce_rc_check_is_pre_enc_qp_valid(
6288                                 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6289                                 (volatile WORD32 *)&ps_enc_ctxt->s_multi_thrd.i4_force_end_flag);
6290                             if(1 == ps_enc_ctxt->s_multi_thrd.i4_force_end_flag)
6291                             {
6292                                 /*** For force end condition break from this loop ***/
6293                                 i4_is_qp_valid = 1;
6294                                 break;
6295                             }
6296                         }
6297 
6298                         /*lock rate control context*/
6299                         osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
6300 
6301                         /* Qp query has to happen irrespective of using it or not since producer consumer logic will be disturbed */
6302                         i4_update_qp = ihevce_rc_pre_enc_qp_query(
6303                             (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6304                             &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_rc_lap_out,
6305                             0);
6306 
6307                         if(ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode != 3)
6308                         {
6309                             ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6310                                 ->s_rc_lap_out.i8_frm_satd_act_accum_L0_frm_L1 =
6311                                 ihevce_get_L0_satd_based_on_L1(
6312                                     ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6313                                         ->s_rc_lap_out.i8_frame_satd_by_act_L1_accum,
6314                                     ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6315                                         ->s_rc_lap_out.i4_num_pels_in_frame_considered,
6316                                     i4_cur_q_scale);
6317 
6318                             if(ps_enc_ctxt->ps_stat_prms->s_pass_prms.i4_pass != 2)
6319                             {
6320                                 if(ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6321                                            ->s_rc_lap_out.i4_rc_scene_type ==
6322                                        SCENE_TYPE_SCENE_CUT ||
6323                                    ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6324                                        ->s_rc_lap_out.i4_is_I_only_scd ||
6325                                    ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6326                                            ->s_rc_lap_out.i4_is_non_I_scd == 1)
6327                                 {
6328                                     float i_to_avg_rest_ratio;
6329                                     WORD32 i4_count = 0;
6330 
6331                                     while(1)
6332                                     {
6333                                         i_to_avg_rest_ratio = ihevce_get_i_to_avg_ratio(
6334                                             ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6335                                             &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6336                                                  ->s_rc_lap_out,
6337                                             1,
6338                                             0,
6339                                             0,
6340                                             ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6341                                                 ->s_rc_lap_out.ai4_offsets,
6342                                             0);
6343                                         /* HEVC_RC query rate control for qp */
6344                                         i4_update_qp = ihevce_get_L0_est_satd_based_scd_qp(
6345                                             ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6346                                             &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6347                                                  ->s_rc_lap_out,
6348                                             ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6349                                                 ->s_rc_lap_out.i8_frm_satd_act_accum_L0_frm_L1,
6350                                             i_to_avg_rest_ratio);
6351 
6352                                         ihevce_set_L0_scd_qp(
6353                                             ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6354                                             i4_update_qp);
6355 
6356                                         if(ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6357                                                    ->s_lap_out.i4_pic_type != IV_IDR_FRAME &&
6358                                            ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6359                                                    ->s_lap_out.i4_pic_type != IV_I_FRAME)
6360                                         {
6361                                             i4_update_qp +=
6362                                                 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6363                                                     ->s_lap_out.i4_temporal_lyr_id +
6364                                                 1;
6365 
6366                                             i4_update_qp =
6367                                                 CLIP3(i4_update_qp, MIN_HEVC_QP, MAX_HEVC_QP);
6368                                         }
6369 
6370                                         i4_count++;
6371                                         if((i4_update_qp ==
6372                                             ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6373                                                 ->s_rc_lap_out.i4_L0_qp) ||
6374                                            i4_count > 4)
6375                                             break;
6376 
6377                                         ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6378                                             ->s_rc_lap_out.i4_L0_qp = i4_update_qp;
6379                                     }
6380                                 }
6381                             }
6382                             else
6383                             {
6384                                 //i4_update_qp = ihevce_get_first_pass_qp(ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_lap_out.pv_frame_info);
6385                                 i4_update_qp = ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6386                                                    ->s_rc_lap_out.ps_frame_info->i4_rc_hevc_qp;
6387                             }
6388                         }
6389 
6390                         {
6391                             WORD32 i4_index = 0;
6392                             rc_lap_out_params_t *ps_rc_lap_temp =
6393                                 &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_rc_lap_out;
6394                             WORD32 i4_offset;
6395 
6396                             if(ps_rc_lap_temp->i4_rc_pic_type != IV_IDR_FRAME &&
6397                                ps_rc_lap_temp->i4_rc_pic_type != IV_I_FRAME)
6398                             {
6399                                 i4_index = ps_rc_lap_temp->i4_rc_temporal_lyr_id + 1;
6400                             }
6401                             i4_offset = ps_rc_lap_temp->ai4_offsets[i4_index];
6402                             ASSERT(i4_offset >= 0);
6403                             /* Map the current frame Qp to L0 Qp */
6404                             ps_rc_lap_temp->i4_L0_qp = i4_update_qp - i4_offset;
6405                         }
6406                         osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
6407                         ASSERT(ps_multi_thrd->i4_qp_update_l0_ipe == -1);
6408                         ps_multi_thrd->i4_qp_update_l0_ipe = i4_update_qp;
6409                         ps_multi_thrd->i4_rc_l0_qp = i4_update_qp;
6410                     }
6411                     ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6412                         ->s_lap_out.f_i_pic_lamda_modifier = CONST_LAMDA_MOD_VAL;
6413                 }
6414                 /* update qp only if it is not scene cut since it has already been
6415                    populated in L1 for scene cut frames */
6416                 if(1 == ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6417                             ->s_input_buf.i4_inp_frm_data_valid_flag &&
6418                    ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode != 3)
6419                 {
6420                     /*get relevant lambda params*/
6421                     ihevce_get_frame_lambda_prms(
6422                         ps_enc_ctxt,
6423                         ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx],
6424                         ps_multi_thrd->i4_qp_update_l0_ipe,
6425                         ps_enc_ctxt->s_runtime_src_prms.i4_field_pic,
6426                         ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_lap_out.i4_is_ref_pic,
6427                         ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6428                             ->s_lap_out.i4_temporal_lyr_id,
6429                         ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6430                             ->s_lap_out.f_i_pic_lamda_modifier,
6431                         0,
6432                         PRE_ENC_LAMBDA_TYPE);
6433 
6434                     ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->i4_curr_frm_qp =
6435                         ps_multi_thrd->i4_qp_update_l0_ipe;
6436                 }
6437                 /* Compute accumulated activity and strength */
6438                 if(1 == ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6439                             ->s_input_buf.i4_inp_frm_data_valid_flag &&
6440                    ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx] == 0)
6441                 {
6442                     ihevce_variance_calc_acc_activity(ps_enc_ctxt, i4_cur_ipe_idx);
6443                 }
6444 
6445                 /* Mark qp as read by last thread */
6446                 ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx]++;
6447                 if(ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx] ==
6448                    ps_multi_thrd->i4_num_pre_enc_proc_thrds)
6449                 {
6450                     ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx] = 0;
6451                     ps_multi_thrd->i4_qp_update_l0_ipe = -1;
6452                 }
6453 
6454                 /****** UnLock the critical section after deinit ******/
6455                 {
6456                     WORD32 i4_status;
6457                     i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_l0_ipe_init);
6458 
6459                     if(OSAL_SUCCESS != i4_status)
6460                         return 0;
6461                 }
6462 
6463                 if(1 == ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6464                             ->s_input_buf.i4_inp_frm_data_valid_flag)
6465                 {
6466                     WORD32 i4_slice_type =
6467                         (WORD32)ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]
6468                             ->s_slice_hdr.i1_slice_type;
6469                     WORD32 i4_quality_preset =
6470                         (WORD32)ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6471                             ->s_lap_out.i4_quality_preset;
6472                     WORD32 i4_temporal_layer_id =
6473                         (WORD32)ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6474                             ->s_lap_out.i4_temporal_lyr_id;
6475 #if DISABLE_L0_IPE_INTRA_IN_BPICS
6476                     if(1 != ((i4_quality_preset == IHEVCE_QUALITY_P6) &&
6477                              (i4_temporal_layer_id > TEMPORAL_LAYER_DISABLE)))
6478 #endif
6479                     {
6480                         UWORD8 i1_cu_qp_delta_enabled_flag =
6481                             ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_cu_level_rc;
6482 
6483                         ihevce_populate_ipe_frame_init(
6484                             ps_enc_ctxt->s_module_ctxt.pv_ipe_ctxt,
6485                             ps_enc_ctxt->ps_stat_prms,
6486                             ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->i4_curr_frm_qp,
6487                             i4_slice_type,
6488                             i4_thrd_id,
6489                             ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx],
6490                             i1_cu_qp_delta_enabled_flag,
6491                             &ps_enc_ctxt->s_rc_quant,
6492                             i4_quality_preset,
6493                             i4_temporal_layer_id,
6494                             &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_lap_out);
6495 
6496                         ihevce_ipe_process(
6497                             ps_enc_ctxt->s_module_ctxt.pv_ipe_ctxt,
6498                             &ps_enc_ctxt->s_frm_ctb_prms,
6499                             &ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->as_lambda_prms[0],
6500                             ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx],
6501                             ps_multi_thrd->ps_L0_IPE_curr_out_pre_enc,
6502                             ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->ps_ctb_analyse,
6503                             ps_multi_thrd->ps_L0_IPE_curr_out_pre_enc->ps_ipe_analyse_ctb,
6504                             &ps_enc_ctxt->s_multi_thrd,
6505                             i4_slice_type,
6506                             ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->ps_layer1_buf,
6507                             ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->ps_layer2_buf,
6508                             ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->ps_ed_ctb_l1,
6509                             i4_thrd_id,
6510                             i4_cur_ipe_idx);
6511                     }
6512                 }
6513 
6514                 /* ----------------------------------------------------------- */
6515                 /*     pre-enc de-init                                         */
6516                 /* ----------------------------------------------------------- */
6517 
6518                 /****** Lock the critical section for deinit ******/
6519                 {
6520                     WORD32 i4_status;
6521                     i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_deinit);
6522 
6523                     if(OSAL_SUCCESS != i4_status)
6524                         return 0;
6525                 }
6526 
6527                 ps_multi_thrd->ai4_num_thrds_processed_pre_enc[i4_cur_ipe_idx]++;
6528                 if(ps_multi_thrd->ai4_num_thrds_processed_pre_enc[i4_cur_ipe_idx] ==
6529                    ps_multi_thrd->i4_num_pre_enc_proc_thrds)
6530                 {
6531                     ps_multi_thrd->ai4_pre_enc_deinit_done[i4_cur_ipe_idx] = 0;
6532                     ps_multi_thrd->ai4_num_thrds_processed_pre_enc[i4_cur_ipe_idx] = 0;
6533 
6534                     /* reset the init flag so that init happens by the first thread for the
6535                        next frame of same ping_pnog instnace */
6536                     ps_multi_thrd->ai4_pre_enc_init_done[i4_cur_ipe_idx] = 0;
6537                 }
6538 
6539                 /* de-init */
6540                 if(0 == ps_multi_thrd->ai4_pre_enc_deinit_done[i4_cur_ipe_idx])
6541                 {
6542                     ihevce_lap_enc_buf_t *ps_curr_inp =
6543                         ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx];
6544                     pre_enc_me_ctxt_t *ps_curr_out =
6545                         ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx];
6546 
6547                     /* set the flag saying de init is done so that other cores dont do it */
6548                     ps_multi_thrd->ai4_pre_enc_deinit_done[i4_cur_ipe_idx] = 1;
6549 
6550                     if(1 == ps_curr_out->i4_frm_proc_valid_flag)
6551                     {
6552                         LWORD64 frame_acc_satd_by_modqp;
6553                         float L1_full_processed_ratio;
6554 
6555                         if(ps_curr_inp->s_rc_lap_out.i8_satd_by_act_L1_accum_evaluated)
6556                         {
6557                             L1_full_processed_ratio =
6558                                 ((float)ps_curr_inp->s_rc_lap_out.i8_frame_satd_by_act_L1_accum /
6559                                  ps_curr_inp->s_rc_lap_out.i8_satd_by_act_L1_accum_evaluated);
6560                         }
6561                         else
6562                         {
6563                             L1_full_processed_ratio = 1.0;
6564                         }
6565                         /* Get frame-level satd cost and mode bit cost from IPE */
6566                         ps_curr_out->i8_frame_acc_satd_cost = ihevce_ipe_get_frame_intra_satd_cost(
6567                             ps_enc_ctxt->s_module_ctxt.pv_ipe_ctxt,
6568                             &frame_acc_satd_by_modqp,
6569                             &ps_curr_inp->s_rc_lap_out.i8_est_I_pic_header_bits,
6570                             &ps_curr_inp->s_lap_out.i8_frame_level_activity_fact,
6571                             &ps_curr_inp->s_lap_out.i8_frame_l0_acc_satd);
6572 
6573                         if((ps_curr_inp->s_lap_out.i4_quality_preset == IHEVCE_QUALITY_P6) &&
6574                            (ps_curr_inp->s_lap_out.i4_temporal_lyr_id > TEMPORAL_LAYER_DISABLE))
6575                         {
6576                             ps_curr_inp->s_rc_lap_out.i8_est_I_pic_header_bits = -1;
6577                         }
6578 
6579                         {
6580                             WORD32 i4_cur_q_scale = (ps_enc_ctxt->s_rc_quant.pi4_qp_to_qscale
6581                                                          [ps_enc_ctxt->s_multi_thrd.i4_rc_l0_qp +
6582                                                           ps_enc_ctxt->s_rc_quant.i1_qp_offset] +
6583                                                      (1 << (QSCALE_Q_FAC_3 - 1))) >>
6584                                                     QSCALE_Q_FAC_3;
6585 
6586                             /* calculate satd/act_fac = satd/qm * (qp_used_at_L0_analysis) */
6587                             ps_curr_inp->s_rc_lap_out.i8_frame_satd_act_accum =
6588                                 frame_acc_satd_by_modqp * i4_cur_q_scale;
6589                         }
6590 
6591                         /* Because of early intra inter decision, L0 intra analysis might not happen for entire frame, correct the error
6592                            based on L1 data */
6593                         ps_curr_inp->s_rc_lap_out.i8_est_I_pic_header_bits = (LWORD64)(
6594                             ps_curr_inp->s_rc_lap_out.i8_est_I_pic_header_bits *
6595                             L1_full_processed_ratio);
6596 
6597                         if(L1_full_processed_ratio < 1.5)
6598                         {
6599                             ps_curr_inp->s_rc_lap_out.i8_frame_satd_act_accum = (LWORD64)(
6600                                 ps_curr_inp->s_rc_lap_out.i8_frame_satd_act_accum *
6601                                 L1_full_processed_ratio);
6602                         }
6603                         else
6604                         {
6605                             /* This is the case when too many candidates would not have gone through intra analysis, scaling based on L1 is found to be inappropriate,
6606                             Hence directly estimating L0 satd from L1 satd */
6607                             ps_curr_inp->s_rc_lap_out.i8_frame_satd_act_accum =
6608                                 ps_curr_inp->s_rc_lap_out.i8_frm_satd_act_accum_L0_frm_L1;
6609                         }
6610                     }
6611 
6612                     /* register the current input buffer to be cnosumed by encode group threads */
6613                     ps_curr_out->curr_inp_buf_id =
6614                         ps_multi_thrd->ai4_in_buf_id_pre_enc[i4_cur_ipe_idx];
6615                     ps_curr_out->ps_curr_inp = ps_curr_inp;
6616 
6617                     /* set the output buffer as produced */
6618                     ihevce_q_set_buff_prod(
6619                         (void *)ps_enc_ctxt,
6620                         IHEVCE_PRE_ENC_ME_Q,
6621                         ps_multi_thrd->ai4_out_buf_id_pre_enc[i4_cur_ipe_idx]);
6622 
6623                     /* set the output buffer of L0 IPE as produced */
6624                     ihevce_q_set_buff_prod(
6625                         (void *)ps_enc_ctxt,
6626                         IHEVCE_L0_IPE_ENC_Q,
6627                         ps_multi_thrd->i4_L0_IPE_out_buf_id);
6628 
6629                     /* update flag indicating ipe is done */
6630                     ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_l0);
6631                 }
6632 
6633                 {
6634                     /* index increment */
6635                     i4_cur_ipe_idx = i4_cur_ipe_idx + 1;
6636 
6637                     /* wrap around case */
6638                     if(i4_cur_ipe_idx >= ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe)
6639                     {
6640                         i4_cur_ipe_idx = 0;
6641                     }
6642 
6643                     i4_num_buf_prod_for_l0_ipe--;
6644                 }
6645                 /*NOTE: update of above indices should mark end if ipe.do not access below this*/
6646 
6647                 /****** UnLock the critical section after deinit ******/
6648                 {
6649                     WORD32 i4_status;
6650                     i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_pre_enc_deinit);
6651 
6652                     if(OSAL_SUCCESS != i4_status)
6653                         return 0;
6654                 }
6655 
6656                 if(1 == ps_multi_thrd->i4_force_end_flag)
6657                 {
6658                     i4_end_flag = 1;
6659                     break;
6660                 }
6661             } while((i4_end_flag || i4_out_flush_flag) && i4_num_buf_prod_for_l0_ipe);
6662         }
6663         if(i4_thrd_id == 0)
6664         {
6665             PROFILE_STOP(&ps_hle_ctxt->profile_pre_enc_l0ipe[i4_resolution_id], NULL);
6666         }
6667     }
6668 
6669     return 0;
6670 }
6671 
calc_l1_level_hme_intra_sad_different_qp(enc_ctxt_t * ps_enc_ctxt,pre_enc_me_ctxt_t * ps_curr_out,ihevce_lap_enc_buf_t * ps_curr_inp,WORD32 i4_tot_ctb_l1_x,WORD32 i4_tot_ctb_l1_y)6672 void calc_l1_level_hme_intra_sad_different_qp(
6673     enc_ctxt_t *ps_enc_ctxt,
6674     pre_enc_me_ctxt_t *ps_curr_out,
6675     ihevce_lap_enc_buf_t *ps_curr_inp,
6676     WORD32 i4_tot_ctb_l1_x,
6677     WORD32 i4_tot_ctb_l1_y)
6678 {
6679     ihevce_ed_ctb_l1_t *ps_ed_ctb_l1;
6680     WORD32 i4_qp_counter, i4_qp_start = 0, i4_qp_end = 0, i, i4_j, i4_new_frame_qp;
6681     LWORD64 i8_l1_intra_sad_nc_accounted = 0, cur_intra_sad, raw_hme_sad = 0;
6682     LWORD64 cur_hme_sad = 0, cur_hme_sad_for_offset = 0, acc_hme_l1_sad = 0,
6683             acc_hme_l1_sad_for_offset = 0;
6684     i4_qp_start = 1;
6685     i4_qp_end = 51;
6686 
6687     for(i4_qp_counter = i4_qp_start; i4_qp_counter <= i4_qp_end; i4_qp_counter = i4_qp_counter + 3)
6688     {
6689         i8_l1_intra_sad_nc_accounted = 0;
6690         cur_intra_sad = 0;
6691         raw_hme_sad = 0;
6692         cur_hme_sad = 0;
6693         cur_hme_sad_for_offset = 0;
6694         acc_hme_l1_sad = 0;
6695         ps_ed_ctb_l1 = ps_curr_out->ps_ed_ctb_l1;
6696         i4_new_frame_qp = i4_qp_counter;
6697         acc_hme_l1_sad = 0;
6698 
6699         for(i = 0; i < (i4_tot_ctb_l1_x * i4_tot_ctb_l1_y); i += 1)
6700         {
6701             for(i4_j = 0; i4_j < 16; i4_j++)
6702             {
6703                 if(ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j] != -1)
6704                 {
6705                     ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j] >= 0);
6706                     if(ps_curr_inp->s_rc_lap_out.i4_rc_pic_type != IV_I_FRAME &&
6707                        ps_curr_inp->s_rc_lap_out.i4_rc_pic_type != IV_IDR_FRAME)
6708                     {
6709                         /*When l1 is disabled for B pics i4_best_sad_8x8_l1_ipe is set to max value always,
6710                         so will enter this path even for incomplete ctb, hence the assert holdsto good only for P pic  */
6711                         if(ps_curr_inp->s_rc_lap_out.i4_rc_quality_preset == IHEVCE_QUALITY_P6)
6712                         {
6713                             if(ps_curr_inp->s_rc_lap_out.i4_rc_pic_type == IV_P_FRAME)
6714                             {
6715                                 ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j] >= 0);
6716                                 ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_me_for_decide[i4_j] >= 0);
6717                             }
6718                         }
6719                         else
6720                         {
6721                             ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j] >= 0);
6722                             ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_me_for_decide[i4_j] >= 0);
6723                         }
6724 
6725 #if 1  //DISABLE_L1_L2_IPE_INTRA_IN_BPICS && RC_DEPENDENCY_FOR_BPIC
6726                         if((ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j] != -1))
6727 #endif
6728                         {
6729                             cur_hme_sad = ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j] -
6730                                           (QP2QUANT_MD[i4_new_frame_qp] << 3);
6731                         }
6732                         raw_hme_sad += ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j];
6733 
6734                         if(cur_hme_sad > 0)
6735                             acc_hme_l1_sad += cur_hme_sad;
6736                     }
6737                     if(cur_hme_sad_for_offset > 0)
6738                     {
6739                         acc_hme_l1_sad_for_offset += cur_hme_sad_for_offset;
6740                     }
6741                     ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j] >= 0);
6742                     /*intra sad is scaled by 1.17 to be account for 1/3 vs 1/6th rounding*/
6743                     cur_intra_sad = (LWORD64)(
6744                         (ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j] * 1.17) -
6745                         (QP2QUANT_MD[i4_new_frame_qp] << 3));
6746 
6747                     if(cur_intra_sad > 0)
6748                         i8_l1_intra_sad_nc_accounted += cur_intra_sad;
6749                 }
6750             }
6751             ps_ed_ctb_l1 += 1;
6752         }
6753         if((ps_curr_inp->s_rc_lap_out.i4_rc_quality_preset == IHEVCE_QUALITY_P6) &&
6754            (ps_curr_inp->s_rc_lap_out.i4_rc_pic_type == IV_B_FRAME))
6755         {
6756             ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter] = -1;
6757             ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter + 1] = -1;
6758             ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter + 2] = -1;
6759         }
6760         else
6761         {
6762             ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter] =
6763                 i8_l1_intra_sad_nc_accounted;
6764             ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter + 1] =
6765                 i8_l1_intra_sad_nc_accounted;
6766             ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter + 2] =
6767                 i8_l1_intra_sad_nc_accounted;
6768         }
6769         ps_curr_inp->s_rc_lap_out.ai8_frame_acc_coarse_me_sad[i4_qp_counter] = acc_hme_l1_sad;
6770         ps_curr_inp->s_rc_lap_out.ai8_frame_acc_coarse_me_sad[i4_qp_counter + 1] = acc_hme_l1_sad;
6771         ps_curr_inp->s_rc_lap_out.ai8_frame_acc_coarse_me_sad[i4_qp_counter + 2] = acc_hme_l1_sad;
6772         ps_curr_inp->s_rc_lap_out.i8_raw_l1_coarse_me_sad = raw_hme_sad;
6773     }
6774 }
6775