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