• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * Copyright (C) 2018 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************
18  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19 */
20 
21 /*!
22 ******************************************************************************
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                                         (ps_enc_ctxt->ps_stat_prms->s_out_strm_prms
3102                                              .i4_sei_enable_flag == 1) &&
3103                                         (ps_enc_ctxt->ps_stat_prms->s_out_strm_prms
3104                                              .i4_decoded_pic_hash_sei_flag != 0);
3105 
3106                                     /* Deblock a picture for all reference frames unconditionally. */
3107                                     /* Deblock non ref if psnr compute or save recon is enabled    */
3108                                     ps_frm_recon->i4_deblk_pad_hpel_cur_pic =
3109                                         ps_frm_recon->i4_is_reference ||
3110                                         (ps_enc_ctxt->ps_stat_prms->i4_save_recon) ||
3111                                         (1 == sei_hash_enabled);
3112                                 }
3113 
3114                                 ps_frm_recon->s_yuv_buf_desc.i4_y_ht =
3115                                     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht;
3116                                 ps_frm_recon->s_yuv_buf_desc.i4_uv_ht =
3117                                     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht >>
3118                                     ((ps_enc_ctxt->s_runtime_src_prms.i4_chr_format ==
3119                                       IV_YUV_422SP_UV)
3120                                          ? 0
3121                                          : 1);
3122                                 ps_frm_recon->s_yuv_buf_desc.i4_y_wd =
3123                                     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd;
3124                                 ps_frm_recon->s_yuv_buf_desc.i4_uv_wd =
3125                                     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd;
3126                                 ps_frm_recon->s_yuv_buf_desc.i4_y_strd =
3127                                     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd +
3128                                     (PAD_HORZ << 1);
3129                                 ps_frm_recon->s_yuv_buf_desc.i4_uv_strd =
3130                                     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd +
3131                                     (PAD_HORZ << 1);
3132 
3133                                 /* reset the row_frm dep mngr for ME reverse sync for reference bitrate */
3134                                 if(i == 0)
3135                                 {
3136                                     ihevce_dmgr_map_rst_sync(ps_frm_recon->pv_dep_mngr_recon);
3137                                 }
3138 
3139                                 ps_enc_ctxt->s_multi_thrd.ps_frm_recon[i4_enc_frm_id][i] =
3140                                     ps_frm_recon;
3141                             }
3142                         }
3143                         /* Reference buffer management and reference list creation */
3144                         /* This needs to be created for each bit-rate since the reconstructed output is
3145                         different for all bit-rates. ME uses only 0th instnace ref list */
3146                         for(i = i4_num_bitrates - 1; i >= 0; i--)
3147                         {
3148                             ihevce_manage_ref_pics(
3149                                 ps_enc_ctxt,
3150                                 ps_curr_inp,
3151                                 &ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id]
3152                                      ->s_slice_hdr,
3153                                 i4_me_frm_id,
3154                                 i4_thrd_id,
3155                                 i); /* bitrate instance ID */
3156                         }
3157                         /*query of qp to be moved just before encoding starts*/
3158                         i4_ref_cur_qp = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]
3159                                             ->i4_curr_frm_qp;
3160                         /* The Qp populated in Pre enc stage needs to overwritten with Qp
3161                         queried from rate control*/
3162                     }
3163                     else
3164                     {
3165                         i4_ref_cur_qp = 0;
3166                     }
3167 
3168                     /* call the core encoding loop */
3169                     ihevce_frame_init(
3170                         ps_enc_ctxt,
3171                         ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id],
3172                         ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id],
3173                         i4_ref_cur_qp,
3174                         i4_me_frm_id,
3175                         i4_thrd_id);
3176                 }
3177 
3178                 ps_enc_ctxt->s_multi_thrd.ai4_me_master_done_flag[i4_me_frm_id] = 1;
3179             }
3180         }
3181 
3182         /************************************/
3183         /******  EXIT CRITICAL SECTION ******/
3184         /************************************/
3185 
3186         /****** Unlock the critical section ******/
3187         if(NULL != ps_enc_ctxt->s_multi_thrd.apv_mutex_handle[i4_me_frm_id])
3188         {
3189             result = osal_mutex_unlock(ps_enc_ctxt->s_multi_thrd.apv_mutex_handle[i4_me_frm_id]);
3190             if(OSAL_SUCCESS != result)
3191                 return 0;
3192         }
3193 
3194         if((1 == ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.i4_mres_single_out) &&
3195            (1 == ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]
3196                      ->ps_curr_inp->s_lap_out.i4_first_frm_new_res))
3197         {
3198             /* Reset the enc frame rc id whenver change in resolution happens */
3199             i4_enc_frm_id_rc = 0;
3200         }
3201 
3202         /*update end flag for each thread */
3203         i4_me_end_flag = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->i4_end_flag;
3204         if(NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id] &&
3205            NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id] &&
3206            NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_L0_ipe_inp_prms[i4_me_frm_id])
3207         {
3208             pre_enc_me_ctxt_t *ps_curr_inp_prms;
3209             pre_enc_L0_ipe_encloop_ctxt_t *ps_curr_L0_IPE_inp_prms;
3210             ihevce_lap_enc_buf_t *ps_curr_inp;
3211 
3212             /* get the current  buffer pointer  */
3213             ps_curr_inp_prms = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id];
3214             ps_curr_L0_IPE_inp_prms =
3215                 ps_enc_ctxt->s_multi_thrd.aps_cur_L0_ipe_inp_prms[i4_me_frm_id];
3216             ps_curr_inp = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->ps_curr_inp;
3217             if(i4_thrd_id == 0)
3218             {
3219                 PROFILE_START(&ps_hle_ctxt->profile_enc_me[ps_enc_ctxt->i4_resolution_id]);
3220             }
3221 
3222             /* -------------------------------------------------- */
3223             /*    Motion estimation (enc layer) of entire frame   */
3224             /* -------------------------------------------------- */
3225             if((i4_me_end_flag == 0) &&
3226                (1 ==
3227                 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->i4_frm_proc_valid_flag))
3228             {
3229                 /* Init i4_is_prev_frame_reference for the next P-frame */
3230                 me_master_ctxt_t *ps_master_ctxt =
3231                     (me_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_me_ctxt;
3232 
3233                 /* get the current thread ctxt pointer */
3234                 me_ctxt_t *ps_ctxt = ps_master_ctxt->aps_me_ctxt[i4_thrd_id];
3235 
3236                 me_frm_ctxt_t *ps_frm_ctxt = ps_ctxt->aps_me_frm_prms[i4_me_frm_id];
3237 
3238                 if(ISLICE != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]
3239                                  ->s_slice_hdr.i1_slice_type)
3240                 {
3241                     ihevce_me_process(
3242                         ps_enc_ctxt->s_module_ctxt.pv_me_ctxt,
3243                         ps_curr_inp,
3244                         ps_curr_inp_prms->ps_ctb_analyse,
3245                         ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id],
3246                         ps_curr_inp_prms->plf_intra_8x8_cost,
3247                         ps_curr_L0_IPE_inp_prms->ps_ipe_analyse_ctb,
3248                         ps_curr_L0_IPE_inp_prms,
3249                         ps_curr_inp_prms->pv_me_lyr_ctxt,
3250                         &ps_enc_ctxt->s_multi_thrd,
3251                         ((ps_enc_ctxt->s_multi_thrd.i4_num_me_frm_pllel == 1) ? 0 : 1),
3252                         i4_thrd_id,
3253                         i4_me_frm_id);
3254                 }
3255                 else
3256                 {
3257                     /* Init i4_is_prev_frame_reference for the next P-frame */
3258                     me_master_ctxt_t *ps_master_ctxt =
3259                         (me_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_me_ctxt;
3260 
3261                     /* get the current thread ctxt pointer */
3262                     me_ctxt_t *ps_ctxt = ps_master_ctxt->aps_me_ctxt[i4_thrd_id];
3263 
3264                     me_frm_ctxt_t *ps_frm_ctxt = ps_ctxt->aps_me_frm_prms[i4_me_frm_id];
3265 
3266                     multi_thrd_ctxt_t *ps_multi_thrd_ctxt = &ps_enc_ctxt->s_multi_thrd;
3267 
3268                     if(ps_enc_ctxt->s_multi_thrd.i4_num_me_frm_pllel != 1)
3269                     {
3270                         ps_frm_ctxt->i4_is_prev_frame_reference = 0;
3271                     }
3272                     else
3273                     {
3274                         ps_frm_ctxt->i4_is_prev_frame_reference =
3275                             ps_multi_thrd_ctxt->aps_cur_inp_me_prms[i4_me_frm_id]
3276                                 ->ps_curr_inp->s_lap_out.i4_is_ref_pic;
3277                     }
3278                 }
3279             }
3280             if(i4_thrd_id == 0)
3281             {
3282                 PROFILE_STOP(&ps_hle_ctxt->profile_enc_me[ps_enc_ctxt->i4_resolution_id], NULL);
3283             }
3284         }
3285         /************************************/
3286         /******  ENTER CRITICAL SECTION *****/
3287         /************************************/
3288         {
3289             WORD32 result_frame_init;
3290             void *pv_mutex_handle_frame_init;
3291 
3292             /* Create mutex for locking non-reentrant sections      */
3293             pv_mutex_handle_frame_init =
3294                 ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_me_end[i4_me_frm_id];
3295 
3296             /****** Lock the critical section ******/
3297             if(NULL != pv_mutex_handle_frame_init)
3298             {
3299                 result_frame_init = osal_mutex_lock(pv_mutex_handle_frame_init);
3300 
3301                 if(OSAL_SUCCESS != result_frame_init)
3302                     return 0;
3303             }
3304         }
3305 
3306         if(0 == ps_enc_ctxt->s_multi_thrd.ai4_me_enc_buff_prod_flag[i4_me_frm_id])
3307         {
3308             /* ------- set buffer produced from me_enc que ------------ */
3309             ihevce_q_set_buff_prod(
3310                 ps_enc_ctxt,
3311                 IHEVCE_ME_ENC_RDOPT_Q,
3312                 ps_enc_ctxt->s_multi_thrd.ai4_me_out_buf_id[i4_me_frm_id]);
3313 
3314             ps_enc_ctxt->s_multi_thrd.ai4_me_enc_buff_prod_flag[i4_me_frm_id] = 1;
3315         }
3316         if(NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id] &&
3317            NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id])
3318         {
3319             ihevce_lap_enc_buf_t *ps_curr_inp;
3320 
3321             WORD32 first_field = 1;
3322 
3323             /* Increment the counter to keep track of no of threads exiting the current mutex*/
3324             ps_enc_ctxt->s_multi_thrd.me_num_thrds_exited[i4_me_frm_id]++;
3325 
3326             ps_curr_inp = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->ps_curr_inp;
3327             /* Last slave thread will reset the master done frame init flag and set the prev
3328             * frame me done flag for curr frame
3329             */
3330             if(ps_enc_ctxt->s_multi_thrd.me_num_thrds_exited[i4_me_frm_id] ==
3331                ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds)
3332             {
3333                 ps_enc_ctxt->s_multi_thrd.me_num_thrds_exited[i4_me_frm_id] = 0;
3334 
3335                 ps_enc_ctxt->s_multi_thrd.ai4_me_master_done_flag[i4_me_frm_id] = 0;
3336 
3337                 /* Update Dyn. Vert. Search prms for P Pic. */
3338                 if(IV_P_FRAME == ps_curr_inp->s_lap_out.i4_pic_type)
3339                 {
3340                     WORD32 i4_idx_dvsr_p = ps_enc_ctxt->s_multi_thrd.i4_idx_dvsr_p;
3341                     /* Sanity Check */
3342                     ASSERT(ps_curr_inp->s_lap_out.i4_pic_type < IV_IP_FRAME);
3343 
3344                     /*  Frame END processing for Dynamic Vertival Search    */
3345                     ihevce_l0_me_frame_end(
3346                         ps_enc_ctxt->s_module_ctxt.pv_me_ctxt,
3347                         i4_idx_dvsr_p,
3348                         ps_curr_inp->s_lap_out.i4_display_num,
3349                         i4_me_frm_id);
3350 
3351                     ps_enc_ctxt->s_multi_thrd.i4_idx_dvsr_p++;
3352                     if(ps_enc_ctxt->s_multi_thrd.i4_idx_dvsr_p == NUM_SG_INTERLEAVED)
3353                     {
3354                         ps_enc_ctxt->s_multi_thrd.i4_idx_dvsr_p = 0;
3355                     }
3356                 }
3357                 if(1 == ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]
3358                             ->i4_frm_proc_valid_flag)
3359                 {
3360                     /* Init i4_is_prev_frame_reference for the next P-frame */
3361                     me_master_ctxt_t *ps_master_ctxt =
3362                         (me_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_me_ctxt;
3363 
3364                     /* get the current thread ctxt pointer */
3365                     me_ctxt_t *ps_ctxt = ps_master_ctxt->aps_me_ctxt[i4_thrd_id];
3366 
3367                     me_frm_ctxt_t *ps_frm_ctxt = ps_ctxt->aps_me_frm_prms[i4_me_frm_id];
3368 
3369                     ps_frm_ctxt->ps_curr_descr->aps_layers[0]->i4_non_ref_free = 1;
3370                 }
3371                 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id] = NULL;
3372                 ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id] = NULL;
3373                 ps_enc_ctxt->s_multi_thrd.aps_cur_L0_ipe_inp_prms[i4_me_frm_id] = NULL;
3374                 ps_enc_ctxt->s_multi_thrd.ai4_me_enc_buff_prod_flag[i4_me_frm_id] = 0;
3375                 ps_enc_ctxt->s_multi_thrd.ai4_me_master_done_flag[i4_me_frm_id] = 0;
3376 
3377                 /* Set me processing done for curr frame in the dependency manager */
3378                 ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_me_done);
3379             }
3380         }
3381         /************************************/
3382         /******  EXIT CRITICAL SECTION ******/
3383         /************************************/
3384 
3385         {
3386             void *pv_mutex_handle_frame_init;
3387 
3388             /* Create mutex for locking non-reentrant sections      */
3389             pv_mutex_handle_frame_init =
3390                 ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_me_end[i4_me_frm_id];
3391             /****** Unlock the critical section ******/
3392             if(NULL != pv_mutex_handle_frame_init)
3393             {
3394                 result = osal_mutex_unlock(pv_mutex_handle_frame_init);
3395                 if(OSAL_SUCCESS != result)
3396                     return 0;
3397             }
3398         }
3399         /* -------------------------------------------- */
3400         /*        Encode Loop of entire frame           */
3401         /* -------------------------------------------- */
3402         ASSERT(ps_enc_ctxt->s_multi_thrd.i4_num_enc_loop_frm_pllel <= MAX_NUM_ENC_LOOP_PARALLEL);
3403 
3404         if(1 == ps_enc_ctxt->s_multi_thrd.i4_num_enc_loop_frm_pllel)
3405         {
3406             pv_dep_mngr_prev_frame_done = ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_prev_frame_done[0];
3407         }
3408         else
3409         {
3410             pv_dep_mngr_prev_frame_done =
3411                 ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_prev_frame_done[i4_enc_frm_id];
3412         }
3413         /* Wait till the prev frame enc loop is completed*/
3414         {
3415             ihevce_dmgr_chk_frm_frm_sync(pv_dep_mngr_prev_frame_done, ps_thrd_ctxt->i4_thrd_id);
3416         }
3417 
3418         /************************************/
3419         /****** ENTER CRITICAL SECTION ******/
3420         /************************************/
3421         {
3422             WORD32 result_frame_init;
3423             void *pv_mutex_handle_frame_init;
3424 
3425             /* Create mutex for locking non-reentrant sections      */
3426             pv_mutex_handle_frame_init =
3427                 ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_frame_init[i4_enc_frm_id];
3428 
3429             /****** Lock the critical section ******/
3430             if(NULL != pv_mutex_handle_frame_init)
3431             {
3432                 result_frame_init = osal_mutex_lock(pv_mutex_handle_frame_init);
3433 
3434                 if(OSAL_SUCCESS != result_frame_init)
3435                     return 0;
3436             }
3437         }
3438 
3439         {
3440             ihevce_lap_enc_buf_t *ps_curr_inp = NULL;
3441             pre_enc_me_ctxt_t *ps_curr_inp_from_me = NULL;
3442             me_enc_rdopt_ctxt_t *ps_curr_inp_enc = NULL;
3443             pre_enc_L0_ipe_encloop_ctxt_t *ps_curr_L0_IPE_inp_prms = NULL;
3444             recon_pic_buf_t *(*aps_ref_list)[HEVCE_MAX_REF_PICS * 2];
3445             WORD32 ai4_cur_qp[IHEVCE_MAX_NUM_BITRATES] = { 0 };
3446             WORD32 i4_field_pic = ps_enc_ctxt->s_runtime_src_prms.i4_field_pic;
3447             WORD32 first_field = 1;
3448             WORD32 result_frame_init;
3449             void *pv_mutex_handle_frame_init;
3450 
3451             /* Create mutex for locking non-reentrant sections      */
3452             pv_mutex_handle_frame_init =
3453                 ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_frame_init[i4_enc_frm_id];
3454 
3455             //aquire and initialize -> output and recon buffers
3456             if(ps_enc_ctxt->s_multi_thrd.enc_master_done_frame_init[i4_enc_frm_id] == 0)
3457             {
3458                 WORD32
3459                     i4_bitrate_ctr;  //bit-rate instance counter (for loop variable) [0->reference bit-rate, 1,2->auxiliarty bit-rates]
3460                 /* ------- get the input prms buffer from me que ------------ */
3461                 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] =
3462                     (me_enc_rdopt_ctxt_t *)ihevce_q_get_filled_buff(
3463                         ps_enc_ctxt,
3464                         IHEVCE_ME_ENC_RDOPT_Q,
3465                         &ps_enc_ctxt->s_multi_thrd.i4_enc_in_buf_id[i4_enc_frm_id],
3466                         BUFF_QUE_BLOCKING_MODE);
3467                 i4_enc_end_flag =
3468                     ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]->i4_end_flag;
3469 
3470                 ASSERT(ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] != NULL);
3471 
3472                 if(ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] != NULL)
3473                 {
3474                     ps_curr_inp =
3475                         ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]->ps_curr_inp;
3476                     ps_curr_inp_from_me =
3477                         ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3478                             ->ps_curr_inp_from_me_prms;
3479                     ps_curr_inp_enc = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id];
3480                     ps_curr_L0_IPE_inp_prms =
3481                         ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3482                             ->ps_curr_inp_from_l0_ipe_prms;
3483 
3484                     for(i4_bitrate_ctr = 0; i4_bitrate_ctr < i4_num_bitrates; i4_bitrate_ctr++)
3485                     {
3486                         iv_enc_recon_data_buffs_t
3487                             *ps_recon_out[MAX_NUM_ENC_LOOP_PARALLEL][IHEVCE_MAX_NUM_BITRATES] = {
3488                                 { NULL }
3489                             };
3490                         frm_proc_ent_cod_ctxt_t *ps_curr_out[MAX_NUM_ENC_LOOP_PARALLEL]
3491                                                             [IHEVCE_MAX_NUM_BITRATES] = { { NULL } };
3492 
3493                         /* ------- get free output buffer from Frame buffer que ---------- */
3494                         /* There is a separate queue for each bit-rate instnace. The output
3495                     buffer is acquired from the corresponding queue based on the
3496                     bitrate instnace */
3497                         ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr] =
3498                             (frm_proc_ent_cod_ctxt_t *)ihevce_q_get_free_buff(
3499                                 (void *)ps_enc_ctxt,
3500                                 IHEVCE_FRM_PRS_ENT_COD_Q +
3501                                     i4_bitrate_ctr, /*decides the buffer queue */
3502                                 &ps_enc_ctxt->s_multi_thrd.out_buf_id[i4_enc_frm_id][i4_bitrate_ctr],
3503                                 BUFF_QUE_BLOCKING_MODE);
3504                         ps_enc_ctxt->s_multi_thrd.is_out_buf_freed[i4_enc_frm_id][i4_bitrate_ctr] =
3505                             0;
3506                         ps_enc_ctxt->s_multi_thrd
3507                             .ps_curr_out_enc_grp[i4_enc_frm_id][i4_bitrate_ctr] =
3508                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr];
3509                         //ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_enc_order_num = ps_curr_inp->s_lap_out.i4_enc_order_num;
3510                         /*registered User Data Call*/
3511                         if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_payload_enable_flag)
3512                         {
3513                             ihevce_fill_sei_payload(
3514                                 ps_enc_ctxt,
3515                                 ps_curr_inp,
3516                                 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]);
3517                         }
3518 
3519                         /*derive end flag and input valid flag in output buffer */
3520                         if(NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id])
3521                         {
3522                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_end_flag =
3523                                 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3524                                     ->i4_end_flag;
3525                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_frm_proc_valid_flag =
3526                                 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3527                                     ->i4_frm_proc_valid_flag;
3528 
3529                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_out_flush_flag =
3530                                 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3531                                     ->ps_curr_inp->s_lap_out.i4_out_flush_flag;
3532                         }
3533 
3534                         /*derive other parameters in output buffer */
3535                         if(NULL != ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr] &&
3536                            (NULL != ps_curr_inp_from_me) &&
3537                            (1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag) &&
3538                            (i4_enc_end_flag == 0))
3539                         {
3540                             /* copy the time stamps from inp to entropy inp */
3541                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_inp_timestamp_low =
3542                                 ps_curr_inp_from_me->i4_inp_timestamp_low;
3543                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_inp_timestamp_high =
3544                                 ps_curr_inp_from_me->i4_inp_timestamp_high;
3545                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->pv_app_frm_ctxt =
3546                                 ps_curr_inp_from_me->pv_app_frm_ctxt;
3547 
3548                             /*copy slice header params from temp structure to output buffer */
3549                             memcpy(
3550                                 &ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->s_slice_hdr,
3551                                 &ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3552                                      ->s_slice_hdr,
3553                                 sizeof(slice_header_t));
3554 
3555                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]
3556                                 ->s_slice_hdr.pu4_entry_point_offset =
3557                                 &ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]
3558                                      ->ai4_entry_point_offset[0];
3559 
3560                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_slice_nal_type =
3561                                 ps_curr_inp_from_me->i4_slice_nal_type;
3562 
3563                             /* populate sps, vps and pps pointers for the entropy input params */
3564                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->ps_pps =
3565                                 &ps_enc_ctxt->as_pps[i4_bitrate_ctr];
3566                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->ps_sps =
3567                                 &ps_enc_ctxt->as_sps[i4_bitrate_ctr];
3568                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->ps_vps =
3569                                 &ps_enc_ctxt->as_vps[i4_bitrate_ctr];
3570 
3571                             /* SEI header will be populated in pre-enocde stage */
3572                             memcpy(
3573                                 &ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->s_sei,
3574                                 &ps_curr_inp_from_me->s_sei,
3575                                 sizeof(sei_params_t));
3576 
3577                             /*AUD and EOS presnt flags are populated*/
3578                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i1_aud_present_flag =
3579                                 ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_aud_enable_flags;
3580 
3581                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i1_eos_present_flag =
3582                                 ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_eos_enable_flags;
3583 
3584                             /* Information required for SEI Picture timing info */
3585                             {
3586                                 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_display_num =
3587                                     ps_curr_inp->s_lap_out.i4_display_num;
3588                             }
3589 
3590                             /* The Qp populated in Pre enc stage needs to overwritten with Qp
3591                         queried from rate control*/
3592                             ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]
3593                                 ->s_slice_hdr.i1_slice_qp_delta =
3594                                 (WORD8)ps_curr_inp_from_me->i4_curr_frm_qp -
3595                                 ps_enc_ctxt->as_pps[i4_bitrate_ctr].i1_pic_init_qp;
3596                         }
3597 
3598                         /* ------- get a filled descriptor from output Que ------------ */
3599                         if(/*(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag) &&*/
3600                            (ps_enc_ctxt->ps_stat_prms->i4_save_recon != 0))
3601                         {
3602                             /*swaping of buf_id for 0th and reference bitrate location, as encoder
3603                         assumes always 0th loc for reference bitrate and app must receive in
3604                         the configured order*/
3605                             WORD32 i4_recon_buf_id = i4_bitrate_ctr;
3606                             if(i4_bitrate_ctr == 0)
3607                             {
3608                                 i4_recon_buf_id = ps_enc_ctxt->i4_ref_mbr_id;
3609                             }
3610                             else if(i4_bitrate_ctr == ps_enc_ctxt->i4_ref_mbr_id)
3611                             {
3612                                 i4_recon_buf_id = 0;
3613                             }
3614 
3615                             /* ------- get free Recon buffer from Frame buffer que ---------- */
3616                             /* There is a separate queue for each bit-rate instnace. The recon
3617                         buffer is acquired from the corresponding queue based on the
3618                         bitrate instnace */
3619                             ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr] =
3620                                 (iv_enc_recon_data_buffs_t *)ihevce_q_get_filled_buff(
3621                                     (void *)ps_enc_ctxt,
3622                                     IHEVCE_RECON_DATA_Q +
3623                                         i4_recon_buf_id, /*decides the buffer queue */
3624                                     &ps_enc_ctxt->s_multi_thrd
3625                                          .recon_buf_id[i4_enc_frm_id][i4_bitrate_ctr],
3626                                     BUFF_QUE_BLOCKING_MODE);
3627 
3628                             ps_enc_ctxt->s_multi_thrd
3629                                 .is_recon_dumped[i4_enc_frm_id][i4_bitrate_ctr] = 0;
3630                             ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr] =
3631                                 ps_enc_ctxt->s_multi_thrd
3632                                     .ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr];
3633 
3634                             ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_end_flag =
3635                                 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3636                                     ->i4_end_flag;
3637                         }
3638 
3639                     }  //bitrate ctr
3640                 }
3641             }
3642             if(ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] != NULL)
3643             {
3644                 ps_curr_inp =
3645                     ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]->ps_curr_inp;
3646                 ps_curr_inp_from_me = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3647                                           ->ps_curr_inp_from_me_prms;
3648                 ps_curr_inp_enc = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id];
3649                 ps_curr_L0_IPE_inp_prms =
3650                     ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3651                         ->ps_curr_inp_from_l0_ipe_prms;
3652             }
3653             if((NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]) &&
3654                ((1 == ps_curr_inp_enc->i4_frm_proc_valid_flag) &&
3655                 (ps_enc_ctxt->s_multi_thrd.enc_master_done_frame_init[i4_enc_frm_id] == 0)))
3656             {
3657                 for(i = 0; i < i4_num_bitrates; i++)
3658                 {
3659                     aps_ref_list = ps_curr_inp_enc->aps_ref_list[i];
3660                     /* acquire mutex lock for rate control calls */
3661                     osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
3662 
3663                     /*utlize the satd data from pre enc stage to get more accurate estimate SAD for I pic*/
3664                     if(ps_curr_inp->s_lap_out.i4_pic_type == IV_I_FRAME ||
3665                        ps_curr_inp->s_lap_out.i4_pic_type == IV_IDR_FRAME)
3666                     {
3667                         ihevce_rc_update_cur_frm_intra_satd(
3668                             (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
3669                             ps_curr_inp_from_me->i8_frame_acc_satd_cost,
3670                             ps_enc_ctxt->i4_active_enc_frame_id);
3671                     }
3672 
3673                     /*pels assuming satd/act is obtained for entire frame*/
3674                     ps_curr_inp->s_rc_lap_out.i4_num_pels_in_frame_considered =
3675                         ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht *
3676                         ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd;
3677 
3678                     /*Service pending request to change average bitrate if any*/
3679                     {
3680                         LWORD64 i8_new_bitrate =
3681                             ihevce_rc_get_new_bitrate(ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0]);
3682                         LWORD64 i8_new_peak_bitrate = ihevce_rc_get_new_peak_bitrate(
3683                             ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0]);
3684                         ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3685                             ->i8_buf_level_bitrate_change = -1;
3686                         if((i8_new_bitrate != -1) &&
3687                            (i8_new_peak_bitrate != -1)) /*-1 indicates no pending request*/
3688                         {
3689                             LWORD64 buffer_level = ihevce_rc_change_avg_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 = buffer_level;
3693                         }
3694                     }
3695 
3696                     if((1 == ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.i4_mres_single_out) &&
3697                        (1 == ps_curr_inp->s_lap_out.i4_first_frm_new_res))
3698                     {
3699                         /* Whenver change in resolution happens change the buffer level */
3700                         ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3701                             ->i8_buf_level_bitrate_change = 0;
3702                     }
3703 #if 1  //KISH ELP
3704                     {
3705                         rc_bits_sad_t as_rc_frame_stat[IHEVCE_MAX_NUM_BITRATES];
3706 
3707                         if(ps_enc_ctxt->ai4_rc_query[i] ==
3708                            ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc)  //KISH
3709                         {
3710                             WORD32 out_buf_id[IHEVCE_MAX_NUM_BITRATES];
3711                             WORD32 i4_pic_type;
3712                             WORD32 cur_qp[IHEVCE_MAX_NUM_BITRATES];
3713                             ihevce_lap_output_params_t s_lap_out;
3714 
3715                             rc_lap_out_params_t s_rc_lap_out;
3716                             WORD32 i4_suppress_bpic_update;
3717 
3718                             ihevce_rc_store_retrive_update_info(
3719                                 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
3720                                 &as_rc_frame_stat[i],
3721                                 ps_enc_ctxt->i4_active_enc_frame_id,
3722                                 i,
3723                                 2,
3724                                 &out_buf_id[i],
3725                                 &i4_pic_type,
3726                                 &cur_qp[i],
3727                                 (void *)&s_lap_out,
3728                                 (void *)&s_rc_lap_out);
3729 
3730                             i4_suppress_bpic_update =
3731                                 (WORD32)(s_rc_lap_out.i4_rc_temporal_lyr_id > 1);
3732                             /*RC inter face update before update to happen only for ELP disabled */
3733                             if(1 == ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc)
3734                             {
3735                                 /* SGI & Enc Loop Parallelism related changes*/
3736                                 ihevce_rc_interface_update(
3737                                     (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
3738                                     (IV_PICTURE_CODING_TYPE_T)s_rc_lap_out.i4_rc_pic_type,
3739                                     &s_rc_lap_out,
3740                                     cur_qp[i],
3741                                     i4_enc_frm_id_rc);
3742                             }
3743 
3744                             ihevce_rc_update_pic_info(
3745                                 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
3746                                 (as_rc_frame_stat[i].u4_total_texture_bits +
3747                                  as_rc_frame_stat[i].u4_total_header_bits),  //pass total bits
3748                                 as_rc_frame_stat[i].u4_total_header_bits,
3749                                 as_rc_frame_stat[i].u4_total_sad,
3750                                 as_rc_frame_stat[i].u4_total_intra_sad,
3751                                 (IV_PICTURE_CODING_TYPE_T)i4_pic_type,
3752                                 cur_qp[i],
3753                                 i4_suppress_bpic_update,
3754                                 as_rc_frame_stat[i].i4_qp_normalized_8x8_cu_sum,
3755                                 as_rc_frame_stat[i].i4_8x8_cu_sum,
3756                                 as_rc_frame_stat[i].i8_sad_by_qscale,
3757                                 &s_lap_out,
3758                                 &s_rc_lap_out,
3759                                 out_buf_id[i],
3760                                 as_rc_frame_stat[i].u4_open_loop_intra_sad,
3761                                 as_rc_frame_stat[i].i8_total_ssd_frame,
3762                                 ps_enc_ctxt
3763                                     ->i4_active_enc_frame_id);  //ps_curr_out->i4_inp_timestamp_low)
3764 
3765                             //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));
3766                             /*populate qp for pre enc*/
3767 
3768                             //g_count--;
3769                             ps_enc_ctxt->ai4_rc_query[i]--;
3770 
3771                             if(i == (i4_num_bitrates - 1))
3772                             {
3773                                 ihevce_rc_cal_pre_enc_qp(
3774                                     (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0]);
3775 
3776                                 ps_enc_ctxt->i4_active_enc_frame_id++;
3777                                 ps_enc_ctxt->i4_active_enc_frame_id =
3778                                     (ps_enc_ctxt->i4_active_enc_frame_id %
3779                                      ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc);
3780                             }
3781                         }
3782                     }
3783 #endif
3784                     if(ps_enc_ctxt->ai4_rc_query[i] < ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc)
3785                     {
3786                         /*HEVC_RC query rate control for qp*/
3787                         ai4_cur_qp[i] = ihevce_rc_get_pic_quant(
3788                             (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
3789                             &ps_curr_inp->s_rc_lap_out,
3790                             ENC_GET_QP,
3791                             i4_enc_frm_id_rc,
3792                             0,
3793                             &ps_curr_inp->s_lap_out.ai4_frame_bits_estimated[i]);
3794 
3795                         ps_curr_inp->s_rc_lap_out.i4_orig_rc_qp = ai4_cur_qp[i];
3796 
3797                         ps_enc_ctxt->s_multi_thrd.i4_in_frame_rc_enabled = 0;
3798                         ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3799                             ->i4_sub_pic_level_rc = 0;
3800                         ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3801                             ->ai4_frame_bits_estimated =
3802                             ps_curr_inp->s_lap_out.ai4_frame_bits_estimated[i];
3803 
3804                         {
3805                             ps_enc_ctxt->ai4_rc_query[i]++;
3806                         }
3807                     }
3808 
3809                     /* SGI & Enc Loop Parallelism related changes*/
3810                     ihevce_rc_interface_update(
3811                         (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
3812                         (IV_PICTURE_CODING_TYPE_T)ps_curr_inp->s_lap_out.i4_pic_type,
3813                         &ps_curr_inp->s_rc_lap_out,
3814                         ai4_cur_qp[i],
3815                         i4_enc_frm_id_rc);
3816 
3817                     //DBG_PRINTF("HEVC_QP = %d  MPEG2_QP = %d\n",cur_qp,gu1_HEVCToMpeg2Quant[cur_qp]);//i_model_print
3818 
3819                     /* release mutex lock after rate control calls */
3820                     osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
3821 
3822                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3823                         ->s_slice_hdr.i1_slice_qp_delta =
3824                         (WORD8)ai4_cur_qp[i] - ps_enc_ctxt->as_pps[i].i1_pic_init_qp;
3825 
3826                     ps_enc_ctxt->s_multi_thrd.cur_qp[i4_enc_frm_id][i] = ai4_cur_qp[i];
3827 
3828                     /* For interlace pictures, first_field depends on topfield_first and bottom field */
3829                     if(i4_field_pic)
3830                     {
3831                         first_field =
3832                             (ps_curr_inp->s_input_buf.i4_topfield_first ^
3833                              ps_curr_inp->s_input_buf.i4_bottom_field);
3834                     }
3835                     /* get frame level lambda params */
3836                     ihevce_get_frame_lambda_prms(
3837                         ps_enc_ctxt,
3838                         ps_curr_inp_from_me,
3839                         ai4_cur_qp[i],
3840                         first_field,
3841                         ps_curr_inp->s_lap_out.i4_is_ref_pic,
3842                         ps_curr_inp->s_lap_out.i4_temporal_lyr_id,
3843                         ps_curr_inp->s_lap_out.f_i_pic_lamda_modifier,
3844                         i,
3845                         ENC_LOOP_LAMBDA_TYPE);
3846 
3847 #if ADAPT_COLOCATED_FROM_L0_FLAG
3848                     ps_enc_ctxt->s_multi_thrd.ps_frm_recon[i4_enc_frm_id][i]->i4_frame_qp =
3849                         ai4_cur_qp[i];
3850 #endif
3851                 }  //bitrate counter ends
3852 
3853                 /* Reset the Dependency Mngrs local to EncLoop., ie CU_TopRight and Dblk */
3854                 ihevce_enc_loop_dep_mngr_frame_reset(
3855                     ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt, i4_enc_frm_id);
3856             }
3857 
3858             {
3859                 /*Set the master done flag for frame init so that other
3860                 * threads can skip it
3861                 */
3862                 ps_enc_ctxt->s_multi_thrd.enc_master_done_frame_init[i4_enc_frm_id] = 1;
3863             }
3864 
3865             /************************************/
3866             /******  EXIT CRITICAL SECTION ******/
3867             /************************************/
3868 
3869             /****** Unlock the critical section ******/
3870             if(NULL != pv_mutex_handle_frame_init)
3871             {
3872                 result_frame_init = osal_mutex_unlock(pv_mutex_handle_frame_init);
3873                 if(OSAL_SUCCESS != result_frame_init)
3874                     return 0;
3875             }
3876             ps_enc_ctxt->s_multi_thrd.i4_encode = 1;
3877             ps_enc_ctxt->s_multi_thrd.i4_num_re_enc = 0;
3878             /************************************/
3879             /******  Do Enc loop process   ******/
3880             /************************************/
3881             /* Each thread will run the enc-loop.
3882             Each thread will initialize it's own enc_loop context and do the processing.
3883             Each thread will run all the bit-rate instances one after another */
3884             if((i4_enc_end_flag == 0) &&
3885                (NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]) &&
3886                (1 == ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3887                          ->i4_frm_proc_valid_flag))
3888             {
3889                 while(1)
3890                 {
3891                     ctb_enc_loop_out_t *ps_ctb_enc_loop_frm[IHEVCE_MAX_NUM_BITRATES];
3892                     cu_enc_loop_out_t *ps_cu_enc_loop_frm[IHEVCE_MAX_NUM_BITRATES];
3893                     tu_enc_loop_out_t *ps_tu_frm[IHEVCE_MAX_NUM_BITRATES];
3894                     pu_t *ps_pu_frm[IHEVCE_MAX_NUM_BITRATES];
3895                     UWORD8 *pu1_frm_coeffs[IHEVCE_MAX_NUM_BITRATES];
3896                     me_master_ctxt_t *ps_master_me_ctxt =
3897                         (me_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_me_ctxt;
3898                     ihevce_enc_loop_master_ctxt_t *ps_master_ctxt =
3899                         (ihevce_enc_loop_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt;
3900 
3901                     for(i = 0; i < i4_num_bitrates; i++)
3902                     {
3903                         if(i4_thrd_id == 0)
3904                         {
3905                             PROFILE_START(
3906                                 &ps_hle_ctxt->profile_enc[ps_enc_ctxt->i4_resolution_id][i]);
3907                         }
3908                         if(NULL != ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id])
3909                         {
3910                             ps_ctb_enc_loop_frm[i] =
3911                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3912                                     ->ps_frm_ctb_data;
3913                             ps_cu_enc_loop_frm[i] =
3914                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3915                                     ->ps_frm_cu_data;
3916                             ps_tu_frm[i] =
3917                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3918                                     ->ps_frm_tu_data;
3919                             ps_pu_frm[i] =
3920                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3921                                     ->ps_frm_pu_data;
3922                             pu1_frm_coeffs[i] = (UWORD8 *)ps_enc_ctxt->s_multi_thrd
3923                                                     .ps_curr_out_enc_grp[i4_enc_frm_id][i]
3924                                                     ->pv_coeff_data;
3925                         }
3926                         /*derive reference picture list based on ping or pong instnace */
3927                         aps_ref_list = ps_curr_inp_enc->aps_ref_list[i];
3928 
3929                         /* Always consider chroma cost when computing cost for derived instance */
3930                         ps_master_ctxt->aps_enc_loop_thrd_ctxt[i4_thrd_id]->i4_consider_chroma_cost =
3931                             1;
3932 
3933                         /*************************
3934                         * MULTI BITRATE CODE START
3935                         **************************/
3936                         if(i4_num_bitrates > 1)
3937                         {
3938                             ihevce_mbr_quality_tool_set_configuration(
3939                                 ps_master_ctxt->aps_enc_loop_thrd_ctxt[i4_thrd_id],
3940                                 ps_enc_ctxt->ps_stat_prms);
3941                         }
3942                         /************************
3943                         * MULTI BITRATE CODE END
3944                         *************************/
3945                         /* picture level init of Encode loop module */
3946                         ihevce_enc_loop_frame_init(
3947                             ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt,
3948                             ps_enc_ctxt->s_multi_thrd.cur_qp[i4_enc_frm_id][i],
3949                             aps_ref_list,
3950                             ps_enc_ctxt->s_multi_thrd.ps_frm_recon[i4_enc_frm_id][i],
3951                             &ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3952                                  ->s_slice_hdr,
3953                             ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]->ps_pps,
3954                             ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]->ps_sps,
3955                             ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]->ps_vps,
3956                             ps_curr_inp_enc->ps_curr_inp->s_lap_out.i1_weighted_pred_flag,
3957                             ps_curr_inp_enc->ps_curr_inp->s_lap_out.i1_weighted_bipred_flag,
3958                             ps_curr_inp_enc->ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom,
3959                             ps_curr_inp_enc->ps_curr_inp->s_lap_out.i4_log2_chroma_wght_denom,
3960                             ps_curr_inp_enc->ps_curr_inp->s_lap_out.i4_poc,
3961                             ps_curr_inp_enc->ps_curr_inp->s_lap_out.i4_display_num,
3962                             ps_enc_ctxt,
3963                             ps_curr_inp_enc,
3964                             i,
3965                             i4_thrd_id,
3966                             i4_enc_frm_id,  // update this to enc_loop_ctxt struct
3967                             i4_num_bitrates,
3968                             ps_curr_inp_enc->ps_curr_inp->s_lap_out.i4_quality_preset,
3969                             ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3970                                 ->pv_dep_mngr_encloop_dep_me);
3971 
3972                         ihevce_enc_loop_process(
3973                             ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt,
3974                             ps_curr_inp,
3975                             ps_curr_inp_from_me->ps_ctb_analyse,
3976                             ps_curr_L0_IPE_inp_prms->ps_ipe_analyse_ctb,
3977                             ps_enc_ctxt->s_multi_thrd.ps_frm_recon[i4_enc_frm_id][i],
3978                             ps_curr_inp_enc->ps_cur_ctb_cu_tree,
3979                             ps_ctb_enc_loop_frm[i],
3980                             ps_cu_enc_loop_frm[i],
3981                             ps_tu_frm[i],
3982                             ps_pu_frm[i],
3983                             pu1_frm_coeffs[i],
3984                             &ps_enc_ctxt->s_frm_ctb_prms,
3985                             &ps_curr_inp_from_me->as_lambda_prms[i],
3986                             &ps_enc_ctxt->s_multi_thrd,
3987                             i4_thrd_id,
3988                             i4_enc_frm_id,
3989                             ps_enc_ctxt->ps_stat_prms->s_pass_prms.i4_pass);
3990                         if(i4_thrd_id == 0)
3991                         {
3992                             PROFILE_STOP(
3993                                 &ps_hle_ctxt->profile_enc[ps_enc_ctxt->i4_resolution_id][i], NULL);
3994                         }
3995                     }  //loop over bitrate ends
3996                     {
3997                         break;
3998                     }
3999                 } /*end of while(ps_enc_ctxt->s_multi_thrd.ai4_encode[i4_enc_frm_id] == 1)*/
4000             }
4001 
4002             /************************************/
4003             /****** ENTER CRITICAL SECTION ******/
4004             /************************************/
4005 
4006             /****** Lock the critical section ******/
4007             if(NULL != ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id])
4008             {
4009                 result = osal_mutex_lock(
4010                     ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id]);
4011 
4012                 if(OSAL_SUCCESS != result)
4013                     return 0;
4014             }
4015             if(ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] != NULL)
4016             {
4017                 /* Increment the counter to keep track of no of threads exiting the current mutex*/
4018                 ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id]++;
4019 
4020                 /* If the end frame is reached force the last slave to enter the next critical section*/
4021                 if(i4_enc_end_flag == 1)
4022                 {
4023                     if(ps_enc_ctxt->s_multi_thrd.num_thrds_done ==
4024                        ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds - 1)
4025                     {
4026                         ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id] =
4027                             ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds;
4028                     }
4029                 }
4030 
4031                 {
4032                     /*Last slave thread comming out of enc loop will execute next critical section*/
4033                     if(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                         iv_enc_recon_data_buffs_t *ps_recon_out_temp = NULL;
4037                         recon_pic_buf_t *ps_frm_recon_temp = NULL;
4038                         ihevce_lap_enc_buf_t *ps_curr_inp;
4039                         rc_lap_out_params_t *ps_rc_lap_out_next_encode;
4040 
4041                         WORD32 ai4_act_qp[IHEVCE_MAX_NUM_BITRATES];
4042                         ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id] = 0;
4043 
4044                         ps_curr_inp = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
4045                                           ->ps_curr_inp;
4046 
4047                         for(i = 0; i < i4_num_bitrates; i++)
4048                         {
4049                             {
4050                                 WORD32 j, i4_avg_QP;
4051                                 ihevce_enc_loop_master_ctxt_t *ps_master_ctxt =
4052                                     (ihevce_enc_loop_master_ctxt_t *)
4053                                         ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt;
4054                                 ihevce_enc_loop_ctxt_t *ps_ctxt, *ps_ctxt_temp;
4055                                 ihevce_enc_loop_ctxt_t *ps_ctxt_last_thrd;
4056                                 LWORD64 i8_total_cu_bits_into_qscale = 0, i8_total_cu_bits = 0;
4057                                 UWORD32 total_frame_intra_sad = 0;
4058                                 UWORD32 total_frame_inter_sad = 0;
4059                                 UWORD32 total_frame_sad = 0;
4060 
4061                                 LWORD64 total_frame_intra_cost = 0;
4062                                 LWORD64 total_frame_inter_cost = 0;
4063                                 LWORD64 total_frame_cost = 0;
4064 
4065                                 ps_ctxt_last_thrd =
4066                                     ps_master_ctxt->aps_enc_loop_thrd_ctxt[i4_thrd_id];
4067                                 if(ps_enc_ctxt->s_multi_thrd.i4_in_frame_rc_enabled)
4068                                 {
4069                                     WORD32 i4_total_ctb =
4070                                         ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz *
4071                                         ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_vert;
4072 
4073                                     ai4_act_qp[i] =
4074                                         ps_enc_ctxt->s_multi_thrd
4075                                             .ai4_curr_qp_acc[ps_ctxt_last_thrd->i4_enc_frm_id][i] /
4076                                         i4_total_ctb;
4077                                 }
4078                                 else
4079                                 {
4080                                     ai4_act_qp[i] =
4081                                         ps_enc_ctxt->s_multi_thrd.cur_qp[i4_enc_frm_id][i];
4082                                 }
4083 
4084                                 ps_enc_ctxt->s_multi_thrd
4085                                     .ai4_curr_qp_acc[ps_ctxt_last_thrd->i4_enc_frm_id][i] = 0;
4086 
4087                                 /*Reset all the values of sub pic rc to default after the frame is completed */
4088                                 {
4089                                     ps_enc_ctxt->s_multi_thrd
4090                                         .ai4_acc_ctb_ctr[ps_ctxt_last_thrd->i4_enc_frm_id][i] = 0;
4091                                     ps_enc_ctxt->s_multi_thrd
4092                                         .ai4_ctb_ctr[ps_ctxt_last_thrd->i4_enc_frm_id][i] = 0;
4093 
4094                                     ps_enc_ctxt->s_multi_thrd
4095                                         .ai4_threshold_reached[ps_ctxt_last_thrd->i4_enc_frm_id][i] =
4096                                         0;
4097 
4098                                     ps_enc_ctxt->s_multi_thrd
4099                                         .ai4_curr_qp_estimated[ps_ctxt_last_thrd->i4_enc_frm_id][i] =
4100                                         (1 << QP_LEVEL_MOD_ACT_FACTOR);
4101 
4102                                     ps_enc_ctxt->s_multi_thrd
4103                                         .af_acc_hdr_bits_scale_err[ps_ctxt_last_thrd->i4_enc_frm_id]
4104                                                                   [i] = 0;
4105                                 }
4106                                 for(j = 0; j < ps_master_ctxt->i4_num_proc_thrds; j++)
4107                                 {
4108                                     /* ENC_LOOP state structure */
4109                                     ps_ctxt = ps_master_ctxt->aps_enc_loop_thrd_ctxt[j];
4110 
4111                                     total_frame_intra_sad +=
4112                                         ps_ctxt
4113                                             ->aaps_enc_loop_rc_params[ps_ctxt_last_thrd
4114                                                                           ->i4_enc_frm_id][i]
4115                                             ->u4_frame_intra_sad_acc;
4116                                     total_frame_inter_sad +=
4117                                         ps_ctxt
4118                                             ->aaps_enc_loop_rc_params[ps_ctxt_last_thrd
4119                                                                           ->i4_enc_frm_id][i]
4120                                             ->u4_frame_inter_sad_acc;
4121                                     total_frame_sad +=
4122                                         ps_ctxt
4123                                             ->aaps_enc_loop_rc_params[ps_ctxt_last_thrd
4124                                                                           ->i4_enc_frm_id][i]
4125                                             ->u4_frame_sad_acc;
4126 
4127                                     total_frame_intra_cost +=
4128                                         ps_ctxt
4129                                             ->aaps_enc_loop_rc_params[ps_ctxt_last_thrd
4130                                                                           ->i4_enc_frm_id][i]
4131                                             ->i8_frame_intra_cost_acc;
4132                                     total_frame_inter_cost +=
4133                                         ps_ctxt
4134                                             ->aaps_enc_loop_rc_params[ps_ctxt_last_thrd
4135                                                                           ->i4_enc_frm_id][i]
4136                                             ->i8_frame_inter_cost_acc;
4137                                     total_frame_cost +=
4138                                         ps_ctxt
4139                                             ->aaps_enc_loop_rc_params[ps_ctxt_last_thrd
4140                                                                           ->i4_enc_frm_id][i]
4141                                             ->i8_frame_cost_acc;
4142                                     /*Reset thrd id flag once the frame is completed */
4143                                     ps_enc_ctxt->s_multi_thrd
4144                                         .ai4_thrd_id_valid_flag[ps_ctxt_last_thrd->i4_enc_frm_id][i]
4145                                                                [j] = -1;
4146                                 }
4147                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4148                                     ->s_pic_level_info.u4_frame_sad = total_frame_sad;
4149                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4150                                     ->s_pic_level_info.u4_frame_intra_sad = total_frame_intra_sad;
4151                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4152                                     ->s_pic_level_info.u4_frame_inter_sad = total_frame_inter_sad;
4153 
4154                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4155                                     ->s_pic_level_info.i8_frame_cost = total_frame_cost;
4156                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4157                                     ->s_pic_level_info.i8_frame_intra_cost = total_frame_intra_cost;
4158                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4159                                     ->s_pic_level_info.i8_frame_inter_cost = total_frame_inter_cost;
4160                             }
4161                             ps_enc_ctxt->s_multi_thrd.ai4_produce_outbuf[i4_enc_frm_id][i] = 1;
4162                             ps_recon_out_temp =
4163                                 ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i];
4164                             ps_frm_recon_temp =
4165                                 ps_enc_ctxt->s_multi_thrd.ps_frm_recon[i4_enc_frm_id][i];
4166 
4167                             /* end of frame processing only if current input is valid */
4168                             if(1 == ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
4169                                         ->i4_frm_proc_valid_flag)
4170                             {
4171                                 /* Calculate the SEI Hash if enabled */
4172                                 if(0 !=
4173                                    ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4174                                        ->s_sei.i1_decoded_pic_hash_sei_flag)
4175                                 {
4176                                     void *pv_y_buf;
4177                                     void *pv_u_buf;
4178 
4179                                     {
4180                                         pv_y_buf = ps_frm_recon_temp->s_yuv_buf_desc.pv_y_buf;
4181                                         pv_u_buf = ps_frm_recon_temp->s_yuv_buf_desc.pv_u_buf;
4182                                     }
4183 
4184                                     ihevce_populate_hash_sei(
4185                                         &ps_enc_ctxt->s_multi_thrd
4186                                              .ps_curr_out_enc_grp[i4_enc_frm_id][i]
4187                                              ->s_sei,
4188                                         ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms
4189                                             .i4_internal_bit_depth,
4190                                         pv_y_buf,
4191                                         ps_frm_recon_temp->s_yuv_buf_desc.i4_y_wd,
4192                                         ps_frm_recon_temp->s_yuv_buf_desc.i4_y_ht,
4193                                         ps_frm_recon_temp->s_yuv_buf_desc.i4_y_strd,
4194                                         pv_u_buf,
4195                                         ps_frm_recon_temp->s_yuv_buf_desc.i4_uv_wd,
4196                                         ps_frm_recon_temp->s_yuv_buf_desc.i4_uv_ht,
4197                                         ps_frm_recon_temp->s_yuv_buf_desc.i4_uv_strd,
4198                                         0,
4199                                         0);
4200                                 }
4201                                 /* Sending qp, poc and pic-type to entropy thread for printing on console */
4202                                 if(ps_enc_ctxt->ps_stat_prms->i4_log_dump_level != 0)
4203                                 {
4204                                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4205                                         ->i4_qp =
4206                                         ps_enc_ctxt->s_multi_thrd.cur_qp[i4_enc_frm_id][i];
4207                                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4208                                         ->i4_poc = ps_curr_inp->s_lap_out.i4_poc;
4209                                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4210                                         ->i4_pic_type = ps_curr_inp->s_lap_out.i4_pic_type;
4211                                 }
4212 
4213                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4214                                     ->i4_is_I_scenecut =
4215                                     ((ps_curr_inp->s_lap_out.i4_scene_type == 1) &&
4216                                      (ps_curr_inp->s_lap_out.i4_pic_type == IV_IDR_FRAME ||
4217                                       ps_curr_inp->s_lap_out.i4_pic_type == IV_I_FRAME));
4218 
4219                                 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4220                                     ->i4_is_non_I_scenecut =
4221                                     ((ps_curr_inp->s_lap_out.i4_scene_type ==
4222                                       SCENE_TYPE_SCENE_CUT) &&
4223                                      (ps_enc_ctxt->s_multi_thrd
4224                                           .ps_curr_out_enc_grp[i4_enc_frm_id][i]
4225                                           ->i4_is_I_scenecut == 0));
4226 
4227                                 /*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;
4228                                 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;
4229 
4230                                 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;*/
4231 
4232                                 /* -------------------------------------------- */
4233                                 /*        MSE Computation for PSNR              */
4234                                 /* -------------------------------------------- */
4235                                 if(ps_enc_ctxt->ps_stat_prms->i4_log_dump_level != 0)
4236                                 {
4237                                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4238                                         ->i4_qp =
4239                                         ps_enc_ctxt->s_multi_thrd.cur_qp[i4_enc_frm_id][i];
4240                                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4241                                         ->i4_poc = ps_curr_inp->s_lap_out.i4_poc;
4242                                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4243                                         ->i4_pic_type = ps_curr_inp->s_lap_out.i4_pic_type;
4244                                 }
4245 
4246                                 /* if non reference B picture */
4247                                 if(0 == ps_frm_recon_temp->i4_is_reference)
4248                                 {
4249                                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4250                                         ->i4_pic_type += 2;
4251                                 }
4252 
4253 #define FORCE_EXT_REF_PIC 0
4254 
4255                                 /* -------------------------------------------- */
4256                                 /*        Dumping of recon to App Queue         */
4257                                 /* -------------------------------------------- */
4258                                 if(1 == ps_enc_ctxt->ps_stat_prms->i4_save_recon)
4259                                 {
4260                                     {
4261                                         WORD32 i, j;
4262                                         UWORD8 *pu1_recon;
4263                                         UWORD8 *pu1_chrm_buf_u;
4264                                         UWORD8 *pu1_chrm_buf_v;
4265                                         UWORD8 *pu1_curr_recon;
4266 
4267                                         pu1_recon =
4268                                             (UWORD8 *)ps_frm_recon_temp->s_yuv_buf_desc.pv_y_buf;
4269 
4270                                         /** Copying Luma into recon buffer  **/
4271                                         pu1_curr_recon = (UWORD8 *)ps_recon_out_temp->pv_y_buf;
4272 
4273                                         for(j = 0; j < ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht;
4274                                             j++)
4275                                         {
4276                                             memcpy(
4277                                                 pu1_curr_recon,
4278                                                 pu1_recon,
4279                                                 ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd);
4280 
4281                                             pu1_recon +=
4282                                                 ps_frm_recon_temp->s_yuv_buf_desc.i4_y_strd;
4283                                             pu1_curr_recon +=
4284                                                 ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd;
4285                                         }
4286 
4287                                         /* recon chroma is converted from Semiplanar to Planar for dumping */
4288                                         pu1_recon =
4289                                             (UWORD8 *)ps_frm_recon_temp->s_yuv_buf_desc.pv_u_buf;
4290                                         pu1_chrm_buf_u = (UWORD8 *)ps_recon_out_temp->pv_cb_buf;
4291                                         pu1_chrm_buf_v =
4292                                             pu1_chrm_buf_u +
4293                                             ((ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd >> 1) *
4294                                              ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht);
4295 
4296                                         for(j = 0; j < ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht;
4297                                             j++)
4298                                         {
4299                                             for(i = 0;
4300                                                 i<ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd>> 1;
4301                                                 i++)
4302                                             {
4303                                                 *pu1_chrm_buf_u++ = *pu1_recon++;
4304                                                 *pu1_chrm_buf_v++ = *pu1_recon++;
4305                                             }
4306 
4307                                             pu1_recon -=
4308                                                 ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd;
4309                                             pu1_recon +=
4310                                                 ps_frm_recon_temp->s_yuv_buf_desc.i4_uv_strd;
4311                                         }
4312 
4313                                         /* set the POC and number of bytes in Y & UV buf */
4314                                         ps_recon_out_temp->i4_poc = ps_frm_recon_temp->i4_poc;
4315                                         ps_recon_out_temp->i4_y_pixels =
4316                                             ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht *
4317                                             ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd;
4318                                         ps_recon_out_temp->i4_uv_pixels =
4319                                             ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd *
4320                                             ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht;
4321                                     }
4322                                 }
4323                                 ps_frm_recon_temp->i4_non_ref_free_flag = 1;
4324                                 /* -------------------------------------------- */
4325                                 /*        End of picture updates                */
4326                                 /* -------------------------------------------- */
4327                             }
4328 
4329                             /* After the MSE (or PSNR) computation is done we will update
4330                     these data in output buffer structure and then signal entropy
4331                     thread that the buffer is produced. */
4332                             if(ps_enc_ctxt->s_multi_thrd.ai4_produce_outbuf[i4_enc_frm_id][i] == 1)
4333                             {
4334                                 /* set the output buffer as produced */
4335                                 ihevce_q_set_buff_prod(
4336                                     (void *)ps_enc_ctxt,
4337                                     IHEVCE_FRM_PRS_ENT_COD_Q + i,
4338                                     ps_enc_ctxt->s_multi_thrd.out_buf_id[i4_enc_frm_id][i]);
4339 
4340                                 ps_enc_ctxt->s_multi_thrd.is_out_buf_freed[i4_enc_frm_id][i] = 1;
4341                                 ps_enc_ctxt->s_multi_thrd.ai4_produce_outbuf[i4_enc_frm_id][i] = 0;
4342                             }
4343 
4344                         }  //bit-rate counter ends
4345                         /* -------------------------------------------- */
4346                         /*        Frame level RC update                 */
4347                         /* -------------------------------------------- */
4348                         /* Query enc_loop to get the Parameters for Rate control */
4349                         if(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag)
4350                         {
4351                             frm_proc_ent_cod_ctxt_t *ps_curr_out = NULL;
4352                             /*HEVC_RC*/
4353                             rc_bits_sad_t as_rc_frame_stat[IHEVCE_MAX_NUM_BITRATES];
4354                             osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4355 
4356                             for(i = 0; i < i4_num_bitrates; i++)
4357                             {
4358                                 /*each bit-rate RC params are collated by master thread */
4359                                 ihevce_enc_loop_get_frame_rc_prms(
4360                                     ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt,
4361                                     &as_rc_frame_stat[i],
4362                                     i,
4363                                     i4_enc_frm_id);
4364 
4365                                 /*update bits estimate on rd opt thread so that mismatch between rdopt and entropy can be taken care of*/
4366                                 ps_curr_out =
4367                                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i];
4368 
4369                                 ps_rc_lap_out_next_encode =
4370                                     (rc_lap_out_params_t *)
4371                                         ps_curr_inp->s_rc_lap_out.ps_rc_lap_out_next_encode;
4372 
4373                                 ps_curr_out->i4_is_end_of_idr_gop = 0;
4374 
4375                                 if(NULL != ps_rc_lap_out_next_encode)
4376                                 {
4377                                     if(ps_rc_lap_out_next_encode->i4_rc_pic_type == IV_IDR_FRAME)
4378                                     {
4379                                         /*If the next pic is IDR, then signal end of gopf for current frame*/
4380                                         ps_curr_out->i4_is_end_of_idr_gop = 1;
4381                                     }
4382                                 }
4383                                 else if(NULL == ps_rc_lap_out_next_encode)
4384                                 {
4385                                     /*If the lap out next is NULL, then end of sequence reached*/
4386                                     ps_curr_out->i4_is_end_of_idr_gop = 1;
4387                                 }
4388 
4389                                 if(NULL == ps_curr_out)
4390                                 {
4391                                     DBG_PRINTF("error in getting curr out in encode loop\n");
4392                                 }
4393 
4394                                 //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);
4395                                 /* acquire mutex lock for rate control calls */
4396 
4397                                 /* Note : u4_total_intra_sad coming out of enc_loop */
4398                                 /* will not be accurate becos of intra gating       */
4399                                 /* need to access the importance of this sad in RC  */
4400 
4401                                 //Store the rc update parameters for deterministic Enc loop parallelism
4402 
4403                                 {
4404                                     ihevce_rc_store_retrive_update_info(
4405                                         (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
4406                                         &as_rc_frame_stat[i],
4407                                         i4_enc_frm_id_rc,
4408                                         i,
4409                                         1,
4410                                         &ps_enc_ctxt->s_multi_thrd.out_buf_id[i4_enc_frm_id][i],
4411                                         &ps_curr_inp->s_lap_out.i4_pic_type,
4412                                         &ai4_act_qp[i],
4413                                         (void *)&ps_curr_inp->s_lap_out,
4414                                         (void *)&ps_curr_inp->s_rc_lap_out);  // STORE
4415                                 }
4416                             }
4417 
4418                             /* release mutex lock after rate control calls */
4419                             osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4420                         }
4421                         if((ps_enc_ctxt->ps_stat_prms->i4_save_recon != 0) /*&&
4422                                                                    (1 == ps_curr_inp->s_input_buf.s_input_buf.i4_inp_frm_data_valid_flag)*/)
4423                         {
4424                             WORD32 i4_bitrate_ctr;
4425                             for(i4_bitrate_ctr = 0; i4_bitrate_ctr < i4_num_bitrates;
4426                                 i4_bitrate_ctr++)
4427                             {
4428                                 /*swaping of buf_id for 0th and reference bitrate location, as encoder
4429                         assumes always 0th loc for reference bitrate and app must receive in
4430                         the configured order*/
4431                                 WORD32 i4_recon_buf_id = i4_bitrate_ctr;
4432                                 if(i4_bitrate_ctr == 0)
4433                                 {
4434                                     i4_recon_buf_id = ps_enc_ctxt->i4_ref_mbr_id;
4435                                 }
4436                                 else if(i4_bitrate_ctr == ps_enc_ctxt->i4_ref_mbr_id)
4437                                 {
4438                                     i4_recon_buf_id = 0;
4439                                 }
4440 
4441                                 /* Call back to Apln. saying recon buffer is produced */
4442                                 ps_hle_ctxt->ihevce_output_recon_fill_done(
4443                                     ps_hle_ctxt->pv_recon_cb_handle,
4444                                     ps_enc_ctxt->s_multi_thrd
4445                                         .ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr],
4446                                     i4_recon_buf_id, /* br instance */
4447                                     i4_resolution_id /* res_intance */);
4448 
4449                                 /* --- release the current recon buffer ---- */
4450                                 ihevce_q_rel_buf(
4451                                     (void *)ps_enc_ctxt,
4452                                     (IHEVCE_RECON_DATA_Q + i4_recon_buf_id),
4453                                     ps_enc_ctxt->s_multi_thrd
4454                                         .recon_buf_id[i4_enc_frm_id][i4_bitrate_ctr]);
4455 
4456                                 ps_enc_ctxt->s_multi_thrd
4457                                     .is_recon_dumped[i4_enc_frm_id][i4_bitrate_ctr] = 1;
4458                             }
4459                         }
4460 
4461                         if(i4_enc_end_flag == 1)
4462                         {
4463                             if(ps_enc_ctxt->s_multi_thrd.is_in_buf_freed[i4_enc_frm_id] == 0)
4464                             {
4465                                 /* release the pre_enc/enc queue buffer */
4466                                 ihevce_q_rel_buf(
4467                                     (void *)ps_enc_ctxt,
4468                                     IHEVCE_PRE_ENC_ME_Q,
4469                                     ps_curr_inp_enc->curr_inp_from_me_buf_id);
4470 
4471                                 ps_enc_ctxt->s_multi_thrd.is_in_buf_freed[i4_enc_frm_id] = 1;
4472                             }
4473                         }
4474                         /* release encoder owned input buffer*/
4475                         ihevce_q_rel_buf(
4476                             (void *)ps_enc_ctxt,
4477                             IHEVCE_INPUT_DATA_CTRL_Q,
4478                             ps_curr_inp_enc->curr_inp_buf_id);
4479                         /* release the pre_enc/enc queue buffer */
4480                         ihevce_q_rel_buf(
4481                             ps_enc_ctxt,
4482                             IHEVCE_PRE_ENC_ME_Q,
4483                             ps_curr_inp_enc->curr_inp_from_me_buf_id);
4484 
4485                         ps_enc_ctxt->s_multi_thrd.is_in_buf_freed[i4_enc_frm_id] = 1;
4486 
4487                         /* release the pre_enc/enc queue buffer */
4488                         ihevce_q_rel_buf(
4489                             ps_enc_ctxt,
4490                             IHEVCE_L0_IPE_ENC_Q,
4491                             ps_curr_inp_enc->curr_inp_from_l0_ipe_buf_id);
4492 
4493                         ps_enc_ctxt->s_multi_thrd.is_L0_ipe_in_buf_freed[i4_enc_frm_id] = 1;
4494                         /* release the me/enc queue buffer */
4495                         ihevce_q_rel_buf(
4496                             ps_enc_ctxt,
4497                             IHEVCE_ME_ENC_RDOPT_Q,
4498                             ps_enc_ctxt->s_multi_thrd.i4_enc_in_buf_id[i4_enc_frm_id]);
4499 
4500                         /* reset the pointers to NULL */
4501                         ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] = NULL;
4502                         ps_enc_ctxt->s_multi_thrd.enc_master_done_frame_init[i4_enc_frm_id] = 0;
4503                         for(i = 0; i < i4_num_bitrates; i++)
4504                             ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i] = NULL;
4505 
4506                         /* Set the prev_frame_done variable to 1 to indicate that
4507                 *prev frame is done */
4508                         ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_done);
4509                     }
4510                 }
4511             }
4512             else
4513             {
4514                 /* Increment the counter to keep track of no of threads exiting the current mutex*/
4515                 ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id]++;
4516                 /*Last slave thread comming out of enc loop will execute next critical section*/
4517                 if(ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id] ==
4518                    ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds)
4519                 {
4520                     ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id] = 0;
4521 
4522                     /* reset the pointers to NULL */
4523                     ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] = NULL;
4524 
4525                     ps_enc_ctxt->s_multi_thrd.enc_master_done_frame_init[i4_enc_frm_id] = 0;
4526 
4527                     for(i = 0; i < i4_num_bitrates; i++)
4528                         ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i] = NULL;
4529 
4530                     /* Set the prev_frame_done variable to 1 to indicate that
4531                         *prev frame is done
4532                         */
4533                     ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_done);
4534                 }
4535             }
4536 
4537             /* Toggle the ping pong flag of the thread exiting curr frame*/
4538             /*ps_enc_ctxt->s_multi_thrd.ping_pong[ps_thrd_ctxt->i4_thrd_id] =
4539                 !ps_enc_ctxt->s_multi_thrd.ping_pong[ps_thrd_ctxt->i4_thrd_id];*/
4540         }
4541 
4542         /************************************/
4543         /******  EXIT CRITICAL SECTION ******/
4544         /************************************/
4545         /****** Unlock the critical section ******/
4546         if(NULL != ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id])
4547         {
4548             result = osal_mutex_unlock(
4549                 ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id]);
4550             if(OSAL_SUCCESS != result)
4551                 return 0;
4552         }
4553 
4554         if((0 == i4_me_end_flag) && (0 == i4_enc_end_flag))
4555         {
4556             i4_enc_frm_id++;
4557             i4_enc_frm_id_rc++;
4558 
4559             if(i4_enc_frm_id == NUM_ME_ENC_BUFS)
4560             {
4561                 i4_enc_frm_id = 0;
4562             }
4563 
4564             if(i4_enc_frm_id_rc == ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc)
4565             {
4566                 i4_enc_frm_id_rc = 0;
4567             }
4568             i4_me_frm_id++;
4569 
4570             if(i4_me_frm_id == NUM_ME_ENC_BUFS)
4571                 i4_me_frm_id = 0;
4572         }
4573         if(1 == ps_enc_ctxt->s_multi_thrd.i4_force_end_flag)
4574         {
4575             i4_me_end_flag = 1;
4576             i4_enc_end_flag = 1;
4577         }
4578     }
4579 
4580     /****** Lock the critical section ******/
4581 
4582     if(NULL != ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id])
4583     {
4584         WORD32 result;
4585 
4586         result =
4587             osal_mutex_lock(ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id]);
4588 
4589         if(OSAL_SUCCESS != result)
4590             return 0;
4591     }
4592 
4593     if(ps_enc_ctxt->s_multi_thrd.num_thrds_done ==
4594        (ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds - 1))
4595     {
4596         if(1 != ps_enc_ctxt->s_multi_thrd.i4_force_end_flag)
4597         {
4598             osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4599             for(i = 0; i < ps_enc_ctxt->i4_num_bitrates; i++)
4600             {
4601                 ihevce_rc_close(
4602                     ps_enc_ctxt,
4603                     ps_enc_ctxt->i4_active_enc_frame_id,
4604                     2,
4605                     MIN(ps_enc_ctxt->ai4_rc_query[i], ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc),
4606                     i);
4607             }
4608             osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4609         }
4610     }
4611 
4612     ps_enc_ctxt->s_multi_thrd.num_thrds_done++;
4613 
4614     /****** UnLock the critical section ******/
4615     if(NULL != ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id])
4616     {
4617         WORD32 result;
4618 
4619         result =
4620             osal_mutex_unlock(ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id]);
4621 
4622         if(OSAL_SUCCESS != result)
4623             return 0;
4624     }
4625 
4626     /****** Lock the critical section ******/
4627     if(NULL != ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id])
4628     {
4629         WORD32 result;
4630         result =
4631             osal_mutex_lock(ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id]);
4632 
4633         if(OSAL_SUCCESS != result)
4634             return 0;
4635     }
4636     if((ps_enc_ctxt->s_multi_thrd.num_thrds_done ==
4637         ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds) &&
4638        (ps_enc_ctxt->s_multi_thrd.i4_force_end_flag))
4639     {
4640         WORD32 num_bufs_preenc_me_que, num_bufs_L0_ipe_enc;
4641         WORD32 buf_id_ctr, frm_id_ctr;
4642         frm_proc_ent_cod_ctxt_t *ps_curr_out_enc_ent[IHEVCE_MAX_NUM_BITRATES];
4643         WORD32 out_buf_id_enc_ent[IHEVCE_MAX_NUM_BITRATES];
4644 
4645         if(ps_enc_ctxt->s_multi_thrd.i4_num_enc_loop_frm_pllel > 1)
4646         {
4647             num_bufs_preenc_me_que = (MAX_L0_IPE_ENC_STAGGER - 1) + MIN_L1_L0_STAGGER_NON_SEQ +
4648                                      NUM_BUFS_DECOMP_HME +
4649                                      ps_enc_ctxt->ps_stat_prms->s_lap_prms.i4_rc_look_ahead_pics;
4650 
4651             num_bufs_L0_ipe_enc = MAX_L0_IPE_ENC_STAGGER;
4652         }
4653         else
4654         {
4655             num_bufs_preenc_me_que = (MIN_L0_IPE_ENC_STAGGER - 1) + MIN_L1_L0_STAGGER_NON_SEQ +
4656                                      NUM_BUFS_DECOMP_HME +
4657                                      ps_enc_ctxt->ps_stat_prms->s_lap_prms.i4_rc_look_ahead_pics;
4658 
4659             num_bufs_L0_ipe_enc = MIN_L0_IPE_ENC_STAGGER;
4660         }
4661         for(buf_id_ctr = 0; buf_id_ctr < num_bufs_preenc_me_que; buf_id_ctr++)
4662         {
4663             /* release encoder owned input buffer*/
4664             ihevce_q_rel_buf((void *)ps_enc_ctxt, IHEVCE_PRE_ENC_ME_Q, buf_id_ctr);
4665         }
4666         for(buf_id_ctr = 0; buf_id_ctr < num_bufs_L0_ipe_enc; buf_id_ctr++)
4667         {
4668             /* release encoder owned input buffer*/
4669             ihevce_q_rel_buf((void *)ps_enc_ctxt, IHEVCE_L0_IPE_ENC_Q, buf_id_ctr);
4670         }
4671         for(frm_id_ctr = 0; frm_id_ctr < NUM_ME_ENC_BUFS; frm_id_ctr++)
4672         {
4673             for(i = 0; i < ps_enc_ctxt->i4_num_bitrates; i++)
4674             {
4675                 if(NULL != ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[frm_id_ctr][i])
4676                 {
4677                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[frm_id_ctr][i]
4678                         ->i4_frm_proc_valid_flag = 0;
4679                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[frm_id_ctr][i]->i4_end_flag = 1;
4680                     /* set the output buffer as produced */
4681                     ihevce_q_set_buff_prod(
4682                         (void *)ps_enc_ctxt,
4683                         IHEVCE_FRM_PRS_ENT_COD_Q + i,
4684                         ps_enc_ctxt->s_multi_thrd.out_buf_id[frm_id_ctr][i]);
4685                 }
4686             }
4687         }
4688         for(buf_id_ctr = 0; buf_id_ctr < NUM_FRMPROC_ENTCOD_BUFS;
4689             buf_id_ctr++) /*** Set buffer produced for NUM_FRMPROC_ENTCOD_BUFS buffers for entropy to exit ***/
4690         {
4691             for(i = 0; i < ps_enc_ctxt->i4_num_bitrates; i++)
4692             {
4693                 ps_curr_out_enc_ent[i] = (frm_proc_ent_cod_ctxt_t *)ihevce_q_get_free_buff(
4694                     (void *)ps_enc_ctxt,
4695                     IHEVCE_FRM_PRS_ENT_COD_Q + i, /*decides the buffer queue */
4696                     &out_buf_id_enc_ent[i],
4697                     BUFF_QUE_NON_BLOCKING_MODE);
4698                 if(NULL != ps_curr_out_enc_ent[i])
4699                 {
4700                     ps_curr_out_enc_ent[i]->i4_frm_proc_valid_flag = 0;
4701                     ps_curr_out_enc_ent[i]->i4_end_flag = 1;
4702                     /* set the output buffer as produced */
4703                     ihevce_q_set_buff_prod(
4704                         (void *)ps_enc_ctxt, IHEVCE_FRM_PRS_ENT_COD_Q + i, out_buf_id_enc_ent[i]);
4705                 }
4706             }
4707         }
4708     }
4709 
4710     /* The last thread coming out of Enc. Proc. */
4711     /* Release all the Recon buffers the application might have queued in */
4712     if((ps_enc_ctxt->s_multi_thrd.num_thrds_done ==
4713         ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds) &&
4714        (ps_enc_ctxt->ps_stat_prms->i4_save_recon != 0) &&
4715        (ps_enc_ctxt->s_multi_thrd.i4_is_recon_free_done == 0))
4716     {
4717         WORD32 i4_bitrate_ctr;
4718 
4719         for(i4_bitrate_ctr = 0; i4_bitrate_ctr < i4_num_bitrates; i4_bitrate_ctr++)
4720         {
4721             WORD32 end_flag = 0;
4722             while(0 == end_flag)
4723             {
4724                 /*swaping of buf_id for 0th and reference bitrate location, as encoder
4725                 assumes always 0th loc for reference bitrate and app must receive in
4726                 the configured order*/
4727                 WORD32 i4_recon_buf_id = i4_bitrate_ctr;
4728                 if(i4_bitrate_ctr == 0)
4729                 {
4730                     i4_recon_buf_id = ps_enc_ctxt->i4_ref_mbr_id;
4731                 }
4732                 else if(i4_bitrate_ctr == ps_enc_ctxt->i4_ref_mbr_id)
4733                 {
4734                     i4_recon_buf_id = 0;
4735                 }
4736 
4737                 /* ------- get free Recon buffer from Frame buffer que ---------- */
4738                 /* There is a separate queue for each bit-rate instnace. The recon
4739                 buffer is acquired from the corresponding queue based on the
4740                 bitrate instnace */
4741                 ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr] =
4742                     (iv_enc_recon_data_buffs_t *)ihevce_q_get_filled_buff(
4743                         (void *)ps_enc_ctxt,
4744                         IHEVCE_RECON_DATA_Q + i4_recon_buf_id, /*decides the buffer queue */
4745                         &ps_enc_ctxt->s_multi_thrd.recon_buf_id[i4_enc_frm_id][i4_bitrate_ctr],
4746                         BUFF_QUE_BLOCKING_MODE);
4747 
4748                 /* Update the end_flag from application */
4749                 end_flag = ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr]
4750                                ->i4_is_last_buf;
4751 
4752                 ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_end_flag =
4753                     1;
4754                 ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_y_pixels =
4755                     0;
4756                 ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_uv_pixels =
4757                     0;
4758 
4759                 /* Call back to Apln. saying recon buffer is produced */
4760                 ps_hle_ctxt->ihevce_output_recon_fill_done(
4761                     ps_hle_ctxt->pv_recon_cb_handle,
4762                     ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr],
4763                     i4_recon_buf_id, /* br instance */
4764                     i4_resolution_id /* res_intance */);
4765 
4766                 /* --- release the current recon buffer ---- */
4767                 ihevce_q_rel_buf(
4768                     (void *)ps_enc_ctxt,
4769                     (IHEVCE_RECON_DATA_Q + i4_recon_buf_id),
4770                     ps_enc_ctxt->s_multi_thrd.recon_buf_id[i4_enc_frm_id][i4_bitrate_ctr]);
4771             }
4772         }
4773         /* Set the recon free done flag */
4774         ps_enc_ctxt->s_multi_thrd.i4_is_recon_free_done = 1;
4775     }
4776 
4777     /****** UnLock the critical section ******/
4778     if(NULL != ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id])
4779     {
4780         WORD32 result;
4781         result =
4782             osal_mutex_unlock(ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id]);
4783 
4784         if(OSAL_SUCCESS != result)
4785             return 0;
4786     }
4787 
4788     return (0);
4789 }
4790 
4791 /*!
4792 ******************************************************************************
4793 * \if Function name : ihevce_set_pre_enc_prms \endif
4794 *
4795 * \brief
4796 *    Set CTB parameters
4797 *    Set ME params
4798 *    Set pps, sps, vps, vui params
4799 *    Do RC init
4800 *
4801 * \param[in] Encoder context pointer
4802 *
4803 * \return
4804 *    None
4805 *
4806 * \author
4807 *  Ittiam
4808 *
4809 *****************************************************************************
4810 */
ihevce_set_pre_enc_prms(enc_ctxt_t * ps_enc_ctxt)4811 void ihevce_set_pre_enc_prms(enc_ctxt_t *ps_enc_ctxt)
4812 {
4813     WORD32 i;
4814     WORD32 i4_num_instance,
4815         i4_resolution_id = ps_enc_ctxt->i4_resolution_id;  //number of bit-rate instances
4816 
4817     i4_num_instance = ps_enc_ctxt->i4_num_bitrates;
4818 
4819 #if PIC_ALIGN_CTB_SIZE
4820 
4821     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd =
4822         ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width +
4823         SET_CTB_ALIGN(
4824             ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width,
4825             ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size);
4826 
4827     ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz =
4828         ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd / ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size;
4829 
4830     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht =
4831         ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height +
4832         SET_CTB_ALIGN(
4833             ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height,
4834             ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size);
4835 
4836     ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_vert =
4837         ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht / ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size;
4838 #else  // PIC_ALIGN_CTB_SIZE
4839     /* Allign the frame width to min CU size */
4840     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd =
4841         ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width +
4842         SET_CTB_ALIGN(
4843             ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width,
4844             ps_enc_ctxt->s_frm_ctb_prms.i4_min_cu_size);
4845 
4846     ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz =
4847         ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd / ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size;
4848 
4849     if((ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd %
4850         ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size) != 0)
4851         ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz =
4852             ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz + 1;
4853 
4854     /* Allign the frame hieght to min CU size */
4855     ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht =
4856         ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height +
4857         SET_CTB_ALIGN(
4858             ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height,
4859             ps_enc_ctxt->s_frm_ctb_prms.i4_min_cu_size);
4860 
4861     ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_vert =
4862         ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht / ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size;
4863 
4864     if((ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht %
4865         ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size) != 0)
4866         ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_vert =
4867             ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_vert + 1;
4868 
4869 #endif  // PIC_ALIGN_CTB_SIZE
4870 
4871     ps_enc_ctxt->s_frm_ctb_prms.i4_max_cus_in_row = ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz *
4872                                                     ps_enc_ctxt->s_frm_ctb_prms.i4_num_cus_in_ctb;
4873 
4874     ps_enc_ctxt->s_frm_ctb_prms.i4_max_pus_in_row = ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz *
4875                                                     ps_enc_ctxt->s_frm_ctb_prms.i4_num_pus_in_ctb;
4876 
4877     ps_enc_ctxt->s_frm_ctb_prms.i4_max_tus_in_row = ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz *
4878                                                     ps_enc_ctxt->s_frm_ctb_prms.i4_num_tus_in_ctb;
4879     ihevce_coarse_me_set_resolution(
4880         ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
4881         1,
4882         &ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd,
4883         &ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht);
4884 
4885     /*if Resolution need to be changed dynamically then needs to go to encode group */
4886     ihevce_me_set_resolution(
4887         ps_enc_ctxt->s_module_ctxt.pv_me_ctxt,
4888         1,
4889         &ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd,
4890         &ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht);
4891     i4_num_instance = ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id]
4892                           .i4_num_bitrate_instances;
4893     for(i = 0; i < i4_num_instance; i++)
4894     {
4895         WORD32 i4_id;
4896         /*swaping of buf_id for 0th and reference bitrate location, as encoder
4897         assumes always 0th loc for reference bitrate and app must receive in
4898         the configured order*/
4899         if(i == 0)
4900         {
4901             i4_id = ps_enc_ctxt->i4_ref_mbr_id;
4902         }
4903         else if(i == ps_enc_ctxt->i4_ref_mbr_id)
4904         {
4905             i4_id = 0;
4906         }
4907         else
4908         {
4909             i4_id = i;
4910         }
4911         /* populate vps based on encoder configuration and tools */
4912         ihevce_populate_vps(
4913             ps_enc_ctxt,
4914             &ps_enc_ctxt->as_vps[i],
4915             &ps_enc_ctxt->s_runtime_src_prms,
4916             &ps_enc_ctxt->ps_stat_prms->s_out_strm_prms,
4917             &ps_enc_ctxt->s_runtime_coding_prms,
4918             &ps_enc_ctxt->ps_stat_prms->s_config_prms,
4919             ps_enc_ctxt->ps_stat_prms,
4920             i4_resolution_id);
4921 
4922         /* populate sps based on encoder configuration and tools */
4923         ihevce_populate_sps(
4924             ps_enc_ctxt,
4925             &ps_enc_ctxt->as_sps[i],
4926             &ps_enc_ctxt->as_vps[i],
4927             &ps_enc_ctxt->s_runtime_src_prms,
4928             &ps_enc_ctxt->ps_stat_prms->s_out_strm_prms,
4929             &ps_enc_ctxt->s_runtime_coding_prms,
4930             &ps_enc_ctxt->ps_stat_prms->s_config_prms,
4931             &ps_enc_ctxt->s_frm_ctb_prms,
4932             ps_enc_ctxt->ps_stat_prms,
4933             i4_resolution_id);
4934 
4935         /* populate pps based on encoder configuration and tools */
4936         ihevce_populate_pps(
4937             &ps_enc_ctxt->as_pps[i],
4938             &ps_enc_ctxt->as_sps[i],
4939             &ps_enc_ctxt->s_runtime_src_prms,
4940             &ps_enc_ctxt->ps_stat_prms->s_out_strm_prms,
4941             &ps_enc_ctxt->s_runtime_coding_prms,
4942             &ps_enc_ctxt->ps_stat_prms->s_config_prms,
4943             ps_enc_ctxt->ps_stat_prms,
4944             i4_id,
4945             i4_resolution_id,
4946             ps_enc_ctxt->ps_tile_params_base,
4947             &ps_enc_ctxt->ai4_column_width_array[0],
4948             &ps_enc_ctxt->ai4_row_height_array[0]);
4949 
4950         // if(ps_enc_ctxt->as_sps[i].i1_vui_parameters_present_flag == 1)
4951         {
4952             WORD32 error_code = ihevce_populate_vui(
4953                                     &ps_enc_ctxt->as_sps[i].s_vui_parameters,
4954                                     &ps_enc_ctxt->as_sps[i],
4955                                     &ps_enc_ctxt->s_runtime_src_prms,
4956                                     &ps_enc_ctxt->ps_stat_prms->s_vui_sei_prms,
4957                                     i4_resolution_id,
4958                                     &ps_enc_ctxt->s_runtime_tgt_params,
4959                                     ps_enc_ctxt->ps_stat_prms,
4960                                     i4_id);
4961             if (error_code)
4962             {
4963                 ((ihevce_hle_ctxt_t *)ps_enc_ctxt->pv_hle_ctxt)->i4_error_code = error_code;
4964                 return;
4965             }
4966         }
4967     }
4968 
4969     osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4970     /* run the loop over all bit-rate instnaces */
4971     for(i = 0; i < i4_num_instance; i++)
4972     {
4973         /*HEVC_RC Do one time initialization of rate control*/
4974         ihevce_rc_init(
4975             (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
4976             &ps_enc_ctxt->s_runtime_src_prms,
4977             &ps_enc_ctxt->s_runtime_tgt_params,
4978             &ps_enc_ctxt->s_rc_quant,
4979             &ps_enc_ctxt->ps_stat_prms->s_sys_api,
4980             &ps_enc_ctxt->ps_stat_prms->s_lap_prms,
4981             ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc);
4982 
4983         ihevce_vbv_complaince_init_level(
4984             (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
4985             &ps_enc_ctxt->as_sps[i].s_vui_parameters);
4986     }
4987     osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4988 }
4989 
4990 /*!
4991 ******************************************************************************
4992 * \if Function name : ihevce_pre_enc_init \endif
4993 *
4994 * \brief
4995 *   set out_buf params
4996 *   Calculate end_flag if flushmode on
4997 *   Slice initialization
4998 *   Populate SIE params
4999 *   reference list creation
5000 *
5001 * \param[in] Encoder context pointer
5002 *
5003 * \return
5004 *    None
5005 *
5006 * \author
5007 *  Ittiam
5008 *
5009 *****************************************************************************
5010 */
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)5011 void ihevce_pre_enc_init(
5012     enc_ctxt_t *ps_enc_ctxt,
5013     ihevce_lap_enc_buf_t *ps_curr_inp,
5014     pre_enc_me_ctxt_t *ps_curr_out,
5015     WORD32 *pi4_end_flag_ret,
5016     WORD32 *pi4_cur_qp_ret,
5017     WORD32 *pi4_decomp_lyr_idx,
5018     WORD32 i4_ping_pong)
5019 {
5020     WORD32 end_flag = 0;
5021     WORD32 cur_qp;
5022     //recon_pic_buf_t *ps_frm_recon;
5023     WORD32 first_field = 1;
5024     WORD32 i4_field_pic = ps_enc_ctxt->s_runtime_src_prms.i4_field_pic;
5025     WORD32 i4_decomp_lyrs_idx = 0;
5026     WORD32 i4_resolution_id = ps_enc_ctxt->i4_resolution_id;
5027     WORD32 slice_type = ISLICE;
5028     WORD32 nal_type;
5029     WORD32 min_cu_size;
5030 
5031     WORD32 stasino_enabled;
5032 
5033     /* copy the time stamps from inp to entropy inp */
5034     ps_curr_out->i4_inp_timestamp_low = ps_curr_inp->s_input_buf.i4_inp_timestamp_low;
5035     ps_curr_out->i4_inp_timestamp_high = ps_curr_inp->s_input_buf.i4_inp_timestamp_high;
5036     ps_curr_out->pv_app_frm_ctxt = ps_curr_inp->s_input_buf.pv_app_frm_ctxt;
5037 
5038     /* get the min cu size from config params */
5039     min_cu_size = ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_min_log2_cu_size;
5040 
5041     min_cu_size = 1 << min_cu_size;
5042 
5043     ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd =
5044         ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd +
5045         SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd, min_cu_size);
5046 
5047     ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht =
5048         ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht +
5049         SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht, min_cu_size);
5050 
5051     ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd =
5052         ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd +
5053         SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd, min_cu_size);
5054 
5055     if(IV_YUV_420SP_UV == ps_enc_ctxt->ps_stat_prms->s_src_prms.i4_chr_format)
5056     {
5057         ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht =
5058             ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht +
5059             SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht, (min_cu_size >> 1));
5060     }
5061     else if(IV_YUV_422SP_UV == ps_enc_ctxt->ps_stat_prms->s_src_prms.i4_chr_format)
5062     {
5063         ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht =
5064             ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht +
5065             SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht, min_cu_size);
5066     }
5067 
5068     /* update the END flag from LAP out */
5069     end_flag = ps_curr_inp->s_lap_out.i4_end_flag;
5070     ps_curr_out->i4_end_flag = end_flag;
5071     ps_enc_ctxt->s_multi_thrd.i4_last_pic_flag = end_flag;
5072 
5073     /* ----------------------------------------------------------------------*/
5074     /*  Slice initialization for current frame; Required for entropy context */
5075     /* ----------------------------------------------------------------------*/
5076     {
5077         WORD32 cur_poc = ps_curr_inp->s_lap_out.i4_poc;
5078 
5079         /* max merge candidates derived based on quality preset for now */
5080         WORD32 max_merge_candidates = 2;
5081 
5082         /* pocs less than random acess poc tagged for discard as they */
5083         /* could be refering to pics before the cra.                  */
5084 
5085         /* CRA case: as the leading pictures can refer the picture precedes the associated
5086         IRAP(CRA) in decoding order, hence make it Random access skipped leading pictures (RASL)*/
5087 
5088         if((1 == ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.i4_enable_temporal_scalability) &&
5089            (ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_max_temporal_layers ==
5090             ps_curr_inp->s_lap_out.i4_temporal_lyr_id))  //TEMPORALA_SCALABILITY CHANGES
5091         {
5092             if(ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5093             {
5094                 nal_type = (cur_poc < ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5095                                ? (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_RASL_R : NAL_RASL_N)
5096                                : (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_TSA_R : NAL_TSA_N);
5097             }
5098             /* IDR case: as the leading pictures can't refer the picture precedes the associated
5099             IRAP(IDR) in decoding order, hence make it Random access decodable leading pictures (RADL)*/
5100             else
5101             {
5102                 nal_type = (cur_poc < ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5103                                ? (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_RADL_R : NAL_RADL_N)
5104                                : (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_TSA_R : NAL_TSA_N);
5105             }
5106         }
5107         else
5108         {
5109             if(ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
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_RASL_R : NAL_RASL_N)
5113                                : (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_TRAIL_R : NAL_TRAIL_N);
5114             }
5115             /* IDR case: as the leading pictures can't refer the picture precedes the associated
5116             IRAP(IDR) in decoding order, hence make it Random access decodable leading pictures (RADL)*/
5117             else
5118             {
5119                 nal_type = (cur_poc < ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5120                                ? (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_RADL_R : NAL_RADL_N)
5121                                : (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_TRAIL_R : NAL_TRAIL_N);
5122             }
5123         }
5124 
5125         switch(ps_curr_inp->s_lap_out.i4_pic_type)
5126         {
5127         case IV_IDR_FRAME:
5128             /*  IDR pic */
5129             slice_type = ISLICE;
5130             nal_type = NAL_IDR_W_LP;
5131             cur_poc = 0;
5132             ps_enc_ctxt->i4_cra_poc = cur_poc;
5133             break;
5134 
5135         case IV_I_FRAME:
5136             slice_type = ISLICE;
5137 
5138             if(ps_curr_inp->s_lap_out.i4_is_cra_pic)
5139             {
5140                 nal_type = NAL_CRA;
5141             }
5142 
5143             ps_enc_ctxt->i4_cra_poc = cur_poc;
5144             break;
5145 
5146         case IV_P_FRAME:
5147             slice_type = PSLICE;
5148             break;
5149 
5150         case IV_B_FRAME:
5151             /* TODO : Mark the nal type as NAL_TRAIL_N for non ref pics */
5152             slice_type = BSLICE;
5153             break;
5154 
5155         default:
5156             /* This should never occur */
5157             ASSERT(0);
5158         }
5159 
5160         /* number of merge candidates and error metric chosen based on quality preset */
5161         switch(ps_curr_inp->s_lap_out.i4_quality_preset)
5162         {
5163         case IHEVCE_QUALITY_P0:
5164             max_merge_candidates = 5;
5165             break;
5166 
5167         case IHEVCE_QUALITY_P2:
5168             max_merge_candidates = 5;
5169             break;
5170 
5171         case IHEVCE_QUALITY_P3:
5172             max_merge_candidates = 3;
5173             break;
5174 
5175         case IHEVCE_QUALITY_P4:
5176         case IHEVCE_QUALITY_P5:
5177         case IHEVCE_QUALITY_P6:
5178             max_merge_candidates = 2;
5179             break;
5180 
5181         default:
5182             ASSERT(0);
5183         }
5184 
5185         /* acquire mutex lock for rate control calls */
5186         osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
5187         {
5188             ps_curr_inp->s_rc_lap_out.i4_num_pels_in_frame_considered =
5189                 ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht *
5190                 ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd;
5191 
5192             /*initialize the frame info stat inside LAP out, Data inside this will be populated in ihevce_rc_get_bpp_based_frame_qp call*/
5193             ps_curr_inp->s_rc_lap_out.ps_frame_info = &ps_curr_inp->s_frame_info;
5194 
5195             ps_curr_inp->s_rc_lap_out.i4_is_bottom_field = ps_curr_inp->s_input_buf.i4_bottom_field;
5196             if(ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode == 3)
5197             {
5198                 /*for constant qp use same qp*/
5199                 /*HEVC_RC query rate control for qp*/
5200                 cur_qp = ihevce_rc_pre_enc_qp_query(
5201                     (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
5202                     &ps_curr_inp->s_rc_lap_out,
5203                     0);
5204             }
5205             else
5206             {
5207                 cur_qp = ihevce_rc_get_bpp_based_frame_qp(
5208                     (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0], &ps_curr_inp->s_rc_lap_out);
5209             }
5210         }
5211         /* release mutex lock after rate control calls */
5212         osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
5213 
5214         /* store the QP in output prms */
5215         /* The same qp is also used in enc thread only for ME*/
5216         ps_curr_out->i4_curr_frm_qp = cur_qp;
5217 
5218         /* slice header entropy syn memory is not valid in pre encode stage */
5219         ps_curr_out->s_slice_hdr.pu4_entry_point_offset = NULL;
5220 
5221         /* derive the flag which indicates if stasino is enabled */
5222         stasino_enabled = (ps_enc_ctxt->s_runtime_coding_prms.i4_vqet &
5223                            (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_NOISE_PRESERVATION)) &&
5224                           (ps_enc_ctxt->s_runtime_coding_prms.i4_vqet &
5225                            (1 << BITPOS_IN_VQ_TOGGLE_FOR_CONTROL_TOGGLER));
5226 
5227         /* initialize the slice header */
5228         ihevce_populate_slice_header(
5229             &ps_curr_out->s_slice_hdr,
5230             &ps_enc_ctxt->as_pps[0],
5231             &ps_enc_ctxt->as_sps[0],
5232             nal_type,
5233             slice_type,
5234             0,
5235             0,
5236             ps_curr_inp->s_lap_out.i4_poc,
5237             cur_qp,
5238             max_merge_candidates,
5239             ps_enc_ctxt->ps_stat_prms->s_pass_prms.i4_pass,
5240             ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id]
5241                 .i4_quality_preset,
5242             stasino_enabled);
5243 
5244         ps_curr_out->i4_slice_nal_type = nal_type;
5245 
5246         ps_curr_out->s_slice_hdr.u4_nuh_temporal_id = 0;
5247 
5248         if(1 == ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.i4_enable_temporal_scalability)
5249         {
5250             ps_curr_out->s_slice_hdr.u4_nuh_temporal_id =
5251                 (ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_max_temporal_layers ==
5252                  ps_curr_inp->s_lap_out.i4_temporal_lyr_id);  //TEMPORALA_SCALABILITY CHANGES
5253         }
5254 
5255         /* populate sps, vps and pps pointers for the entropy input params */
5256         ps_curr_out->ps_pps = &ps_enc_ctxt->as_pps[0];
5257         ps_curr_out->ps_sps = &ps_enc_ctxt->as_sps[0];
5258         ps_curr_out->ps_vps = &ps_enc_ctxt->as_vps[0];
5259     }
5260 
5261     /* By default, Sei messages are set to 0, to avoid unintialised memory access */
5262     memset(&ps_curr_out->s_sei, 0, sizeof(sei_params_t));
5263 
5264     /* VUI, SEI flags reset */
5265     ps_curr_out->s_sei.i1_sei_parameters_present_flag = 0;
5266     ps_curr_out->s_sei.i1_buf_period_params_present_flag = 0;
5267     ps_curr_out->s_sei.i1_pic_timing_params_present_flag = 0;
5268     ps_curr_out->s_sei.i1_recovery_point_params_present_flag = 0;
5269     ps_curr_out->s_sei.i1_decoded_pic_hash_sei_flag = 0;
5270     ps_curr_out->s_sei.i4_sei_mastering_disp_colour_vol_params_present_flags = 0;
5271 
5272     if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_enable_flag == 1)
5273     {
5274         /* insert buffering period, display volume, recovery point only at irap points */
5275         WORD32 insert_per_irap =
5276             ((slice_type == ISLICE) &&
5277              (((NAL_IDR_N_LP == nal_type) || (NAL_CRA == nal_type)) || (NAL_IDR_W_LP == nal_type)));
5278 
5279         ps_curr_out->s_sei.i1_sei_parameters_present_flag = 1;
5280 
5281         /* populate Sei buffering period based on encoder configuration and tools */
5282         if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_buffer_period_flags == 1)
5283         {
5284             ihevce_populate_buffering_period_sei(
5285                 &ps_curr_out->s_sei,
5286                 &ps_enc_ctxt->as_sps[0].s_vui_parameters,
5287                 &ps_enc_ctxt->as_sps[0],
5288                 &ps_enc_ctxt->ps_stat_prms->s_vui_sei_prms);
5289 
5290             ps_curr_out->s_sei.i1_buf_period_params_present_flag = insert_per_irap;
5291 
5292             ihevce_populate_active_parameter_set_sei(
5293                 &ps_curr_out->s_sei, &ps_enc_ctxt->as_vps[0], &ps_enc_ctxt->as_sps[0]);
5294         }
5295 
5296         /* populate Sei picture timing based on encoder configuration and tools */
5297         if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_pic_timing_flags == 1)
5298         {
5299             ihevce_populate_picture_timing_sei(
5300                 &ps_curr_out->s_sei,
5301                 &ps_enc_ctxt->as_sps[0].s_vui_parameters,
5302                 &ps_enc_ctxt->s_runtime_src_prms,
5303                 ps_curr_inp->s_input_buf.i4_bottom_field);
5304             ps_curr_out->s_sei.i1_pic_timing_params_present_flag = 1;
5305         }
5306 
5307         /* populate Sei recovery point based on encoder configuration and tools */
5308         if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_recovery_point_flags == 1)
5309         {
5310             ihevce_populate_recovery_point_sei(
5311                 &ps_curr_out->s_sei, &ps_enc_ctxt->ps_stat_prms->s_vui_sei_prms);
5312             ps_curr_out->s_sei.i1_recovery_point_params_present_flag = insert_per_irap;
5313         }
5314 
5315         /* populate mastering_display_colour_volume parameters */
5316         if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_mastering_disp_colour_vol_flags == 1)
5317         {
5318             ihevce_populate_mastering_disp_col_vol_sei(
5319                 &ps_curr_out->s_sei, &ps_enc_ctxt->ps_stat_prms->s_out_strm_prms);
5320 
5321             ps_curr_out->s_sei.i4_sei_mastering_disp_colour_vol_params_present_flags =
5322                 insert_per_irap;
5323         }
5324 
5325         /* populate SEI Hash Flag based on encoder configuration */
5326         if(0 != ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag)
5327         {
5328             /* Sanity checks */
5329             ASSERT(0 != ps_enc_ctxt->as_sps[0].i1_chroma_format_idc);
5330 
5331             ASSERT(
5332                 (0 < ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag) &&
5333                 (4 > ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag));
5334 
5335             /* MD5 is not supported now! picture_md5[cIdx][i] pblm */
5336             ASSERT(1 != ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag);
5337 
5338             ps_curr_out->s_sei.i1_decoded_pic_hash_sei_flag =
5339                 ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag;
5340         }
5341     }
5342 
5343     /* For interlace pictures, first_field depends on topfield_first and bottom field */
5344     if(i4_field_pic)
5345     {
5346         first_field =
5347             (ps_curr_inp->s_input_buf.i4_topfield_first ^ ps_curr_inp->s_input_buf.i4_bottom_field);
5348     }
5349 
5350     /* get frame level lambda params */
5351     ihevce_get_frame_lambda_prms(
5352         ps_enc_ctxt,
5353         ps_curr_out,
5354         cur_qp,
5355         first_field,
5356         ps_curr_inp->s_lap_out.i4_is_ref_pic,
5357         ps_curr_inp->s_lap_out.i4_temporal_lyr_id,
5358         lamda_modifier_for_I_pic[4] /*mean TRF*/,
5359         0,
5360         PRE_ENC_LAMBDA_TYPE);
5361     /* Coarse ME and Decomp buffers sharing */
5362     {
5363         UWORD8 *apu1_lyr_bufs[MAX_NUM_HME_LAYERS];
5364         WORD32 ai4_lyr_buf_strd[MAX_NUM_HME_LAYERS];
5365 
5366         /* get the Decomposition frame buffer from ME */
5367         i4_decomp_lyrs_idx = ihevce_coarse_me_get_lyr_buf_desc(
5368             ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt, &apu1_lyr_bufs[0], &ai4_lyr_buf_strd[0]);
5369         /* register the buffers with decomp module along with frame init */
5370         ihevce_decomp_pre_intra_frame_init(
5371             ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt,
5372             &apu1_lyr_bufs[0],
5373             &ai4_lyr_buf_strd[0],
5374             ps_curr_out->ps_layer1_buf,
5375             ps_curr_out->ps_layer2_buf,
5376             ps_curr_out->ps_ed_ctb_l1,
5377             ps_curr_out->as_lambda_prms[0].i4_ol_sad_lambda_qf,
5378             ps_curr_out->ps_ctb_analyse);
5379     }
5380 
5381     /* -------------------------------------------------------- */
5382     /*   Preparing Pre encode Passes Job Queue                  */
5383     /* -------------------------------------------------------- */
5384     ihevce_prepare_pre_enc_job_queue(ps_enc_ctxt, ps_curr_inp, i4_ping_pong);
5385 
5386     /*assign return variables */
5387     *pi4_end_flag_ret = end_flag;
5388     *pi4_cur_qp_ret = cur_qp;
5389     *pi4_decomp_lyr_idx = i4_decomp_lyrs_idx;
5390     //*pps_frm_recon_ret = ps_frm_recon;
5391 }
5392 
5393 /*!
5394 ******************************************************************************
5395 * \if Function name : ihevce_pre_enc_coarse_me_init \endif
5396 *
5397 * \brief
5398 *   set out_buf params
5399 *   Calculate end_flag if flushmode on
5400 *   Slice initialization
5401 *   Populate SIE params
5402 *   reference list creation
5403 *
5404 * \param[in] Encoder context pointer
5405 *
5406 * \return
5407 *    None
5408 *
5409 * \author
5410 *  Ittiam
5411 *
5412 *****************************************************************************
5413 */
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)5414 void ihevce_pre_enc_coarse_me_init(
5415     enc_ctxt_t *ps_enc_ctxt,
5416     ihevce_lap_enc_buf_t *ps_curr_inp,
5417     pre_enc_me_ctxt_t *ps_curr_out,
5418     recon_pic_buf_t **pps_frm_recon_ret,
5419     WORD32 i4_decomp_lyrs_idx,
5420     WORD32 i4_cur_qp,
5421     WORD32 i4_ping_pong)
5422 
5423 {
5424     /* local variables */
5425     recon_pic_buf_t *ps_frm_recon;
5426     coarse_me_master_ctxt_t *ps_ctxt = NULL;
5427     ps_ctxt = (coarse_me_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt;
5428     /* Reference buffer management and reference list creation for pre enc group */
5429     ihevce_pre_enc_manage_ref_pics(ps_enc_ctxt, ps_curr_inp, ps_curr_out, i4_ping_pong);
5430 
5431     /* get a free recon buffer for current picture  */
5432     {
5433         WORD32 ctr;
5434 
5435         ps_frm_recon = NULL;
5436         for(ctr = 0; ctr < ps_enc_ctxt->i4_pre_enc_num_buf_recon_q; ctr++)
5437         {
5438             if(1 == ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr]->i4_is_free)
5439             {
5440                 ps_frm_recon = ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr];
5441                 break;
5442             }
5443         }
5444     }
5445     /* should not be NULL */
5446     ASSERT(ps_frm_recon != NULL);
5447 
5448     /* populate reference /recon params based on LAP output */
5449     ps_frm_recon->i4_is_free = 0;
5450     /* top first field is set to 1 by application */
5451     ps_frm_recon->i4_topfield_first = ps_curr_inp->s_input_buf.i4_topfield_first;
5452     ps_frm_recon->i4_poc = ps_curr_inp->s_lap_out.i4_poc;
5453     ps_frm_recon->i4_pic_type = ps_curr_inp->s_lap_out.i4_pic_type;
5454     ps_frm_recon->i4_display_num = ps_curr_inp->s_lap_out.i4_display_num;
5455     /* bottom field is toggled for every field by application */
5456     ps_frm_recon->i4_bottom_field = ps_curr_inp->s_input_buf.i4_bottom_field;
5457 
5458     /* Reference picture property is given by LAP */
5459     ps_frm_recon->i4_is_reference = ps_curr_inp->s_lap_out.i4_is_ref_pic;
5460 
5461     /* Deblock a picture for all reference frames unconditionally. */
5462     /* Deblock non ref if psnr compute or save recon is enabled    */
5463     ps_frm_recon->i4_deblk_pad_hpel_cur_pic = ps_frm_recon->i4_is_reference ||
5464                                               (ps_enc_ctxt->ps_stat_prms->i4_save_recon);
5465 
5466     /* set the width, height and stride to defalut values */
5467     ps_frm_recon->s_yuv_buf_desc.i4_y_ht = 0;
5468     ps_frm_recon->s_yuv_buf_desc.i4_uv_ht = 0;
5469     ps_frm_recon->s_yuv_buf_desc.i4_y_wd = 0;
5470     ps_frm_recon->s_yuv_buf_desc.i4_uv_wd = 0;
5471     ps_frm_recon->s_yuv_buf_desc.i4_y_strd = 0;
5472     ps_frm_recon->s_yuv_buf_desc.i4_uv_strd = 0;
5473 
5474     /* register the Layer1 MV bank pointer with ME module */
5475     ihevce_coarse_me_set_lyr1_mv_bank(
5476         ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
5477         ps_curr_inp,
5478         ps_curr_out->pv_me_mv_bank,
5479         ps_curr_out->pv_me_ref_idx,
5480         i4_decomp_lyrs_idx);
5481 
5482     /* Coarse picture level init of ME */
5483     ihevce_coarse_me_frame_init(
5484         ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
5485         ps_enc_ctxt->ps_stat_prms,
5486         &ps_enc_ctxt->s_frm_ctb_prms,
5487         &ps_curr_out->as_lambda_prms[0],
5488         ps_enc_ctxt->i4_pre_enc_num_ref_l0,
5489         ps_enc_ctxt->i4_pre_enc_num_ref_l1,
5490         ps_enc_ctxt->i4_pre_enc_num_ref_l0_active,
5491         ps_enc_ctxt->i4_pre_enc_num_ref_l1_active,
5492         &ps_enc_ctxt->aps_pre_enc_ref_lists[i4_ping_pong][LIST_0][0],
5493         &ps_enc_ctxt->aps_pre_enc_ref_lists[i4_ping_pong][LIST_1][0],
5494         ps_curr_inp,
5495         i4_cur_qp,
5496         ps_curr_out->ps_layer1_buf,
5497         ps_curr_out->ps_ed_ctb_l1,
5498         ps_curr_out->pu1_me_reverse_map_info,
5499         ps_curr_inp->s_lap_out.i4_temporal_lyr_id);
5500 
5501     /*assign return variables */
5502     *pps_frm_recon_ret = ps_frm_recon;
5503 }
5504 
5505 /*!
5506 ******************************************************************************
5507 * \brief
5508 *  Function to calculate modulation based on spatial variance across lap period
5509 *
5510 *****************************************************************************
5511 */
ihevce_variance_calc_acc_activity(enc_ctxt_t * ps_enc_ctxt,WORD32 i4_cur_ipe_idx)5512 void ihevce_variance_calc_acc_activity(enc_ctxt_t *ps_enc_ctxt, WORD32 i4_cur_ipe_idx)
5513 {
5514     pre_enc_me_ctxt_t *ps_curr_out = ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[i4_cur_ipe_idx];
5515     WORD32 is_curr_bslice = (ps_curr_out->s_slice_hdr.i1_slice_type == BSLICE);
5516 #if MODULATION_OVER_LAP
5517     WORD32 loop_lap2 = MAX(1, ps_enc_ctxt->s_multi_thrd.i4_delay_pre_me_btw_l0_ipe - 1);
5518 #else
5519     WORD32 loop_lap2 = 1;
5520 #endif
5521     WORD32 i4_delay_loop = ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe;
5522     WORD32 i, j;
5523 
5524     ps_curr_out->i8_acc_frame_8x8_sum_act_sqr = 0;
5525     ps_curr_out->i8_acc_frame_8x8_sum_act_for_strength = 0;
5526     for(i = 0; i < 2; i++)
5527     {
5528         ps_curr_out->i8_acc_frame_8x8_sum_act[i] = 0;
5529         ps_curr_out->i4_acc_frame_8x8_num_blks[i] = 0;
5530         ps_curr_out->i8_acc_frame_16x16_sum_act[i] = 0;
5531         ps_curr_out->i4_acc_frame_16x16_num_blks[i] = 0;
5532         ps_curr_out->i8_acc_frame_32x32_sum_act[i] = 0;
5533         ps_curr_out->i4_acc_frame_32x32_num_blks[i] = 0;
5534     }
5535     ps_curr_out->i8_acc_frame_16x16_sum_act[i] = 0;
5536     ps_curr_out->i4_acc_frame_16x16_num_blks[i] = 0;
5537     ps_curr_out->i8_acc_frame_32x32_sum_act[i] = 0;
5538     ps_curr_out->i4_acc_frame_32x32_num_blks[i] = 0;
5539 
5540     if(!is_curr_bslice)
5541     {
5542         for(i = 0; i < loop_lap2; i++)
5543         {
5544             WORD32 ipe_idx_tmp = (i4_cur_ipe_idx + i) % i4_delay_loop;
5545             ihevce_lap_enc_buf_t *ps_in = ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[ipe_idx_tmp];
5546             pre_enc_me_ctxt_t *ps_out = ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[ipe_idx_tmp];
5547             UWORD8 is_bslice = (ps_out->s_slice_hdr.i1_slice_type == BSLICE);
5548 
5549             if(!is_bslice)
5550             {
5551                 ps_curr_out->i8_acc_frame_8x8_sum_act_sqr += ps_out->u8_curr_frame_8x8_sum_act_sqr;
5552                 ps_curr_out->i8_acc_frame_8x8_sum_act_for_strength += ps_out->i4_curr_frame_8x8_sum_act_for_strength[0];
5553                 for(j = 0; j < 2; j++)
5554                 {
5555                     ps_curr_out->i8_acc_frame_8x8_sum_act[j] += ps_out->i8_curr_frame_8x8_sum_act[j];
5556                     ps_curr_out->i4_acc_frame_8x8_num_blks[j] += ps_out->i4_curr_frame_8x8_num_blks[j];
5557                     ps_curr_out->i8_acc_frame_16x16_sum_act[j] += ps_out->i8_curr_frame_16x16_sum_act[j];
5558                     ps_curr_out->i4_acc_frame_16x16_num_blks[j] += ps_out->i4_curr_frame_16x16_num_blks[j];
5559                     ps_curr_out->i8_acc_frame_32x32_sum_act[j] += ps_out->i8_curr_frame_32x32_sum_act[j];
5560                     ps_curr_out->i4_acc_frame_32x32_num_blks[j] += ps_out->i4_curr_frame_32x32_num_blks[j];
5561                 }
5562                 ps_curr_out->i8_acc_frame_16x16_sum_act[j] += ps_out->i8_curr_frame_16x16_sum_act[j];
5563                 ps_curr_out->i4_acc_frame_16x16_num_blks[j] += ps_out->i4_curr_frame_16x16_num_blks[j];
5564                 ps_curr_out->i8_acc_frame_32x32_sum_act[j] += ps_out->i8_curr_frame_32x32_sum_act[j];
5565                 ps_curr_out->i4_acc_frame_32x32_num_blks[j] += ps_out->i4_curr_frame_32x32_num_blks[j];
5566             }
5567             if(NULL == ps_in->s_rc_lap_out.ps_rc_lap_out_next_encode)
5568                 break;
5569         }
5570 
5571         for(j = 0; j < 3; j++)
5572         {
5573             if(j < 2)
5574                 ASSERT(0 != ps_curr_out->i4_acc_frame_8x8_num_blks[j]);
5575             ASSERT(0 != ps_curr_out->i4_acc_frame_16x16_num_blks[j]);
5576             ASSERT(0 != ps_curr_out->i4_acc_frame_32x32_num_blks[j]);
5577 
5578 #define AVG_ACTIVITY(a, b, c) a = ((b + (c >> 1)) / c)
5579 
5580             if(j < 2)
5581             {
5582                 if(0 == ps_curr_out->i4_acc_frame_8x8_num_blks[j])
5583                 {
5584                     ps_curr_out->i8_curr_frame_8x8_avg_act[j] = 0;
5585                 }
5586                 else
5587                 {
5588                     AVG_ACTIVITY(ps_curr_out->i8_curr_frame_8x8_sum_act_for_strength,
5589                                  ps_curr_out->i8_acc_frame_8x8_sum_act_for_strength,
5590                                  ps_curr_out->i4_acc_frame_8x8_num_blks[j]);
5591                     AVG_ACTIVITY(ps_curr_out->i8_curr_frame_8x8_avg_act[j],
5592                                  ps_curr_out->i8_acc_frame_8x8_sum_act[j],
5593                                  ps_curr_out->i4_acc_frame_8x8_num_blks[j]);
5594                     ps_curr_out->ld_curr_frame_8x8_log_avg[j] =
5595                         fast_log2(1 + ps_curr_out->i8_curr_frame_8x8_avg_act[j]);
5596                 }
5597             }
5598 
5599             if(0 == ps_curr_out->i4_acc_frame_16x16_num_blks[j])
5600             {
5601                 ps_curr_out->i8_curr_frame_16x16_avg_act[j] = 0;
5602             }
5603             else
5604             {
5605                 AVG_ACTIVITY(ps_curr_out->i8_curr_frame_16x16_avg_act[j],
5606                              ps_curr_out->i8_acc_frame_16x16_sum_act[j],
5607                              ps_curr_out->i4_acc_frame_16x16_num_blks[j]);
5608                 ps_curr_out->ld_curr_frame_16x16_log_avg[j] =
5609                     fast_log2(1 + ps_curr_out->i8_curr_frame_16x16_avg_act[j]);
5610             }
5611 
5612             if(0 == ps_curr_out->i4_acc_frame_32x32_num_blks[j])
5613             {
5614                 ps_curr_out->i8_curr_frame_32x32_avg_act[j] = 0;
5615             }
5616             else
5617             {
5618                 AVG_ACTIVITY(ps_curr_out->i8_curr_frame_32x32_avg_act[j],
5619                              ps_curr_out->i8_acc_frame_32x32_sum_act[j],
5620                              ps_curr_out->i4_acc_frame_32x32_num_blks[j]);
5621                 ps_curr_out->ld_curr_frame_32x32_log_avg[j] =
5622                     fast_log2(1 + ps_curr_out->i8_curr_frame_32x32_avg_act[j]);
5623             }
5624         }
5625 
5626         /* store the avg activity for B pictures */
5627 #if POW_OPT
5628         ps_enc_ctxt->ald_lap2_8x8_log_avg_act_from_T0[0] = ps_curr_out->ld_curr_frame_8x8_log_avg[0];
5629         ps_enc_ctxt->ald_lap2_8x8_log_avg_act_from_T0[1] = ps_curr_out->ld_curr_frame_8x8_log_avg[1];
5630         ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[0] = ps_curr_out->ld_curr_frame_16x16_log_avg[0];
5631         ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[1] = ps_curr_out->ld_curr_frame_16x16_log_avg[1];
5632         ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[2] = ps_curr_out->ld_curr_frame_16x16_log_avg[2];
5633         ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[0] = ps_curr_out->ld_curr_frame_32x32_log_avg[0];
5634         ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[1] = ps_curr_out->ld_curr_frame_32x32_log_avg[1];
5635         ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[2] = ps_curr_out->ld_curr_frame_32x32_log_avg[2];
5636 #else
5637         ps_enc_ctxt->ai8_lap2_8x8_avg_act_from_T0[0] = ps_curr_out->i8_curr_frame_8x8_avg_act[0];
5638         ps_enc_ctxt->ai8_lap2_8x8_avg_act_from_T0[1] = ps_curr_out->i8_curr_frame_8x8_avg_act[1];
5639         ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[0] = ps_curr_out->i8_curr_frame_16x16_avg_act[0];
5640         ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[1] = ps_curr_out->i8_curr_frame_16x16_avg_act[1];
5641         ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[2] = ps_curr_out->i8_curr_frame_16x16_avg_act[2];
5642         ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[0] = ps_curr_out->i8_curr_frame_32x32_avg_act[0];
5643         ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[1] = ps_curr_out->i8_curr_frame_32x32_avg_act[1];
5644         ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[2] = ps_curr_out->i8_curr_frame_32x32_avg_act[2];
5645 #endif
5646 
5647         /* calculate modulation index */
5648         {
5649             LWORD64 i8_mean, i8_mean_sqr, i8_variance;
5650             LWORD64 i8_deviation;
5651             WORD32 i4_mod_factor;
5652             float f_strength;
5653 
5654             if(ps_curr_out->i4_acc_frame_8x8_num_blks[0] > 0)
5655             {
5656 #if STRENGTH_BASED_ON_CURR_FRM
5657                 AVG_ACTIVITY(i8_mean_sqr, ps_curr_out->i8_curr_frame_8x8_sum_act_sqr,
5658                              ps_curr_out->i4_curr_frame_8x8_num_blks[0]);
5659 #else
5660                 AVG_ACTIVITY(i8_mean_sqr, ps_curr_out->i8_acc_frame_8x8_sum_act_sqr,
5661                              ps_curr_out->i4_acc_frame_8x8_num_blks[0]);
5662 #endif
5663                 i8_mean = ps_curr_out->i8_curr_frame_8x8_sum_act_for_strength;
5664                 i8_variance = i8_mean_sqr - (i8_mean * i8_mean);
5665                 i8_deviation = sqrt(i8_variance);
5666 
5667 #if STRENGTH_BASED_ON_DEVIATION
5668                 if(i8_deviation <= REF_MOD_DEVIATION)
5669                 {
5670                     f_strength = ((i8_deviation - BELOW_REF_DEVIATION) * REF_MOD_STRENGTH) / (REF_MOD_DEVIATION - BELOW_REF_DEVIATION);
5671                 }
5672                 else
5673                 {
5674                     f_strength = ((i8_deviation - ABOVE_REF_DEVIATION) * REF_MOD_STRENGTH) / (REF_MOD_DEVIATION - ABOVE_REF_DEVIATION);
5675                 }
5676 #else
5677                 f_strength = ((i8_mean_sqr / (float)(i8_mean * i8_mean)) - 1.0) * REF_MOD_STRENGTH / REF_MOD_VARIANCE;
5678 #endif
5679                 i4_mod_factor = (WORD32)(i8_deviation / 60);
5680                 f_strength = CLIP3(f_strength, 0.0, REF_MAX_STRENGTH);
5681             }
5682             else
5683             {
5684                 /* If not sufficient blocks are present, turn modulation index to 1  */
5685                 i4_mod_factor = 1;
5686                 f_strength = 0;
5687             }
5688             ps_curr_out->ai4_mod_factor_derived_by_variance[0] = i4_mod_factor;
5689             ps_curr_out->ai4_mod_factor_derived_by_variance[1] = i4_mod_factor;
5690             ps_curr_out->f_strength = f_strength;
5691 
5692             ps_enc_ctxt->ai4_mod_factor_derived_by_variance[0] = i4_mod_factor;
5693             ps_enc_ctxt->ai4_mod_factor_derived_by_variance[1] = i4_mod_factor;
5694             ps_enc_ctxt->f_strength = f_strength;
5695         }
5696     }
5697     else
5698     {
5699         ps_curr_out->ai4_mod_factor_derived_by_variance[0] = ps_enc_ctxt->ai4_mod_factor_derived_by_variance[0];
5700         ps_curr_out->ai4_mod_factor_derived_by_variance[1] = ps_enc_ctxt->ai4_mod_factor_derived_by_variance[1];
5701         ps_curr_out->f_strength = ps_enc_ctxt->f_strength;
5702 
5703         /* copy the prev avg activity from Tid 0 for B pictures*/
5704 #if POW_OPT
5705         ps_curr_out->ld_curr_frame_8x8_log_avg[0] = ps_enc_ctxt->ald_lap2_8x8_log_avg_act_from_T0[0];
5706         ps_curr_out->ld_curr_frame_8x8_log_avg[1] = ps_enc_ctxt->ald_lap2_8x8_log_avg_act_from_T0[1];
5707         ps_curr_out->ld_curr_frame_16x16_log_avg[0] = ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[0];
5708         ps_curr_out->ld_curr_frame_16x16_log_avg[1] = ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[1];
5709         ps_curr_out->ld_curr_frame_16x16_log_avg[2] = ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[2];
5710         ps_curr_out->ld_curr_frame_32x32_log_avg[0] = ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[0];
5711         ps_curr_out->ld_curr_frame_32x32_log_avg[1] = ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[1];
5712         ps_curr_out->ld_curr_frame_32x32_log_avg[2] = ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[2];
5713 #else
5714         ps_curr_out->i8_curr_frame_8x8_avg_act[0] = ps_enc_ctxt->ai8_lap2_8x8_avg_act_from_T0[0];
5715         ps_curr_out->i8_curr_frame_8x8_avg_act[1] = ps_enc_ctxt->ai8_lap2_8x8_avg_act_from_T0[1];
5716         ps_curr_out->i8_curr_frame_16x16_avg_act[0] = ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[0];
5717         ps_curr_out->i8_curr_frame_16x16_avg_act[1] = ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[1];
5718         ps_curr_out->i8_curr_frame_16x16_avg_act[2] = ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[2];
5719         ps_curr_out->i8_curr_frame_32x32_avg_act[0] = ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[0];
5720         ps_curr_out->i8_curr_frame_32x32_avg_act[1] = ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[1];
5721         ps_curr_out->i8_curr_frame_32x32_avg_act[2] = ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[2];
5722 #endif
5723     }
5724 #undef AVG_ACTIVITY
5725 }
5726 
5727 /*!
5728 ******************************************************************************
5729 * \if Function name : ihevce_pre_enc_process_frame_thrd \endif
5730 *
5731 * \brief
5732 *    Pre-Encode Frame processing thread interface function
5733 *
5734 * \param[in] High level encoder context pointer
5735 *
5736 * \return
5737 *    None
5738 *
5739 * \author
5740 *  Ittiam
5741 *
5742 *****************************************************************************
5743 */
ihevce_pre_enc_process_frame_thrd(void * pv_frm_proc_thrd_ctxt)5744 WORD32 ihevce_pre_enc_process_frame_thrd(void *pv_frm_proc_thrd_ctxt)
5745 {
5746     frm_proc_thrd_ctxt_t *ps_thrd_ctxt = (frm_proc_thrd_ctxt_t *)pv_frm_proc_thrd_ctxt;
5747     ihevce_hle_ctxt_t *ps_hle_ctxt = ps_thrd_ctxt->ps_hle_ctxt;
5748     enc_ctxt_t *ps_enc_ctxt = (enc_ctxt_t *)ps_thrd_ctxt->pv_enc_ctxt;
5749     multi_thrd_ctxt_t *ps_multi_thrd = &ps_enc_ctxt->s_multi_thrd;
5750     WORD32 i4_thrd_id = ps_thrd_ctxt->i4_thrd_id;
5751     WORD32 i4_resolution_id = ps_enc_ctxt->i4_resolution_id;
5752     WORD32 i4_end_flag = 0;
5753     WORD32 i4_out_flush_flag = 0;
5754     WORD32 i4_cur_decomp_idx = 0;
5755     WORD32 i4_cur_coarse_me_idx = 0;
5756     WORD32 i4_cur_ipe_idx = 0;
5757     ihevce_lap_enc_buf_t *ps_lap_inp_buf = NULL;
5758     void *pv_dep_mngr_prev_frame_pre_enc_l1 = ps_multi_thrd->pv_dep_mngr_prev_frame_pre_enc_l1;
5759     void *pv_dep_mngr_prev_frame_pre_enc_l0 = ps_multi_thrd->pv_dep_mngr_prev_frame_pre_enc_l0;
5760     void *pv_dep_mngr_prev_frame_pre_enc_coarse_me =
5761         ps_multi_thrd->pv_dep_mngr_prev_frame_pre_enc_coarse_me;
5762     WORD32 i4_num_buf_prod_for_l0_ipe = 0;
5763     WORD32 i4_decomp_end_flag = 0;
5764 
5765     (void)ps_hle_ctxt;
5766     (void)i4_resolution_id;
5767 
5768     /* ---------- Processing Loop until Flush command is received --------- */
5769     while(0 == i4_end_flag)
5770     {
5771         /* Wait till previous frame(instance)'s decomp_intra is processed */
5772         {
5773             ihevce_dmgr_chk_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_l1, i4_thrd_id);
5774         }
5775 
5776         /* ----------------------------------------------------------- */
5777         /*     decomp pre_intra init                                   */
5778         /* ----------------------------------------------------------- */
5779 
5780         /****** Lock the critical section for decomp pre_intra init ******/
5781         {
5782             WORD32 i4_status;
5783 
5784             i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_init);
5785             if(OSAL_SUCCESS != i4_status)
5786                 return 0;
5787         }
5788 
5789         ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_decomp_idx] = 0;
5790 
5791         /* init */
5792         if((ps_multi_thrd->ai4_pre_enc_init_done[i4_cur_decomp_idx] == 0) &&
5793            (0 == i4_decomp_end_flag))
5794         {
5795             ihevce_lap_enc_buf_t *ps_curr_inp = NULL;
5796             pre_enc_me_ctxt_t *ps_curr_out = NULL;
5797             WORD32 in_buf_id;
5798             WORD32 out_buf_id;
5799 
5800             do
5801             {
5802                 ps_lap_inp_buf = NULL;
5803                 if(0 == ps_multi_thrd->i4_last_inp_buf)
5804                 {
5805                     /* ------- get input buffer input data que ---------- */
5806                     ps_lap_inp_buf = (ihevce_lap_enc_buf_t *)ihevce_q_get_filled_buff(
5807                         (void *)ps_enc_ctxt,
5808                         IHEVCE_INPUT_DATA_CTRL_Q,
5809                         &in_buf_id,
5810                         BUFF_QUE_BLOCKING_MODE);
5811                     ps_multi_thrd->i4_last_inp_buf = ihevce_check_last_inp_buf(
5812                         (WORD32 *)ps_lap_inp_buf->s_input_buf.pv_synch_ctrl_bufs);
5813                 }
5814 
5815                 ps_curr_inp =
5816                     ihevce_lap_process(ps_enc_ctxt->pv_lap_interface_ctxt, ps_lap_inp_buf);
5817 
5818             } while(NULL == ps_curr_inp);
5819 
5820             /* set the flag saying init is done so that other cores dont do it */
5821             ps_multi_thrd->ai4_pre_enc_init_done[i4_cur_decomp_idx] = 1;
5822 
5823             ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_decomp_idx] = ps_curr_inp;
5824             ps_multi_thrd->ai4_in_buf_id_pre_enc[i4_cur_decomp_idx] =
5825                 ps_curr_inp->s_input_buf.i4_buf_id;
5826 
5827             /* ------- get free output buffer from pre-enc/enc buffer que ---------- */
5828             ps_curr_out = (pre_enc_me_ctxt_t *)ihevce_q_get_free_buff(
5829                 (void *)ps_enc_ctxt, IHEVCE_PRE_ENC_ME_Q, &out_buf_id, BUFF_QUE_BLOCKING_MODE);
5830             ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_decomp_idx] = ps_curr_out;
5831             ps_multi_thrd->ai4_out_buf_id_pre_enc[i4_cur_decomp_idx] = out_buf_id;
5832 
5833             if((NULL != ps_curr_inp) && (NULL != ps_curr_out))
5834             {
5835                 /* by default last picture to be encoded flag is set to 0      */
5836                 /* this flag will be used by slave threads to exit at the end */
5837                 ps_multi_thrd->i4_last_pic_flag = 0;
5838 
5839                 /* store the buffer id */
5840                 ps_curr_out->i4_buf_id = out_buf_id;
5841 
5842                 ps_curr_out->i8_acc_num_blks_high_sad = 0;
5843                 ps_curr_out->i8_total_blks = 0;
5844                 ps_curr_out->i4_is_high_complex_region = -1;
5845 
5846                 /* set the parameters for sync b/w pre-encode and encode threads */
5847                 ps_curr_out->i4_end_flag = ps_curr_inp->s_lap_out.i4_end_flag;
5848                 ps_curr_out->i4_frm_proc_valid_flag = 1;
5849                 if(ps_curr_out->i4_end_flag)
5850                 {
5851                     ps_curr_out->i4_frm_proc_valid_flag =
5852                         ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag;
5853                     ps_multi_thrd->i4_last_pic_flag = 1;
5854                     ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx] = 1;
5855                 }
5856                 if(ps_curr_inp->s_lap_out.i4_out_flush_flag)
5857                 {
5858                     ps_curr_out->i4_frm_proc_valid_flag =
5859                         ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag;
5860                 }
5861 
5862                 /* do the init processing if input frm data is valid */
5863                 if(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag)
5864                 {
5865                     WORD32 end_flag = ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx];
5866                     WORD32 cur_qp = 0, count;
5867 
5868                     ihevce_pre_enc_init(
5869                         ps_enc_ctxt,
5870                         ps_curr_inp,
5871                         ps_curr_out,
5872                         &end_flag,
5873                         &cur_qp,
5874                         &ps_multi_thrd->ai4_decomp_lyr_buf_idx[i4_cur_decomp_idx],
5875                         i4_cur_decomp_idx);
5876 
5877                     ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx] = end_flag;
5878                     ps_multi_thrd->ai4_cur_frame_qp_pre_enc[i4_cur_decomp_idx] = cur_qp;
5879 
5880                     for(count = 0; count < ((HEVCE_MAX_HEIGHT >> 1) / 8); count++)
5881                     {
5882                         ps_multi_thrd->aai4_l1_pre_intra_done[i4_cur_decomp_idx][count] = 0;
5883                     }
5884                 }
5885             }
5886         }
5887         else if(1 == i4_decomp_end_flag)
5888         {
5889             /* Once end is reached all subsequent flags are set to 1 to indicate end */
5890             ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx] = 1;
5891         }
5892 
5893         /****** UnLock the critical section after decomp pre_intra init ******/
5894         {
5895             WORD32 i4_status;
5896             i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_pre_enc_init);
5897 
5898             if(OSAL_SUCCESS != i4_status)
5899                 return 0;
5900         }
5901         if(i4_thrd_id == 0)
5902         {
5903             PROFILE_START(&ps_hle_ctxt->profile_pre_enc_l1l2[i4_resolution_id]);
5904         }
5905         /* ------------------------------------------------------------ */
5906         /*        Layer Decomp and Pre Intra Analysis                   */
5907         /* ------------------------------------------------------------ */
5908         if(0 == i4_decomp_end_flag)
5909         {
5910             pre_enc_me_ctxt_t *ps_curr_out = ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_decomp_idx];
5911 
5912             if(1 == ps_curr_out->i4_frm_proc_valid_flag)
5913             {
5914                 ihevce_decomp_pre_intra_process(
5915                     ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt,
5916                     &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_decomp_idx]->s_lap_out,
5917                     &ps_enc_ctxt->s_frm_ctb_prms,
5918                     ps_multi_thrd,
5919                     i4_thrd_id,
5920                     i4_cur_decomp_idx);
5921             }
5922         }
5923 
5924         /* ------------------------------------------------------------ */
5925         /*        Layer Decomp and Pre Intra Deinit                     */
5926         /* ------------------------------------------------------------ */
5927 
5928         /****** Lock the critical section for decomp deinit ******/
5929         {
5930             WORD32 i4_status;
5931             i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_decomp_deinit);
5932 
5933             if(OSAL_SUCCESS != i4_status)
5934                 return 0;
5935         }
5936 
5937         ps_multi_thrd->ai4_num_thrds_processed_decomp[i4_cur_decomp_idx]++;
5938         i4_decomp_end_flag = ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx];
5939 
5940         /* check for last thread condition */
5941         if(ps_multi_thrd->ai4_num_thrds_processed_decomp[i4_cur_decomp_idx] ==
5942            ps_multi_thrd->i4_num_pre_enc_proc_thrds)
5943         {
5944             ps_multi_thrd->ai4_num_thrds_processed_decomp[i4_cur_decomp_idx] = 0;
5945 
5946             /* reset the init flag so that init happens by the first thread for the next frame
5947                of same ping_pong instance */
5948             ps_multi_thrd->ai4_pre_enc_init_done[i4_cur_decomp_idx] = 0;
5949 
5950             /* update the pre enc l1 done in dep manager */
5951             ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_l1);
5952         }
5953 
5954         /* index increment */
5955         i4_cur_decomp_idx = i4_cur_decomp_idx + 1;
5956 
5957         /* wrap around case */
5958         if(i4_cur_decomp_idx >= ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe)
5959         {
5960             i4_cur_decomp_idx = 0;
5961         }
5962 
5963         /****** UnLock the critical section after decomp pre_intra deinit ******/
5964         {
5965             WORD32 i4_status;
5966             i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_pre_enc_decomp_deinit);
5967 
5968             if(OSAL_SUCCESS != i4_status)
5969                 return 0;
5970         }
5971 
5972         /* ------------------------------------------------------------ */
5973         /*                     HME Init                                 */
5974         /* ------------------------------------------------------------ */
5975 
5976         /* Wait till previous frame(instance)'s coarse_me is processed */
5977         {
5978             ihevce_dmgr_chk_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_coarse_me, i4_thrd_id);
5979         }
5980 
5981         /****** Lock the critical section for hme init ******/
5982         {
5983             WORD32 i4_status;
5984 
5985             i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_hme_init);
5986             if(OSAL_SUCCESS != i4_status)
5987                 return 0;
5988         }
5989 
5990         if(0 == ps_multi_thrd->ai4_pre_enc_hme_init_done[i4_cur_coarse_me_idx])
5991         {
5992             /* do the init processing if input frm data is valid */
5993             if(1 ==
5994                ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->i4_frm_proc_valid_flag)
5995             {
5996                 recon_pic_buf_t *ps_frm_recon = NULL;
5997 
5998                 /* DPB management for coarse me + HME init */
5999                 ihevce_pre_enc_coarse_me_init(
6000                     ps_enc_ctxt,
6001                     ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx],
6002                     ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx],
6003                     &ps_frm_recon,
6004                     ps_multi_thrd->ai4_decomp_lyr_buf_idx[i4_cur_coarse_me_idx],
6005                     ps_multi_thrd->ai4_cur_frame_qp_pre_enc[i4_cur_coarse_me_idx],
6006                     i4_cur_coarse_me_idx);
6007             }
6008 
6009             ps_multi_thrd->ai4_pre_enc_hme_init_done[i4_cur_coarse_me_idx] = 1;
6010         }
6011 
6012         /****** Unlock the critical section for hme init ******/
6013         {
6014             WORD32 i4_status;
6015 
6016             i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_pre_enc_hme_init);
6017             if(OSAL_SUCCESS != i4_status)
6018                 return 0;
6019         }
6020 
6021         /* ------------------------------------------------------------ */
6022         /*  Coarse Motion estimation and early intra-inter decision     */
6023         /* ------------------------------------------------------------ */
6024         if(1 == ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->i4_frm_proc_valid_flag)
6025         {
6026             ihevce_coarse_me_process(
6027                 ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
6028                 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx],
6029                 &ps_enc_ctxt->s_multi_thrd,
6030                 i4_thrd_id,
6031                 i4_cur_coarse_me_idx);
6032         }
6033 
6034         /* update the end flag */
6035         i4_end_flag = ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_coarse_me_idx];
6036         i4_out_flush_flag =
6037             ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx]->s_lap_out.i4_out_flush_flag;
6038 
6039         /****** Lock the critical section for hme deinit ******/
6040         {
6041             WORD32 i4_status;
6042             i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_hme_deinit);
6043 
6044             if(OSAL_SUCCESS != i4_status)
6045                 return 0;
6046         }
6047 
6048         /* last thread finishing pre_enc_process will update the flag indicating
6049         decomp and coarse ME is done. So that the next frame (next ping_pong instance)
6050         can start immediately after finishing current frame's IPE */
6051         if(1 == ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->i4_frm_proc_valid_flag)
6052         {
6053             ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx]++;
6054 
6055             /* ------------------------------------------------------------ */
6056             /*  Update qp used in based in L1 satd/act in case of scene cut */
6057             /* ------------------------------------------------------------ */
6058             {
6059                 ihevce_lap_enc_buf_t *ps_curr_inp =
6060                     ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx];
6061 
6062                 if(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag)
6063                 {
6064                     WORD32 i4_prev_coarse_me_idx;
6065 
6066                     /* wrap around case */
6067                     if(i4_cur_coarse_me_idx == 0)
6068                     {
6069                         i4_prev_coarse_me_idx = ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe - 1;
6070                     }
6071                     else
6072                     {
6073                         i4_prev_coarse_me_idx = i4_cur_coarse_me_idx - 1;
6074                     }
6075 
6076                     ihevce_update_qp_L1_sad_based(
6077                         ps_enc_ctxt,
6078                         ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx],
6079                         ps_multi_thrd->aps_curr_inp_pre_enc[i4_prev_coarse_me_idx],
6080                         ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx],
6081                         ((ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx] ==
6082                           ps_multi_thrd->i4_num_pre_enc_proc_thrds)));
6083                 }
6084             }
6085             /* check for last thread condition */
6086             if(ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx] ==
6087                ps_multi_thrd->i4_num_pre_enc_proc_thrds)
6088             {
6089                 ihevce_lap_enc_buf_t *ps_curr_inp =
6090                     ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx];
6091 
6092                 /*        Frame END processing                  */
6093                 ihevce_coarse_me_frame_end(ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt);
6094 
6095                 if(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag)
6096                 {
6097                     WORD32 i4_enable_noise_detection = 0;
6098                     WORD32 i4_vqet = ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_vqet;
6099 
6100                     if(i4_vqet & (1 << BITPOS_IN_VQ_TOGGLE_FOR_CONTROL_TOGGLER))
6101                     {
6102                         if(i4_vqet & (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_NOISE_PRESERVATION))
6103                         {
6104                             i4_enable_noise_detection = 1;
6105                         }
6106                     }
6107 
6108                     if(1 != ((ps_curr_inp->s_lap_out.i4_pic_type == IV_B_FRAME) &&
6109                              (ps_enc_ctxt->s_lap_stat_prms.ai4_quality_preset[i4_resolution_id] ==
6110                               IHEVCE_QUALITY_P6)))
6111                     {
6112                         ihevce_decomp_pre_intra_curr_frame_pre_intra_deinit(
6113                             ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt,
6114                             ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx],
6115                             &ps_enc_ctxt->s_frm_ctb_prms);
6116                     }
6117                 }
6118 
6119                 ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_coarse_me_idx] = 1;
6120 
6121                 ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx] = 0;
6122 
6123                 /* get the layer 1 ctxt to be passed on to encode group */
6124                 ihevce_coarse_me_get_lyr1_ctxt(
6125                     ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
6126                     ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->pv_me_lyr_ctxt,
6127                     ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->pv_me_lyr_bnk_ctxt);
6128 
6129                 /* reset the init flag so that init happens by the first thread for the next frame
6130                     of same ping_pong instance */
6131                 ps_multi_thrd->ai4_pre_enc_hme_init_done[i4_cur_coarse_me_idx] = 0;
6132 
6133                 /* update the pre enc l1 done in dep manager */
6134                 ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_coarse_me);
6135             }
6136 
6137             i4_num_buf_prod_for_l0_ipe++;
6138 
6139             /* index increment */
6140             i4_cur_coarse_me_idx = i4_cur_coarse_me_idx + 1;
6141 
6142             /* wrap around case */
6143             if(i4_cur_coarse_me_idx >= ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe)
6144             {
6145                 i4_cur_coarse_me_idx = 0;
6146             }
6147         }
6148         else
6149         {
6150             /* for invalid frame set the processed flag to 1 for L0 IPE */
6151             ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_coarse_me_idx] = 1;
6152 
6153             if(1 == i4_out_flush_flag)
6154             {
6155                 /* update the num thrds who have finished pre-enc processing */
6156                 ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx]++;
6157 
6158                 if(ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx] ==
6159                    ps_multi_thrd->i4_num_pre_enc_proc_thrds)
6160                 {
6161                     ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_coarse_me_idx] = 1;
6162 
6163                     /* reset num thread finished counter */
6164                     ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx] = 0;
6165 
6166                     ps_multi_thrd->ai4_pre_enc_hme_init_done[i4_cur_coarse_me_idx] = 0;
6167 
6168                     /* update flag indicating coarse_me and decomp is done */
6169                     ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_coarse_me);
6170                 }
6171             }
6172 
6173             i4_num_buf_prod_for_l0_ipe++;
6174 
6175             /* index increment */
6176             i4_cur_coarse_me_idx = i4_cur_coarse_me_idx + 1;
6177 
6178             /* wrap around case */
6179             if(i4_cur_coarse_me_idx >= ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe)
6180             {
6181                 i4_cur_coarse_me_idx = 0;
6182             }
6183         }
6184 
6185         /****** UnLock the critical section after hme deinit ******/
6186         {
6187             WORD32 i4_status;
6188             i4_status =
6189                 osal_mutex_unlock(ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_hme_deinit);
6190 
6191             if(OSAL_SUCCESS != i4_status)
6192                 return 0;
6193         }
6194 
6195         if(i4_thrd_id == 0)
6196         {
6197             PROFILE_STOP(&ps_hle_ctxt->profile_pre_enc_l1l2[i4_resolution_id], NULL);
6198         }
6199 
6200         /* ----------------------------------------------------------- */
6201         /*     IPE init and process                                    */
6202         /* ----------------------------------------------------------- */
6203         if(i4_thrd_id == 0)
6204         {
6205             PROFILE_START(&ps_hle_ctxt->profile_pre_enc_l0ipe[i4_resolution_id]);
6206         }
6207         if(i4_num_buf_prod_for_l0_ipe >= ps_multi_thrd->i4_delay_pre_me_btw_l0_ipe || i4_end_flag ||
6208            i4_out_flush_flag)
6209         {
6210             do
6211             {
6212                 /* Wait till previous frame(instance)'s IPE is processed */
6213                 {
6214                     ihevce_dmgr_chk_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_l0, i4_thrd_id);
6215                 }
6216 
6217                 /* Wait till current frame(instance)'s L1 and below layers are processed */
6218                 {
6219                     volatile WORD32 *pi4_cur_l1_complete =
6220                         &ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_ipe_idx];
6221 
6222                     while(1)
6223                     {
6224                         if(*pi4_cur_l1_complete)
6225                             break;
6226                     }
6227                 }
6228 
6229                 /* ----------------------------------------------------------- */
6230                 /*     L0 IPE qp init                                          */
6231                 /* ----------------------------------------------------------- */
6232 
6233                 /****** Lock the critical section for init ******/
6234                 {
6235                     WORD32 i4_status;
6236                     i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_l0_ipe_init);
6237 
6238                     if(OSAL_SUCCESS != i4_status)
6239                         return 0;
6240                 }
6241 
6242                 /* first thread that enters will calculate qp and write that to shared variable
6243                    that will be accessed by other threads */
6244                 if(ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx] == 0)
6245                 {
6246                     volatile WORD32 i4_is_qp_valid = -1;
6247                     WORD32 i4_update_qp;
6248                     WORD32 i4_cur_q_scale;
6249 
6250                     i4_cur_q_scale =
6251                         ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->i4_curr_frm_qp;
6252                     i4_cur_q_scale = ps_enc_ctxt->s_rc_quant.pi4_qp_to_qscale[i4_cur_q_scale];
6253                     i4_cur_q_scale = (i4_cur_q_scale + (1 << (QSCALE_Q_FAC_3 - 1))) >>
6254                                      QSCALE_Q_FAC_3;
6255                     /* Get free buffer to store L0 IPE output to enc loop */
6256                     ps_multi_thrd->ps_L0_IPE_curr_out_pre_enc =
6257                         (pre_enc_L0_ipe_encloop_ctxt_t *)ihevce_q_get_free_buff(
6258                             (void *)ps_enc_ctxt,
6259                             IHEVCE_L0_IPE_ENC_Q,
6260                             &ps_multi_thrd->i4_L0_IPE_out_buf_id,
6261                             BUFF_QUE_BLOCKING_MODE);
6262                     if(ps_enc_ctxt->ps_stat_prms->s_pass_prms.i4_pass != 2 &&
6263                        ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode != 3)
6264                     {
6265                         complexity_RC_reset_marking(
6266                             ps_enc_ctxt, i4_cur_ipe_idx, (i4_end_flag || i4_out_flush_flag));
6267                     }
6268                     if(1 == ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6269                                 ->s_input_buf.i4_inp_frm_data_valid_flag)
6270                     {
6271                         while(i4_is_qp_valid == -1)
6272                         {
6273                             /*this rate control call is outside mutex lock to avoid deadlock. If this acquires mutex lock enc will not be able to
6274                             populate qp*/
6275                             i4_is_qp_valid = ihevce_rc_check_is_pre_enc_qp_valid(
6276                                 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6277                                 (volatile WORD32 *)&ps_enc_ctxt->s_multi_thrd.i4_force_end_flag);
6278                             if(1 == ps_enc_ctxt->s_multi_thrd.i4_force_end_flag)
6279                             {
6280                                 /*** For force end condition break from this loop ***/
6281                                 i4_is_qp_valid = 1;
6282                                 break;
6283                             }
6284                         }
6285 
6286                         /*lock rate control context*/
6287                         osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
6288 
6289                         /* Qp query has to happen irrespective of using it or not since producer consumer logic will be disturbed */
6290                         i4_update_qp = ihevce_rc_pre_enc_qp_query(
6291                             (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6292                             &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_rc_lap_out,
6293                             0);
6294 
6295                         if(ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode != 3)
6296                         {
6297                             ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6298                                 ->s_rc_lap_out.i8_frm_satd_act_accum_L0_frm_L1 =
6299                                 ihevce_get_L0_satd_based_on_L1(
6300                                     ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6301                                         ->s_rc_lap_out.i8_frame_satd_by_act_L1_accum,
6302                                     ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6303                                         ->s_rc_lap_out.i4_num_pels_in_frame_considered,
6304                                     i4_cur_q_scale);
6305 
6306                             if(ps_enc_ctxt->ps_stat_prms->s_pass_prms.i4_pass != 2)
6307                             {
6308                                 if(ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6309                                            ->s_rc_lap_out.i4_rc_scene_type ==
6310                                        SCENE_TYPE_SCENE_CUT ||
6311                                    ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6312                                        ->s_rc_lap_out.i4_is_I_only_scd ||
6313                                    ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6314                                            ->s_rc_lap_out.i4_is_non_I_scd == 1)
6315                                 {
6316                                     float i_to_avg_rest_ratio;
6317                                     WORD32 i4_count = 0;
6318 
6319                                     while(1)
6320                                     {
6321                                         i_to_avg_rest_ratio = ihevce_get_i_to_avg_ratio(
6322                                             ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6323                                             &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6324                                                  ->s_rc_lap_out,
6325                                             1,
6326                                             0,
6327                                             0,
6328                                             ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6329                                                 ->s_rc_lap_out.ai4_offsets,
6330                                             0);
6331                                         /* HEVC_RC query rate control for qp */
6332                                         i4_update_qp = ihevce_get_L0_est_satd_based_scd_qp(
6333                                             ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6334                                             &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6335                                                  ->s_rc_lap_out,
6336                                             ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6337                                                 ->s_rc_lap_out.i8_frm_satd_act_accum_L0_frm_L1,
6338                                             i_to_avg_rest_ratio);
6339 
6340                                         ihevce_set_L0_scd_qp(
6341                                             ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6342                                             i4_update_qp);
6343 
6344                                         if(ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6345                                                    ->s_lap_out.i4_pic_type != IV_IDR_FRAME &&
6346                                            ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6347                                                    ->s_lap_out.i4_pic_type != IV_I_FRAME)
6348                                         {
6349                                             i4_update_qp +=
6350                                                 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6351                                                     ->s_lap_out.i4_temporal_lyr_id +
6352                                                 1;
6353 
6354                                             i4_update_qp =
6355                                                 CLIP3(i4_update_qp, MIN_HEVC_QP, MAX_HEVC_QP);
6356                                         }
6357 
6358                                         i4_count++;
6359                                         if((i4_update_qp ==
6360                                             ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6361                                                 ->s_rc_lap_out.i4_L0_qp) ||
6362                                            i4_count > 4)
6363                                             break;
6364 
6365                                         ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6366                                             ->s_rc_lap_out.i4_L0_qp = i4_update_qp;
6367                                     }
6368                                 }
6369                             }
6370                             else
6371                             {
6372                                 //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);
6373                                 i4_update_qp = ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6374                                                    ->s_rc_lap_out.ps_frame_info->i4_rc_hevc_qp;
6375                             }
6376                         }
6377 
6378                         {
6379                             WORD32 i4_index = 0;
6380                             rc_lap_out_params_t *ps_rc_lap_temp =
6381                                 &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_rc_lap_out;
6382                             WORD32 i4_offset;
6383 
6384                             if(ps_rc_lap_temp->i4_rc_pic_type != IV_IDR_FRAME &&
6385                                ps_rc_lap_temp->i4_rc_pic_type != IV_I_FRAME)
6386                             {
6387                                 i4_index = ps_rc_lap_temp->i4_rc_temporal_lyr_id + 1;
6388                             }
6389                             i4_offset = ps_rc_lap_temp->ai4_offsets[i4_index];
6390                             ASSERT(i4_offset >= 0);
6391                             /* Map the current frame Qp to L0 Qp */
6392                             ps_rc_lap_temp->i4_L0_qp = i4_update_qp - i4_offset;
6393                         }
6394                         osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
6395                         ASSERT(ps_multi_thrd->i4_qp_update_l0_ipe == -1);
6396                         ps_multi_thrd->i4_qp_update_l0_ipe = i4_update_qp;
6397                         ps_multi_thrd->i4_rc_l0_qp = i4_update_qp;
6398                     }
6399                     ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6400                         ->s_lap_out.f_i_pic_lamda_modifier = CONST_LAMDA_MOD_VAL;
6401                 }
6402                 /* update qp only if it is not scene cut since it has already been
6403                    populated in L1 for scene cut frames */
6404                 if(1 == ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6405                             ->s_input_buf.i4_inp_frm_data_valid_flag &&
6406                    ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode != 3)
6407                 {
6408                     /*get relevant lambda params*/
6409                     ihevce_get_frame_lambda_prms(
6410                         ps_enc_ctxt,
6411                         ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx],
6412                         ps_multi_thrd->i4_qp_update_l0_ipe,
6413                         ps_enc_ctxt->s_runtime_src_prms.i4_field_pic,
6414                         ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_lap_out.i4_is_ref_pic,
6415                         ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6416                             ->s_lap_out.i4_temporal_lyr_id,
6417                         ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6418                             ->s_lap_out.f_i_pic_lamda_modifier,
6419                         0,
6420                         PRE_ENC_LAMBDA_TYPE);
6421 
6422                     ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->i4_curr_frm_qp =
6423                         ps_multi_thrd->i4_qp_update_l0_ipe;
6424                 }
6425                 /* Compute accumulated activity and strength */
6426                 if(1 == ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6427                             ->s_input_buf.i4_inp_frm_data_valid_flag &&
6428                    ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx] == 0)
6429                 {
6430                     ihevce_variance_calc_acc_activity(ps_enc_ctxt, i4_cur_ipe_idx);
6431                 }
6432 
6433                 /* Mark qp as read by last thread */
6434                 ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx]++;
6435                 if(ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx] ==
6436                    ps_multi_thrd->i4_num_pre_enc_proc_thrds)
6437                 {
6438                     ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx] = 0;
6439                     ps_multi_thrd->i4_qp_update_l0_ipe = -1;
6440                 }
6441 
6442                 /****** UnLock the critical section after deinit ******/
6443                 {
6444                     WORD32 i4_status;
6445                     i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_l0_ipe_init);
6446 
6447                     if(OSAL_SUCCESS != i4_status)
6448                         return 0;
6449                 }
6450 
6451                 if(1 == ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6452                             ->s_input_buf.i4_inp_frm_data_valid_flag)
6453                 {
6454                     WORD32 i4_slice_type =
6455                         (WORD32)ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]
6456                             ->s_slice_hdr.i1_slice_type;
6457                     WORD32 i4_quality_preset =
6458                         (WORD32)ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6459                             ->s_lap_out.i4_quality_preset;
6460                     WORD32 i4_temporal_layer_id =
6461                         (WORD32)ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6462                             ->s_lap_out.i4_temporal_lyr_id;
6463 #if DISABLE_L0_IPE_INTRA_IN_BPICS
6464                     if(1 != ((i4_quality_preset == IHEVCE_QUALITY_P6) &&
6465                              (i4_temporal_layer_id > TEMPORAL_LAYER_DISABLE)))
6466 #endif
6467                     {
6468                         UWORD8 i1_cu_qp_delta_enabled_flag =
6469                             ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_cu_level_rc;
6470 
6471                         ihevce_populate_ipe_frame_init(
6472                             ps_enc_ctxt->s_module_ctxt.pv_ipe_ctxt,
6473                             ps_enc_ctxt->ps_stat_prms,
6474                             ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->i4_curr_frm_qp,
6475                             i4_slice_type,
6476                             i4_thrd_id,
6477                             ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx],
6478                             i1_cu_qp_delta_enabled_flag,
6479                             &ps_enc_ctxt->s_rc_quant,
6480                             i4_quality_preset,
6481                             i4_temporal_layer_id,
6482                             &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_lap_out);
6483 
6484                         ihevce_ipe_process(
6485                             ps_enc_ctxt->s_module_ctxt.pv_ipe_ctxt,
6486                             &ps_enc_ctxt->s_frm_ctb_prms,
6487                             &ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->as_lambda_prms[0],
6488                             ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx],
6489                             ps_multi_thrd->ps_L0_IPE_curr_out_pre_enc,
6490                             ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->ps_ctb_analyse,
6491                             ps_multi_thrd->ps_L0_IPE_curr_out_pre_enc->ps_ipe_analyse_ctb,
6492                             &ps_enc_ctxt->s_multi_thrd,
6493                             i4_slice_type,
6494                             ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->ps_layer1_buf,
6495                             ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->ps_layer2_buf,
6496                             ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->ps_ed_ctb_l1,
6497                             i4_thrd_id,
6498                             i4_cur_ipe_idx);
6499                     }
6500                 }
6501 
6502                 /* ----------------------------------------------------------- */
6503                 /*     pre-enc de-init                                         */
6504                 /* ----------------------------------------------------------- */
6505 
6506                 /****** Lock the critical section for deinit ******/
6507                 {
6508                     WORD32 i4_status;
6509                     i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_deinit);
6510 
6511                     if(OSAL_SUCCESS != i4_status)
6512                         return 0;
6513                 }
6514 
6515                 ps_multi_thrd->ai4_num_thrds_processed_pre_enc[i4_cur_ipe_idx]++;
6516                 if(ps_multi_thrd->ai4_num_thrds_processed_pre_enc[i4_cur_ipe_idx] ==
6517                    ps_multi_thrd->i4_num_pre_enc_proc_thrds)
6518                 {
6519                     ps_multi_thrd->ai4_pre_enc_deinit_done[i4_cur_ipe_idx] = 0;
6520                     ps_multi_thrd->ai4_num_thrds_processed_pre_enc[i4_cur_ipe_idx] = 0;
6521 
6522                     /* reset the init flag so that init happens by the first thread for the
6523                        next frame of same ping_pnog instnace */
6524                     ps_multi_thrd->ai4_pre_enc_init_done[i4_cur_ipe_idx] = 0;
6525                 }
6526 
6527                 /* de-init */
6528                 if(0 == ps_multi_thrd->ai4_pre_enc_deinit_done[i4_cur_ipe_idx])
6529                 {
6530                     ihevce_lap_enc_buf_t *ps_curr_inp =
6531                         ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx];
6532                     pre_enc_me_ctxt_t *ps_curr_out =
6533                         ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx];
6534 
6535                     /* set the flag saying de init is done so that other cores dont do it */
6536                     ps_multi_thrd->ai4_pre_enc_deinit_done[i4_cur_ipe_idx] = 1;
6537 
6538                     if(1 == ps_curr_out->i4_frm_proc_valid_flag)
6539                     {
6540                         LWORD64 frame_acc_satd_by_modqp;
6541                         float L1_full_processed_ratio;
6542 
6543                         if(ps_curr_inp->s_rc_lap_out.i8_satd_by_act_L1_accum_evaluated)
6544                         {
6545                             L1_full_processed_ratio =
6546                                 ((float)ps_curr_inp->s_rc_lap_out.i8_frame_satd_by_act_L1_accum /
6547                                  ps_curr_inp->s_rc_lap_out.i8_satd_by_act_L1_accum_evaluated);
6548                         }
6549                         else
6550                         {
6551                             L1_full_processed_ratio = 1.0;
6552                         }
6553                         /* Get frame-level satd cost and mode bit cost from IPE */
6554                         ps_curr_out->i8_frame_acc_satd_cost = ihevce_ipe_get_frame_intra_satd_cost(
6555                             ps_enc_ctxt->s_module_ctxt.pv_ipe_ctxt,
6556                             &frame_acc_satd_by_modqp,
6557                             &ps_curr_inp->s_rc_lap_out.i8_est_I_pic_header_bits,
6558                             &ps_curr_inp->s_lap_out.i8_frame_level_activity_fact,
6559                             &ps_curr_inp->s_lap_out.i8_frame_l0_acc_satd);
6560 
6561                         if((ps_curr_inp->s_lap_out.i4_quality_preset == IHEVCE_QUALITY_P6) &&
6562                            (ps_curr_inp->s_lap_out.i4_temporal_lyr_id > TEMPORAL_LAYER_DISABLE))
6563                         {
6564                             ps_curr_inp->s_rc_lap_out.i8_est_I_pic_header_bits = -1;
6565                         }
6566 
6567                         {
6568                             WORD32 i4_cur_q_scale = (ps_enc_ctxt->s_rc_quant.pi4_qp_to_qscale
6569                                                          [ps_enc_ctxt->s_multi_thrd.i4_rc_l0_qp +
6570                                                           ps_enc_ctxt->s_rc_quant.i1_qp_offset] +
6571                                                      (1 << (QSCALE_Q_FAC_3 - 1))) >>
6572                                                     QSCALE_Q_FAC_3;
6573 
6574                             /* calculate satd/act_fac = satd/qm * (qp_used_at_L0_analysis) */
6575                             ps_curr_inp->s_rc_lap_out.i8_frame_satd_act_accum =
6576                                 frame_acc_satd_by_modqp * i4_cur_q_scale;
6577                         }
6578 
6579                         /* Because of early intra inter decision, L0 intra analysis might not happen for entire frame, correct the error
6580                            based on L1 data */
6581                         ps_curr_inp->s_rc_lap_out.i8_est_I_pic_header_bits = (LWORD64)(
6582                             ps_curr_inp->s_rc_lap_out.i8_est_I_pic_header_bits *
6583                             L1_full_processed_ratio);
6584 
6585                         if(L1_full_processed_ratio < 1.5)
6586                         {
6587                             ps_curr_inp->s_rc_lap_out.i8_frame_satd_act_accum = (LWORD64)(
6588                                 ps_curr_inp->s_rc_lap_out.i8_frame_satd_act_accum *
6589                                 L1_full_processed_ratio);
6590                         }
6591                         else
6592                         {
6593                             /* This is the case when too many candidates would not have gone through intra analysis, scaling based on L1 is found to be inappropriate,
6594                             Hence directly estimating L0 satd from L1 satd */
6595                             ps_curr_inp->s_rc_lap_out.i8_frame_satd_act_accum =
6596                                 ps_curr_inp->s_rc_lap_out.i8_frm_satd_act_accum_L0_frm_L1;
6597                         }
6598                     }
6599 
6600                     /* register the current input buffer to be cnosumed by encode group threads */
6601                     ps_curr_out->curr_inp_buf_id =
6602                         ps_multi_thrd->ai4_in_buf_id_pre_enc[i4_cur_ipe_idx];
6603                     ps_curr_out->ps_curr_inp = ps_curr_inp;
6604 
6605                     /* set the output buffer as produced */
6606                     ihevce_q_set_buff_prod(
6607                         (void *)ps_enc_ctxt,
6608                         IHEVCE_PRE_ENC_ME_Q,
6609                         ps_multi_thrd->ai4_out_buf_id_pre_enc[i4_cur_ipe_idx]);
6610 
6611                     /* set the output buffer of L0 IPE as produced */
6612                     ihevce_q_set_buff_prod(
6613                         (void *)ps_enc_ctxt,
6614                         IHEVCE_L0_IPE_ENC_Q,
6615                         ps_multi_thrd->i4_L0_IPE_out_buf_id);
6616 
6617                     /* update flag indicating ipe is done */
6618                     ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_l0);
6619                 }
6620 
6621                 {
6622                     /* index increment */
6623                     i4_cur_ipe_idx = i4_cur_ipe_idx + 1;
6624 
6625                     /* wrap around case */
6626                     if(i4_cur_ipe_idx >= ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe)
6627                     {
6628                         i4_cur_ipe_idx = 0;
6629                     }
6630 
6631                     i4_num_buf_prod_for_l0_ipe--;
6632                 }
6633                 /*NOTE: update of above indices should mark end if ipe.do not access below this*/
6634 
6635                 /****** UnLock the critical section after deinit ******/
6636                 {
6637                     WORD32 i4_status;
6638                     i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_pre_enc_deinit);
6639 
6640                     if(OSAL_SUCCESS != i4_status)
6641                         return 0;
6642                 }
6643 
6644                 if(1 == ps_multi_thrd->i4_force_end_flag)
6645                 {
6646                     i4_end_flag = 1;
6647                     break;
6648                 }
6649             } while((i4_end_flag || i4_out_flush_flag) && i4_num_buf_prod_for_l0_ipe);
6650         }
6651         if(i4_thrd_id == 0)
6652         {
6653             PROFILE_STOP(&ps_hle_ctxt->profile_pre_enc_l0ipe[i4_resolution_id], NULL);
6654         }
6655     }
6656 
6657     return 0;
6658 }
6659 
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)6660 void calc_l1_level_hme_intra_sad_different_qp(
6661     enc_ctxt_t *ps_enc_ctxt,
6662     pre_enc_me_ctxt_t *ps_curr_out,
6663     ihevce_lap_enc_buf_t *ps_curr_inp,
6664     WORD32 i4_tot_ctb_l1_x,
6665     WORD32 i4_tot_ctb_l1_y)
6666 {
6667     ihevce_ed_ctb_l1_t *ps_ed_ctb_l1;
6668     WORD32 i4_qp_counter, i4_qp_start = 0, i4_qp_end = 0, i, i4_j, i4_new_frame_qp;
6669     LWORD64 i8_l1_intra_sad_nc_accounted = 0, cur_intra_sad, raw_hme_sad = 0;
6670     LWORD64 cur_hme_sad = 0, cur_hme_sad_for_offset = 0, acc_hme_l1_sad = 0,
6671             acc_hme_l1_sad_for_offset = 0;
6672     i4_qp_start = 1;
6673     i4_qp_end = 51;
6674 
6675     for(i4_qp_counter = i4_qp_start; i4_qp_counter <= i4_qp_end; i4_qp_counter = i4_qp_counter + 3)
6676     {
6677         i8_l1_intra_sad_nc_accounted = 0;
6678         cur_intra_sad = 0;
6679         raw_hme_sad = 0;
6680         cur_hme_sad = 0;
6681         cur_hme_sad_for_offset = 0;
6682         acc_hme_l1_sad = 0;
6683         ps_ed_ctb_l1 = ps_curr_out->ps_ed_ctb_l1;
6684         i4_new_frame_qp = i4_qp_counter;
6685         acc_hme_l1_sad = 0;
6686 
6687         for(i = 0; i < (i4_tot_ctb_l1_x * i4_tot_ctb_l1_y); i += 1)
6688         {
6689             for(i4_j = 0; i4_j < 16; i4_j++)
6690             {
6691                 if(ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j] != -1)
6692                 {
6693                     ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j] >= 0);
6694                     if(ps_curr_inp->s_rc_lap_out.i4_rc_pic_type != IV_I_FRAME &&
6695                        ps_curr_inp->s_rc_lap_out.i4_rc_pic_type != IV_IDR_FRAME)
6696                     {
6697                         /*When l1 is disabled for B pics i4_best_sad_8x8_l1_ipe is set to max value always,
6698                         so will enter this path even for incomplete ctb, hence the assert holdsto good only for P pic  */
6699                         if(ps_curr_inp->s_rc_lap_out.i4_rc_quality_preset == IHEVCE_QUALITY_P6)
6700                         {
6701                             if(ps_curr_inp->s_rc_lap_out.i4_rc_pic_type == IV_P_FRAME)
6702                             {
6703                                 ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j] >= 0);
6704                                 ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_me_for_decide[i4_j] >= 0);
6705                             }
6706                         }
6707                         else
6708                         {
6709                             ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j] >= 0);
6710                             ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_me_for_decide[i4_j] >= 0);
6711                         }
6712 
6713 #if 1  //DISABLE_L1_L2_IPE_INTRA_IN_BPICS && RC_DEPENDENCY_FOR_BPIC
6714                         if((ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j] != -1))
6715 #endif
6716                         {
6717                             cur_hme_sad = ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j] -
6718                                           (QP2QUANT_MD[i4_new_frame_qp] << 3);
6719                         }
6720                         raw_hme_sad += ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j];
6721 
6722                         if(cur_hme_sad > 0)
6723                             acc_hme_l1_sad += cur_hme_sad;
6724                     }
6725                     if(cur_hme_sad_for_offset > 0)
6726                     {
6727                         acc_hme_l1_sad_for_offset += cur_hme_sad_for_offset;
6728                     }
6729                     ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j] >= 0);
6730                     /*intra sad is scaled by 1.17 to be account for 1/3 vs 1/6th rounding*/
6731                     cur_intra_sad = (LWORD64)(
6732                         (ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j] * 1.17) -
6733                         (QP2QUANT_MD[i4_new_frame_qp] << 3));
6734 
6735                     if(cur_intra_sad > 0)
6736                         i8_l1_intra_sad_nc_accounted += cur_intra_sad;
6737                 }
6738             }
6739             ps_ed_ctb_l1 += 1;
6740         }
6741         if((ps_curr_inp->s_rc_lap_out.i4_rc_quality_preset == IHEVCE_QUALITY_P6) &&
6742            (ps_curr_inp->s_rc_lap_out.i4_rc_pic_type == IV_B_FRAME))
6743         {
6744             ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter] = -1;
6745             ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter + 1] = -1;
6746             ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter + 2] = -1;
6747         }
6748         else
6749         {
6750             ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter] =
6751                 i8_l1_intra_sad_nc_accounted;
6752             ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter + 1] =
6753                 i8_l1_intra_sad_nc_accounted;
6754             ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter + 2] =
6755                 i8_l1_intra_sad_nc_accounted;
6756         }
6757         ps_curr_inp->s_rc_lap_out.ai8_frame_acc_coarse_me_sad[i4_qp_counter] = acc_hme_l1_sad;
6758         ps_curr_inp->s_rc_lap_out.ai8_frame_acc_coarse_me_sad[i4_qp_counter + 1] = acc_hme_l1_sad;
6759         ps_curr_inp->s_rc_lap_out.ai8_frame_acc_coarse_me_sad[i4_qp_counter + 2] = acc_hme_l1_sad;
6760         ps_curr_inp->s_rc_lap_out.i8_raw_l1_coarse_me_sad = raw_hme_sad;
6761     }
6762 }
6763