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 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 }
4962 }
4963
4964 osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4965 /* run the loop over all bit-rate instnaces */
4966 for(i = 0; i < i4_num_instance; i++)
4967 {
4968 /*HEVC_RC Do one time initialization of rate control*/
4969 ihevce_rc_init(
4970 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
4971 &ps_enc_ctxt->s_runtime_src_prms,
4972 &ps_enc_ctxt->s_runtime_tgt_params,
4973 &ps_enc_ctxt->s_rc_quant,
4974 &ps_enc_ctxt->ps_stat_prms->s_sys_api,
4975 &ps_enc_ctxt->ps_stat_prms->s_lap_prms,
4976 ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc);
4977
4978 ihevce_vbv_complaince_init_level(
4979 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
4980 &ps_enc_ctxt->as_sps[i].s_vui_parameters);
4981 }
4982 osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4983 }
4984
4985 /*!
4986 ******************************************************************************
4987 * \if Function name : ihevce_pre_enc_init \endif
4988 *
4989 * \brief
4990 * set out_buf params
4991 * Calculate end_flag if flushmode on
4992 * Slice initialization
4993 * Populate SIE params
4994 * reference list creation
4995 *
4996 * \param[in] Encoder context pointer
4997 *
4998 * \return
4999 * None
5000 *
5001 * \author
5002 * Ittiam
5003 *
5004 *****************************************************************************
5005 */
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)5006 void ihevce_pre_enc_init(
5007 enc_ctxt_t *ps_enc_ctxt,
5008 ihevce_lap_enc_buf_t *ps_curr_inp,
5009 pre_enc_me_ctxt_t *ps_curr_out,
5010 WORD32 *pi4_end_flag_ret,
5011 WORD32 *pi4_cur_qp_ret,
5012 WORD32 *pi4_decomp_lyr_idx,
5013 WORD32 i4_ping_pong)
5014 {
5015 WORD32 end_flag = 0;
5016 WORD32 cur_qp;
5017 //recon_pic_buf_t *ps_frm_recon;
5018 WORD32 first_field = 1;
5019 WORD32 i4_field_pic = ps_enc_ctxt->s_runtime_src_prms.i4_field_pic;
5020 WORD32 i4_decomp_lyrs_idx = 0;
5021 WORD32 i4_resolution_id = ps_enc_ctxt->i4_resolution_id;
5022 WORD32 slice_type = ISLICE;
5023 WORD32 nal_type;
5024 WORD32 min_cu_size;
5025
5026 WORD32 stasino_enabled;
5027
5028 /* copy the time stamps from inp to entropy inp */
5029 ps_curr_out->i4_inp_timestamp_low = ps_curr_inp->s_input_buf.i4_inp_timestamp_low;
5030 ps_curr_out->i4_inp_timestamp_high = ps_curr_inp->s_input_buf.i4_inp_timestamp_high;
5031 ps_curr_out->pv_app_frm_ctxt = ps_curr_inp->s_input_buf.pv_app_frm_ctxt;
5032
5033 /* get the min cu size from config params */
5034 min_cu_size = ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_min_log2_cu_size;
5035
5036 min_cu_size = 1 << min_cu_size;
5037
5038 ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd =
5039 ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd +
5040 SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd, min_cu_size);
5041
5042 ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht =
5043 ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht +
5044 SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht, min_cu_size);
5045
5046 ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd =
5047 ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd +
5048 SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd, min_cu_size);
5049
5050 if(IV_YUV_420SP_UV == ps_enc_ctxt->ps_stat_prms->s_src_prms.i4_chr_format)
5051 {
5052 ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht =
5053 ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht +
5054 SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht, (min_cu_size >> 1));
5055 }
5056 else if(IV_YUV_422SP_UV == ps_enc_ctxt->ps_stat_prms->s_src_prms.i4_chr_format)
5057 {
5058 ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht =
5059 ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht +
5060 SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht, min_cu_size);
5061 }
5062
5063 /* update the END flag from LAP out */
5064 end_flag = ps_curr_inp->s_lap_out.i4_end_flag;
5065 ps_curr_out->i4_end_flag = end_flag;
5066 ps_enc_ctxt->s_multi_thrd.i4_last_pic_flag = end_flag;
5067
5068 /* ----------------------------------------------------------------------*/
5069 /* Slice initialization for current frame; Required for entropy context */
5070 /* ----------------------------------------------------------------------*/
5071 {
5072 WORD32 cur_poc = ps_curr_inp->s_lap_out.i4_poc;
5073
5074 /* max merge candidates derived based on quality preset for now */
5075 WORD32 max_merge_candidates = 2;
5076
5077 /* pocs less than random acess poc tagged for discard as they */
5078 /* could be refering to pics before the cra. */
5079
5080 /* CRA case: as the leading pictures can refer the picture precedes the associated
5081 IRAP(CRA) in decoding order, hence make it Random access skipped leading pictures (RASL)*/
5082
5083 if((1 == ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.i4_enable_temporal_scalability) &&
5084 (ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_max_temporal_layers ==
5085 ps_curr_inp->s_lap_out.i4_temporal_lyr_id)) //TEMPORALA_SCALABILITY CHANGES
5086 {
5087 if(ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5088 {
5089 nal_type = (cur_poc < ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5090 ? (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_RASL_R : NAL_RASL_N)
5091 : (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_TSA_R : NAL_TSA_N);
5092 }
5093 /* IDR case: as the leading pictures can't refer the picture precedes the associated
5094 IRAP(IDR) in decoding order, hence make it Random access decodable leading pictures (RADL)*/
5095 else
5096 {
5097 nal_type = (cur_poc < ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5098 ? (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_RADL_R : NAL_RADL_N)
5099 : (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_TSA_R : NAL_TSA_N);
5100 }
5101 }
5102 else
5103 {
5104 if(ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5105 {
5106 nal_type = (cur_poc < ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5107 ? (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_RASL_R : NAL_RASL_N)
5108 : (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_TRAIL_R : NAL_TRAIL_N);
5109 }
5110 /* IDR case: as the leading pictures can't refer the picture precedes the associated
5111 IRAP(IDR) in decoding order, hence make it Random access decodable leading pictures (RADL)*/
5112 else
5113 {
5114 nal_type = (cur_poc < ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5115 ? (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_RADL_R : NAL_RADL_N)
5116 : (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_TRAIL_R : NAL_TRAIL_N);
5117 }
5118 }
5119
5120 switch(ps_curr_inp->s_lap_out.i4_pic_type)
5121 {
5122 case IV_IDR_FRAME:
5123 /* IDR pic */
5124 slice_type = ISLICE;
5125 nal_type = NAL_IDR_W_LP;
5126 cur_poc = 0;
5127 ps_enc_ctxt->i4_cra_poc = cur_poc;
5128 break;
5129
5130 case IV_I_FRAME:
5131 slice_type = ISLICE;
5132
5133 if(ps_curr_inp->s_lap_out.i4_is_cra_pic)
5134 {
5135 nal_type = NAL_CRA;
5136 }
5137
5138 ps_enc_ctxt->i4_cra_poc = cur_poc;
5139 break;
5140
5141 case IV_P_FRAME:
5142 slice_type = PSLICE;
5143 break;
5144
5145 case IV_B_FRAME:
5146 /* TODO : Mark the nal type as NAL_TRAIL_N for non ref pics */
5147 slice_type = BSLICE;
5148 break;
5149
5150 default:
5151 /* This should never occur */
5152 ASSERT(0);
5153 }
5154
5155 /* number of merge candidates and error metric chosen based on quality preset */
5156 switch(ps_curr_inp->s_lap_out.i4_quality_preset)
5157 {
5158 case IHEVCE_QUALITY_P0:
5159 max_merge_candidates = 5;
5160 break;
5161
5162 case IHEVCE_QUALITY_P2:
5163 max_merge_candidates = 5;
5164 break;
5165
5166 case IHEVCE_QUALITY_P3:
5167 max_merge_candidates = 3;
5168 break;
5169
5170 case IHEVCE_QUALITY_P4:
5171 case IHEVCE_QUALITY_P5:
5172 case IHEVCE_QUALITY_P6:
5173 max_merge_candidates = 2;
5174 break;
5175
5176 default:
5177 ASSERT(0);
5178 }
5179
5180 /* acquire mutex lock for rate control calls */
5181 osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
5182 {
5183 ps_curr_inp->s_rc_lap_out.i4_num_pels_in_frame_considered =
5184 ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht *
5185 ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd;
5186
5187 /*initialize the frame info stat inside LAP out, Data inside this will be populated in ihevce_rc_get_bpp_based_frame_qp call*/
5188 ps_curr_inp->s_rc_lap_out.ps_frame_info = &ps_curr_inp->s_frame_info;
5189
5190 ps_curr_inp->s_rc_lap_out.i4_is_bottom_field = ps_curr_inp->s_input_buf.i4_bottom_field;
5191 if(ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode == 3)
5192 {
5193 /*for constant qp use same qp*/
5194 /*HEVC_RC query rate control for qp*/
5195 cur_qp = ihevce_rc_pre_enc_qp_query(
5196 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
5197 &ps_curr_inp->s_rc_lap_out,
5198 0);
5199 }
5200 else
5201 {
5202 cur_qp = ihevce_rc_get_bpp_based_frame_qp(
5203 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0], &ps_curr_inp->s_rc_lap_out);
5204 }
5205 }
5206 /* release mutex lock after rate control calls */
5207 osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
5208
5209 /* store the QP in output prms */
5210 /* The same qp is also used in enc thread only for ME*/
5211 ps_curr_out->i4_curr_frm_qp = cur_qp;
5212
5213 /* slice header entropy syn memory is not valid in pre encode stage */
5214 ps_curr_out->s_slice_hdr.pu4_entry_point_offset = NULL;
5215
5216 /* derive the flag which indicates if stasino is enabled */
5217 stasino_enabled = (ps_enc_ctxt->s_runtime_coding_prms.i4_vqet &
5218 (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_NOISE_PRESERVATION)) &&
5219 (ps_enc_ctxt->s_runtime_coding_prms.i4_vqet &
5220 (1 << BITPOS_IN_VQ_TOGGLE_FOR_CONTROL_TOGGLER));
5221
5222 /* initialize the slice header */
5223 ihevce_populate_slice_header(
5224 &ps_curr_out->s_slice_hdr,
5225 &ps_enc_ctxt->as_pps[0],
5226 &ps_enc_ctxt->as_sps[0],
5227 nal_type,
5228 slice_type,
5229 0,
5230 0,
5231 ps_curr_inp->s_lap_out.i4_poc,
5232 cur_qp,
5233 max_merge_candidates,
5234 ps_enc_ctxt->ps_stat_prms->s_pass_prms.i4_pass,
5235 ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id]
5236 .i4_quality_preset,
5237 stasino_enabled);
5238
5239 ps_curr_out->i4_slice_nal_type = nal_type;
5240
5241 ps_curr_out->s_slice_hdr.u4_nuh_temporal_id = 0;
5242
5243 if(1 == ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.i4_enable_temporal_scalability)
5244 {
5245 ps_curr_out->s_slice_hdr.u4_nuh_temporal_id =
5246 (ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_max_temporal_layers ==
5247 ps_curr_inp->s_lap_out.i4_temporal_lyr_id); //TEMPORALA_SCALABILITY CHANGES
5248 }
5249
5250 /* populate sps, vps and pps pointers for the entropy input params */
5251 ps_curr_out->ps_pps = &ps_enc_ctxt->as_pps[0];
5252 ps_curr_out->ps_sps = &ps_enc_ctxt->as_sps[0];
5253 ps_curr_out->ps_vps = &ps_enc_ctxt->as_vps[0];
5254 }
5255
5256 /* By default, Sei messages are set to 0, to avoid unintialised memory access */
5257 memset(&ps_curr_out->s_sei, 0, sizeof(sei_params_t));
5258
5259 /* VUI, SEI flags reset */
5260 ps_curr_out->s_sei.i1_sei_parameters_present_flag = 0;
5261 ps_curr_out->s_sei.i1_buf_period_params_present_flag = 0;
5262 ps_curr_out->s_sei.i1_pic_timing_params_present_flag = 0;
5263 ps_curr_out->s_sei.i1_recovery_point_params_present_flag = 0;
5264 ps_curr_out->s_sei.i1_decoded_pic_hash_sei_flag = 0;
5265 ps_curr_out->s_sei.i4_sei_mastering_disp_colour_vol_params_present_flags = 0;
5266
5267 if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_enable_flag == 1)
5268 {
5269 /* insert buffering period, display volume, recovery point only at irap points */
5270 WORD32 insert_per_irap =
5271 ((slice_type == ISLICE) &&
5272 (((NAL_IDR_N_LP == nal_type) || (NAL_CRA == nal_type)) || (NAL_IDR_W_LP == nal_type)));
5273
5274 ps_curr_out->s_sei.i1_sei_parameters_present_flag = 1;
5275
5276 /* populate Sei buffering period based on encoder configuration and tools */
5277 if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_buffer_period_flags == 1)
5278 {
5279 ihevce_populate_buffering_period_sei(
5280 &ps_curr_out->s_sei,
5281 &ps_enc_ctxt->as_sps[0].s_vui_parameters,
5282 &ps_enc_ctxt->as_sps[0],
5283 &ps_enc_ctxt->ps_stat_prms->s_vui_sei_prms);
5284
5285 ps_curr_out->s_sei.i1_buf_period_params_present_flag = insert_per_irap;
5286
5287 ihevce_populate_active_parameter_set_sei(
5288 &ps_curr_out->s_sei, &ps_enc_ctxt->as_vps[0], &ps_enc_ctxt->as_sps[0]);
5289 }
5290
5291 /* populate Sei picture timing based on encoder configuration and tools */
5292 if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_pic_timing_flags == 1)
5293 {
5294 ihevce_populate_picture_timing_sei(
5295 &ps_curr_out->s_sei,
5296 &ps_enc_ctxt->as_sps[0].s_vui_parameters,
5297 &ps_enc_ctxt->s_runtime_src_prms,
5298 ps_curr_inp->s_input_buf.i4_bottom_field);
5299 ps_curr_out->s_sei.i1_pic_timing_params_present_flag = 1;
5300 }
5301
5302 /* populate Sei recovery point based on encoder configuration and tools */
5303 if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_recovery_point_flags == 1)
5304 {
5305 ihevce_populate_recovery_point_sei(
5306 &ps_curr_out->s_sei, &ps_enc_ctxt->ps_stat_prms->s_vui_sei_prms);
5307 ps_curr_out->s_sei.i1_recovery_point_params_present_flag = insert_per_irap;
5308 }
5309
5310 /* populate mastering_display_colour_volume parameters */
5311 if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_mastering_disp_colour_vol_flags == 1)
5312 {
5313 ihevce_populate_mastering_disp_col_vol_sei(
5314 &ps_curr_out->s_sei, &ps_enc_ctxt->ps_stat_prms->s_out_strm_prms);
5315
5316 ps_curr_out->s_sei.i4_sei_mastering_disp_colour_vol_params_present_flags =
5317 insert_per_irap;
5318 }
5319
5320 /* populate SEI Hash Flag based on encoder configuration */
5321 if(0 != ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag)
5322 {
5323 /* Sanity checks */
5324 ASSERT(0 != ps_enc_ctxt->as_sps[0].i1_chroma_format_idc);
5325
5326 ASSERT(
5327 (0 < ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag) &&
5328 (4 > ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag));
5329
5330 /* MD5 is not supported now! picture_md5[cIdx][i] pblm */
5331 ASSERT(1 != ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag);
5332
5333 ps_curr_out->s_sei.i1_decoded_pic_hash_sei_flag =
5334 ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag;
5335 }
5336 }
5337
5338 /* For interlace pictures, first_field depends on topfield_first and bottom field */
5339 if(i4_field_pic)
5340 {
5341 first_field =
5342 (ps_curr_inp->s_input_buf.i4_topfield_first ^ ps_curr_inp->s_input_buf.i4_bottom_field);
5343 }
5344
5345 /* get frame level lambda params */
5346 ihevce_get_frame_lambda_prms(
5347 ps_enc_ctxt,
5348 ps_curr_out,
5349 cur_qp,
5350 first_field,
5351 ps_curr_inp->s_lap_out.i4_is_ref_pic,
5352 ps_curr_inp->s_lap_out.i4_temporal_lyr_id,
5353 lamda_modifier_for_I_pic[4] /*mean TRF*/,
5354 0,
5355 PRE_ENC_LAMBDA_TYPE);
5356 /* Coarse ME and Decomp buffers sharing */
5357 {
5358 UWORD8 *apu1_lyr_bufs[MAX_NUM_HME_LAYERS];
5359 WORD32 ai4_lyr_buf_strd[MAX_NUM_HME_LAYERS];
5360
5361 /* get the Decomposition frame buffer from ME */
5362 i4_decomp_lyrs_idx = ihevce_coarse_me_get_lyr_buf_desc(
5363 ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt, &apu1_lyr_bufs[0], &ai4_lyr_buf_strd[0]);
5364 /* register the buffers with decomp module along with frame init */
5365 ihevce_decomp_pre_intra_frame_init(
5366 ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt,
5367 &apu1_lyr_bufs[0],
5368 &ai4_lyr_buf_strd[0],
5369 ps_curr_out->ps_layer1_buf,
5370 ps_curr_out->ps_layer2_buf,
5371 ps_curr_out->ps_ed_ctb_l1,
5372 ps_curr_out->as_lambda_prms[0].i4_ol_sad_lambda_qf,
5373 ps_curr_out->ps_ctb_analyse);
5374 }
5375
5376 /* -------------------------------------------------------- */
5377 /* Preparing Pre encode Passes Job Queue */
5378 /* -------------------------------------------------------- */
5379 ihevce_prepare_pre_enc_job_queue(ps_enc_ctxt, ps_curr_inp, i4_ping_pong);
5380
5381 /*assign return variables */
5382 *pi4_end_flag_ret = end_flag;
5383 *pi4_cur_qp_ret = cur_qp;
5384 *pi4_decomp_lyr_idx = i4_decomp_lyrs_idx;
5385 //*pps_frm_recon_ret = ps_frm_recon;
5386 }
5387
5388 /*!
5389 ******************************************************************************
5390 * \if Function name : ihevce_pre_enc_coarse_me_init \endif
5391 *
5392 * \brief
5393 * set out_buf params
5394 * Calculate end_flag if flushmode on
5395 * Slice initialization
5396 * Populate SIE params
5397 * reference list creation
5398 *
5399 * \param[in] Encoder context pointer
5400 *
5401 * \return
5402 * None
5403 *
5404 * \author
5405 * Ittiam
5406 *
5407 *****************************************************************************
5408 */
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)5409 void ihevce_pre_enc_coarse_me_init(
5410 enc_ctxt_t *ps_enc_ctxt,
5411 ihevce_lap_enc_buf_t *ps_curr_inp,
5412 pre_enc_me_ctxt_t *ps_curr_out,
5413 recon_pic_buf_t **pps_frm_recon_ret,
5414 WORD32 i4_decomp_lyrs_idx,
5415 WORD32 i4_cur_qp,
5416 WORD32 i4_ping_pong)
5417
5418 {
5419 /* local variables */
5420 recon_pic_buf_t *ps_frm_recon;
5421 coarse_me_master_ctxt_t *ps_ctxt = NULL;
5422 ps_ctxt = (coarse_me_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt;
5423 /* Reference buffer management and reference list creation for pre enc group */
5424 ihevce_pre_enc_manage_ref_pics(ps_enc_ctxt, ps_curr_inp, ps_curr_out, i4_ping_pong);
5425
5426 /* get a free recon buffer for current picture */
5427 {
5428 WORD32 ctr;
5429
5430 ps_frm_recon = NULL;
5431 for(ctr = 0; ctr < ps_enc_ctxt->i4_pre_enc_num_buf_recon_q; ctr++)
5432 {
5433 if(1 == ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr]->i4_is_free)
5434 {
5435 ps_frm_recon = ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr];
5436 break;
5437 }
5438 }
5439 }
5440 /* should not be NULL */
5441 ASSERT(ps_frm_recon != NULL);
5442
5443 /* populate reference /recon params based on LAP output */
5444 ps_frm_recon->i4_is_free = 0;
5445 /* top first field is set to 1 by application */
5446 ps_frm_recon->i4_topfield_first = ps_curr_inp->s_input_buf.i4_topfield_first;
5447 ps_frm_recon->i4_poc = ps_curr_inp->s_lap_out.i4_poc;
5448 ps_frm_recon->i4_pic_type = ps_curr_inp->s_lap_out.i4_pic_type;
5449 ps_frm_recon->i4_display_num = ps_curr_inp->s_lap_out.i4_display_num;
5450 /* bottom field is toggled for every field by application */
5451 ps_frm_recon->i4_bottom_field = ps_curr_inp->s_input_buf.i4_bottom_field;
5452
5453 /* Reference picture property is given by LAP */
5454 ps_frm_recon->i4_is_reference = ps_curr_inp->s_lap_out.i4_is_ref_pic;
5455
5456 /* Deblock a picture for all reference frames unconditionally. */
5457 /* Deblock non ref if psnr compute or save recon is enabled */
5458 ps_frm_recon->i4_deblk_pad_hpel_cur_pic = ps_frm_recon->i4_is_reference ||
5459 (ps_enc_ctxt->ps_stat_prms->i4_save_recon);
5460
5461 /* set the width, height and stride to defalut values */
5462 ps_frm_recon->s_yuv_buf_desc.i4_y_ht = 0;
5463 ps_frm_recon->s_yuv_buf_desc.i4_uv_ht = 0;
5464 ps_frm_recon->s_yuv_buf_desc.i4_y_wd = 0;
5465 ps_frm_recon->s_yuv_buf_desc.i4_uv_wd = 0;
5466 ps_frm_recon->s_yuv_buf_desc.i4_y_strd = 0;
5467 ps_frm_recon->s_yuv_buf_desc.i4_uv_strd = 0;
5468
5469 /* register the Layer1 MV bank pointer with ME module */
5470 ihevce_coarse_me_set_lyr1_mv_bank(
5471 ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
5472 ps_curr_inp,
5473 ps_curr_out->pv_me_mv_bank,
5474 ps_curr_out->pv_me_ref_idx,
5475 i4_decomp_lyrs_idx);
5476
5477 /* Coarse picture level init of ME */
5478 ihevce_coarse_me_frame_init(
5479 ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
5480 ps_enc_ctxt->ps_stat_prms,
5481 &ps_enc_ctxt->s_frm_ctb_prms,
5482 &ps_curr_out->as_lambda_prms[0],
5483 ps_enc_ctxt->i4_pre_enc_num_ref_l0,
5484 ps_enc_ctxt->i4_pre_enc_num_ref_l1,
5485 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active,
5486 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active,
5487 &ps_enc_ctxt->aps_pre_enc_ref_lists[i4_ping_pong][LIST_0][0],
5488 &ps_enc_ctxt->aps_pre_enc_ref_lists[i4_ping_pong][LIST_1][0],
5489 ps_curr_inp,
5490 i4_cur_qp,
5491 ps_curr_out->ps_layer1_buf,
5492 ps_curr_out->ps_ed_ctb_l1,
5493 ps_curr_out->pu1_me_reverse_map_info,
5494 ps_curr_inp->s_lap_out.i4_temporal_lyr_id);
5495
5496 /*assign return variables */
5497 *pps_frm_recon_ret = ps_frm_recon;
5498 }
5499
5500 /*!
5501 ******************************************************************************
5502 * \brief
5503 * Function to calculate modulation based on spatial variance across lap period
5504 *
5505 *****************************************************************************
5506 */
ihevce_variance_calc_acc_activity(enc_ctxt_t * ps_enc_ctxt,WORD32 i4_cur_ipe_idx)5507 void ihevce_variance_calc_acc_activity(enc_ctxt_t *ps_enc_ctxt, WORD32 i4_cur_ipe_idx)
5508 {
5509 pre_enc_me_ctxt_t *ps_curr_out = ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[i4_cur_ipe_idx];
5510 WORD32 is_curr_bslice = (ps_curr_out->s_slice_hdr.i1_slice_type == BSLICE);
5511 #if MODULATION_OVER_LAP
5512 WORD32 loop_lap2 = MAX(1, ps_enc_ctxt->s_multi_thrd.i4_delay_pre_me_btw_l0_ipe - 1);
5513 #else
5514 WORD32 loop_lap2 = 1;
5515 #endif
5516 WORD32 i4_delay_loop = ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe;
5517 WORD32 i, j;
5518
5519 ps_curr_out->i8_acc_frame_8x8_sum_act_sqr = 0;
5520 ps_curr_out->i8_acc_frame_8x8_sum_act_for_strength = 0;
5521 for(i = 0; i < 2; i++)
5522 {
5523 ps_curr_out->i8_acc_frame_8x8_sum_act[i] = 0;
5524 ps_curr_out->i4_acc_frame_8x8_num_blks[i] = 0;
5525 ps_curr_out->i8_acc_frame_16x16_sum_act[i] = 0;
5526 ps_curr_out->i4_acc_frame_16x16_num_blks[i] = 0;
5527 ps_curr_out->i8_acc_frame_32x32_sum_act[i] = 0;
5528 ps_curr_out->i4_acc_frame_32x32_num_blks[i] = 0;
5529 }
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 if(!is_curr_bslice)
5536 {
5537 for(i = 0; i < loop_lap2; i++)
5538 {
5539 WORD32 ipe_idx_tmp = (i4_cur_ipe_idx + i) % i4_delay_loop;
5540 ihevce_lap_enc_buf_t *ps_in = ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[ipe_idx_tmp];
5541 pre_enc_me_ctxt_t *ps_out = ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[ipe_idx_tmp];
5542 UWORD8 is_bslice = (ps_out->s_slice_hdr.i1_slice_type == BSLICE);
5543
5544 if(!is_bslice)
5545 {
5546 ps_curr_out->i8_acc_frame_8x8_sum_act_sqr += ps_out->u8_curr_frame_8x8_sum_act_sqr;
5547 ps_curr_out->i8_acc_frame_8x8_sum_act_for_strength += ps_out->i4_curr_frame_8x8_sum_act_for_strength[0];
5548 for(j = 0; j < 2; j++)
5549 {
5550 ps_curr_out->i8_acc_frame_8x8_sum_act[j] += ps_out->i8_curr_frame_8x8_sum_act[j];
5551 ps_curr_out->i4_acc_frame_8x8_num_blks[j] += ps_out->i4_curr_frame_8x8_num_blks[j];
5552 ps_curr_out->i8_acc_frame_16x16_sum_act[j] += ps_out->i8_curr_frame_16x16_sum_act[j];
5553 ps_curr_out->i4_acc_frame_16x16_num_blks[j] += ps_out->i4_curr_frame_16x16_num_blks[j];
5554 ps_curr_out->i8_acc_frame_32x32_sum_act[j] += ps_out->i8_curr_frame_32x32_sum_act[j];
5555 ps_curr_out->i4_acc_frame_32x32_num_blks[j] += ps_out->i4_curr_frame_32x32_num_blks[j];
5556 }
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 if(NULL == ps_in->s_rc_lap_out.ps_rc_lap_out_next_encode)
5563 break;
5564 }
5565
5566 for(j = 0; j < 3; j++)
5567 {
5568 if(j < 2)
5569 ASSERT(0 != ps_curr_out->i4_acc_frame_8x8_num_blks[j]);
5570 ASSERT(0 != ps_curr_out->i4_acc_frame_16x16_num_blks[j]);
5571 ASSERT(0 != ps_curr_out->i4_acc_frame_32x32_num_blks[j]);
5572
5573 #define AVG_ACTIVITY(a, b, c) a = ((b + (c >> 1)) / c)
5574
5575 if(j < 2)
5576 {
5577 if(0 == ps_curr_out->i4_acc_frame_8x8_num_blks[j])
5578 {
5579 ps_curr_out->i8_curr_frame_8x8_avg_act[j] = 0;
5580 }
5581 else
5582 {
5583 AVG_ACTIVITY(ps_curr_out->i8_curr_frame_8x8_sum_act_for_strength,
5584 ps_curr_out->i8_acc_frame_8x8_sum_act_for_strength,
5585 ps_curr_out->i4_acc_frame_8x8_num_blks[j]);
5586 AVG_ACTIVITY(ps_curr_out->i8_curr_frame_8x8_avg_act[j],
5587 ps_curr_out->i8_acc_frame_8x8_sum_act[j],
5588 ps_curr_out->i4_acc_frame_8x8_num_blks[j]);
5589 ps_curr_out->ld_curr_frame_8x8_log_avg[j] =
5590 fast_log2(1 + ps_curr_out->i8_curr_frame_8x8_avg_act[j]);
5591 }
5592 }
5593
5594 if(0 == ps_curr_out->i4_acc_frame_16x16_num_blks[j])
5595 {
5596 ps_curr_out->i8_curr_frame_16x16_avg_act[j] = 0;
5597 }
5598 else
5599 {
5600 AVG_ACTIVITY(ps_curr_out->i8_curr_frame_16x16_avg_act[j],
5601 ps_curr_out->i8_acc_frame_16x16_sum_act[j],
5602 ps_curr_out->i4_acc_frame_16x16_num_blks[j]);
5603 ps_curr_out->ld_curr_frame_16x16_log_avg[j] =
5604 fast_log2(1 + ps_curr_out->i8_curr_frame_16x16_avg_act[j]);
5605 }
5606
5607 if(0 == ps_curr_out->i4_acc_frame_32x32_num_blks[j])
5608 {
5609 ps_curr_out->i8_curr_frame_32x32_avg_act[j] = 0;
5610 }
5611 else
5612 {
5613 AVG_ACTIVITY(ps_curr_out->i8_curr_frame_32x32_avg_act[j],
5614 ps_curr_out->i8_acc_frame_32x32_sum_act[j],
5615 ps_curr_out->i4_acc_frame_32x32_num_blks[j]);
5616 ps_curr_out->ld_curr_frame_32x32_log_avg[j] =
5617 fast_log2(1 + ps_curr_out->i8_curr_frame_32x32_avg_act[j]);
5618 }
5619 }
5620
5621 /* store the avg activity for B pictures */
5622 #if POW_OPT
5623 ps_enc_ctxt->ald_lap2_8x8_log_avg_act_from_T0[0] = ps_curr_out->ld_curr_frame_8x8_log_avg[0];
5624 ps_enc_ctxt->ald_lap2_8x8_log_avg_act_from_T0[1] = ps_curr_out->ld_curr_frame_8x8_log_avg[1];
5625 ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[0] = ps_curr_out->ld_curr_frame_16x16_log_avg[0];
5626 ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[1] = ps_curr_out->ld_curr_frame_16x16_log_avg[1];
5627 ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[2] = ps_curr_out->ld_curr_frame_16x16_log_avg[2];
5628 ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[0] = ps_curr_out->ld_curr_frame_32x32_log_avg[0];
5629 ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[1] = ps_curr_out->ld_curr_frame_32x32_log_avg[1];
5630 ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[2] = ps_curr_out->ld_curr_frame_32x32_log_avg[2];
5631 #else
5632 ps_enc_ctxt->ai8_lap2_8x8_avg_act_from_T0[0] = ps_curr_out->i8_curr_frame_8x8_avg_act[0];
5633 ps_enc_ctxt->ai8_lap2_8x8_avg_act_from_T0[1] = ps_curr_out->i8_curr_frame_8x8_avg_act[1];
5634 ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[0] = ps_curr_out->i8_curr_frame_16x16_avg_act[0];
5635 ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[1] = ps_curr_out->i8_curr_frame_16x16_avg_act[1];
5636 ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[2] = ps_curr_out->i8_curr_frame_16x16_avg_act[2];
5637 ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[0] = ps_curr_out->i8_curr_frame_32x32_avg_act[0];
5638 ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[1] = ps_curr_out->i8_curr_frame_32x32_avg_act[1];
5639 ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[2] = ps_curr_out->i8_curr_frame_32x32_avg_act[2];
5640 #endif
5641
5642 /* calculate modulation index */
5643 {
5644 LWORD64 i8_mean, i8_mean_sqr, i8_variance;
5645 LWORD64 i8_deviation;
5646 WORD32 i4_mod_factor;
5647 float f_strength;
5648
5649 if(ps_curr_out->i4_acc_frame_8x8_num_blks[0] > 0)
5650 {
5651 #if STRENGTH_BASED_ON_CURR_FRM
5652 AVG_ACTIVITY(i8_mean_sqr, ps_curr_out->i8_curr_frame_8x8_sum_act_sqr,
5653 ps_curr_out->i4_curr_frame_8x8_num_blks[0]);
5654 #else
5655 AVG_ACTIVITY(i8_mean_sqr, ps_curr_out->i8_acc_frame_8x8_sum_act_sqr,
5656 ps_curr_out->i4_acc_frame_8x8_num_blks[0]);
5657 #endif
5658 i8_mean = ps_curr_out->i8_curr_frame_8x8_sum_act_for_strength;
5659 i8_variance = i8_mean_sqr - (i8_mean * i8_mean);
5660 i8_deviation = sqrt(i8_variance);
5661
5662 #if STRENGTH_BASED_ON_DEVIATION
5663 if(i8_deviation <= REF_MOD_DEVIATION)
5664 {
5665 f_strength = ((i8_deviation - BELOW_REF_DEVIATION) * REF_MOD_STRENGTH) / (REF_MOD_DEVIATION - BELOW_REF_DEVIATION);
5666 }
5667 else
5668 {
5669 f_strength = ((i8_deviation - ABOVE_REF_DEVIATION) * REF_MOD_STRENGTH) / (REF_MOD_DEVIATION - ABOVE_REF_DEVIATION);
5670 }
5671 #else
5672 f_strength = ((i8_mean_sqr / (float)(i8_mean * i8_mean)) - 1.0) * REF_MOD_STRENGTH / REF_MOD_VARIANCE;
5673 #endif
5674 i4_mod_factor = (WORD32)(i8_deviation / 60);
5675 f_strength = CLIP3(f_strength, 0.0, REF_MAX_STRENGTH);
5676 }
5677 else
5678 {
5679 /* If not sufficient blocks are present, turn modulation index to 1 */
5680 i4_mod_factor = 1;
5681 f_strength = 0;
5682 }
5683 ps_curr_out->ai4_mod_factor_derived_by_variance[0] = i4_mod_factor;
5684 ps_curr_out->ai4_mod_factor_derived_by_variance[1] = i4_mod_factor;
5685 ps_curr_out->f_strength = f_strength;
5686
5687 ps_enc_ctxt->ai4_mod_factor_derived_by_variance[0] = i4_mod_factor;
5688 ps_enc_ctxt->ai4_mod_factor_derived_by_variance[1] = i4_mod_factor;
5689 ps_enc_ctxt->f_strength = f_strength;
5690 }
5691 }
5692 else
5693 {
5694 ps_curr_out->ai4_mod_factor_derived_by_variance[0] = ps_enc_ctxt->ai4_mod_factor_derived_by_variance[0];
5695 ps_curr_out->ai4_mod_factor_derived_by_variance[1] = ps_enc_ctxt->ai4_mod_factor_derived_by_variance[1];
5696 ps_curr_out->f_strength = ps_enc_ctxt->f_strength;
5697
5698 /* copy the prev avg activity from Tid 0 for B pictures*/
5699 #if POW_OPT
5700 ps_curr_out->ld_curr_frame_8x8_log_avg[0] = ps_enc_ctxt->ald_lap2_8x8_log_avg_act_from_T0[0];
5701 ps_curr_out->ld_curr_frame_8x8_log_avg[1] = ps_enc_ctxt->ald_lap2_8x8_log_avg_act_from_T0[1];
5702 ps_curr_out->ld_curr_frame_16x16_log_avg[0] = ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[0];
5703 ps_curr_out->ld_curr_frame_16x16_log_avg[1] = ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[1];
5704 ps_curr_out->ld_curr_frame_16x16_log_avg[2] = ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[2];
5705 ps_curr_out->ld_curr_frame_32x32_log_avg[0] = ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[0];
5706 ps_curr_out->ld_curr_frame_32x32_log_avg[1] = ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[1];
5707 ps_curr_out->ld_curr_frame_32x32_log_avg[2] = ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[2];
5708 #else
5709 ps_curr_out->i8_curr_frame_8x8_avg_act[0] = ps_enc_ctxt->ai8_lap2_8x8_avg_act_from_T0[0];
5710 ps_curr_out->i8_curr_frame_8x8_avg_act[1] = ps_enc_ctxt->ai8_lap2_8x8_avg_act_from_T0[1];
5711 ps_curr_out->i8_curr_frame_16x16_avg_act[0] = ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[0];
5712 ps_curr_out->i8_curr_frame_16x16_avg_act[1] = ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[1];
5713 ps_curr_out->i8_curr_frame_16x16_avg_act[2] = ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[2];
5714 ps_curr_out->i8_curr_frame_32x32_avg_act[0] = ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[0];
5715 ps_curr_out->i8_curr_frame_32x32_avg_act[1] = ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[1];
5716 ps_curr_out->i8_curr_frame_32x32_avg_act[2] = ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[2];
5717 #endif
5718 }
5719 #undef AVG_ACTIVITY
5720 }
5721
5722 /*!
5723 ******************************************************************************
5724 * \if Function name : ihevce_pre_enc_process_frame_thrd \endif
5725 *
5726 * \brief
5727 * Pre-Encode Frame processing thread interface function
5728 *
5729 * \param[in] High level encoder context pointer
5730 *
5731 * \return
5732 * None
5733 *
5734 * \author
5735 * Ittiam
5736 *
5737 *****************************************************************************
5738 */
ihevce_pre_enc_process_frame_thrd(void * pv_frm_proc_thrd_ctxt)5739 WORD32 ihevce_pre_enc_process_frame_thrd(void *pv_frm_proc_thrd_ctxt)
5740 {
5741 frm_proc_thrd_ctxt_t *ps_thrd_ctxt = (frm_proc_thrd_ctxt_t *)pv_frm_proc_thrd_ctxt;
5742 ihevce_hle_ctxt_t *ps_hle_ctxt = ps_thrd_ctxt->ps_hle_ctxt;
5743 enc_ctxt_t *ps_enc_ctxt = (enc_ctxt_t *)ps_thrd_ctxt->pv_enc_ctxt;
5744 multi_thrd_ctxt_t *ps_multi_thrd = &ps_enc_ctxt->s_multi_thrd;
5745 WORD32 i4_thrd_id = ps_thrd_ctxt->i4_thrd_id;
5746 WORD32 i4_resolution_id = ps_enc_ctxt->i4_resolution_id;
5747 WORD32 i4_end_flag = 0;
5748 WORD32 i4_out_flush_flag = 0;
5749 WORD32 i4_cur_decomp_idx = 0;
5750 WORD32 i4_cur_coarse_me_idx = 0;
5751 WORD32 i4_cur_ipe_idx = 0;
5752 ihevce_lap_enc_buf_t *ps_lap_inp_buf = NULL;
5753 void *pv_dep_mngr_prev_frame_pre_enc_l1 = ps_multi_thrd->pv_dep_mngr_prev_frame_pre_enc_l1;
5754 void *pv_dep_mngr_prev_frame_pre_enc_l0 = ps_multi_thrd->pv_dep_mngr_prev_frame_pre_enc_l0;
5755 void *pv_dep_mngr_prev_frame_pre_enc_coarse_me =
5756 ps_multi_thrd->pv_dep_mngr_prev_frame_pre_enc_coarse_me;
5757 WORD32 i4_num_buf_prod_for_l0_ipe = 0;
5758 WORD32 i4_decomp_end_flag = 0;
5759
5760 (void)ps_hle_ctxt;
5761 (void)i4_resolution_id;
5762
5763 /* ---------- Processing Loop until Flush command is received --------- */
5764 while(0 == i4_end_flag)
5765 {
5766 /* Wait till previous frame(instance)'s decomp_intra is processed */
5767 {
5768 ihevce_dmgr_chk_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_l1, i4_thrd_id);
5769 }
5770
5771 /* ----------------------------------------------------------- */
5772 /* decomp pre_intra init */
5773 /* ----------------------------------------------------------- */
5774
5775 /****** Lock the critical section for decomp pre_intra init ******/
5776 {
5777 WORD32 i4_status;
5778
5779 i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_init);
5780 if(OSAL_SUCCESS != i4_status)
5781 return 0;
5782 }
5783
5784 ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_decomp_idx] = 0;
5785
5786 /* init */
5787 if((ps_multi_thrd->ai4_pre_enc_init_done[i4_cur_decomp_idx] == 0) &&
5788 (0 == i4_decomp_end_flag))
5789 {
5790 ihevce_lap_enc_buf_t *ps_curr_inp = NULL;
5791 pre_enc_me_ctxt_t *ps_curr_out = NULL;
5792 WORD32 in_buf_id;
5793 WORD32 out_buf_id;
5794
5795 do
5796 {
5797 ps_lap_inp_buf = NULL;
5798 if(0 == ps_multi_thrd->i4_last_inp_buf)
5799 {
5800 /* ------- get input buffer input data que ---------- */
5801 ps_lap_inp_buf = (ihevce_lap_enc_buf_t *)ihevce_q_get_filled_buff(
5802 (void *)ps_enc_ctxt,
5803 IHEVCE_INPUT_DATA_CTRL_Q,
5804 &in_buf_id,
5805 BUFF_QUE_BLOCKING_MODE);
5806 ps_multi_thrd->i4_last_inp_buf = ihevce_check_last_inp_buf(
5807 (WORD32 *)ps_lap_inp_buf->s_input_buf.pv_synch_ctrl_bufs);
5808 }
5809
5810 ps_curr_inp =
5811 ihevce_lap_process(ps_enc_ctxt->pv_lap_interface_ctxt, ps_lap_inp_buf);
5812
5813 } while(NULL == ps_curr_inp);
5814
5815 /* set the flag saying init is done so that other cores dont do it */
5816 ps_multi_thrd->ai4_pre_enc_init_done[i4_cur_decomp_idx] = 1;
5817
5818 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_decomp_idx] = ps_curr_inp;
5819 ps_multi_thrd->ai4_in_buf_id_pre_enc[i4_cur_decomp_idx] =
5820 ps_curr_inp->s_input_buf.i4_buf_id;
5821
5822 /* ------- get free output buffer from pre-enc/enc buffer que ---------- */
5823 ps_curr_out = (pre_enc_me_ctxt_t *)ihevce_q_get_free_buff(
5824 (void *)ps_enc_ctxt, IHEVCE_PRE_ENC_ME_Q, &out_buf_id, BUFF_QUE_BLOCKING_MODE);
5825 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_decomp_idx] = ps_curr_out;
5826 ps_multi_thrd->ai4_out_buf_id_pre_enc[i4_cur_decomp_idx] = out_buf_id;
5827
5828 if((NULL != ps_curr_inp) && (NULL != ps_curr_out))
5829 {
5830 /* by default last picture to be encoded flag is set to 0 */
5831 /* this flag will be used by slave threads to exit at the end */
5832 ps_multi_thrd->i4_last_pic_flag = 0;
5833
5834 /* store the buffer id */
5835 ps_curr_out->i4_buf_id = out_buf_id;
5836
5837 ps_curr_out->i8_acc_num_blks_high_sad = 0;
5838 ps_curr_out->i8_total_blks = 0;
5839 ps_curr_out->i4_is_high_complex_region = -1;
5840
5841 /* set the parameters for sync b/w pre-encode and encode threads */
5842 ps_curr_out->i4_end_flag = ps_curr_inp->s_lap_out.i4_end_flag;
5843 ps_curr_out->i4_frm_proc_valid_flag = 1;
5844 if(ps_curr_out->i4_end_flag)
5845 {
5846 ps_curr_out->i4_frm_proc_valid_flag =
5847 ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag;
5848 ps_multi_thrd->i4_last_pic_flag = 1;
5849 ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx] = 1;
5850 }
5851 if(ps_curr_inp->s_lap_out.i4_out_flush_flag)
5852 {
5853 ps_curr_out->i4_frm_proc_valid_flag =
5854 ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag;
5855 }
5856
5857 /* do the init processing if input frm data is valid */
5858 if(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag)
5859 {
5860 WORD32 end_flag = ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx];
5861 WORD32 cur_qp = 0, count;
5862
5863 ihevce_pre_enc_init(
5864 ps_enc_ctxt,
5865 ps_curr_inp,
5866 ps_curr_out,
5867 &end_flag,
5868 &cur_qp,
5869 &ps_multi_thrd->ai4_decomp_lyr_buf_idx[i4_cur_decomp_idx],
5870 i4_cur_decomp_idx);
5871
5872 ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx] = end_flag;
5873 ps_multi_thrd->ai4_cur_frame_qp_pre_enc[i4_cur_decomp_idx] = cur_qp;
5874
5875 for(count = 0; count < ((HEVCE_MAX_HEIGHT >> 1) / 8); count++)
5876 {
5877 ps_multi_thrd->aai4_l1_pre_intra_done[i4_cur_decomp_idx][count] = 0;
5878 }
5879 }
5880 }
5881 }
5882 else if(1 == i4_decomp_end_flag)
5883 {
5884 /* Once end is reached all subsequent flags are set to 1 to indicate end */
5885 ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx] = 1;
5886 }
5887
5888 /****** UnLock the critical section after decomp pre_intra init ******/
5889 {
5890 WORD32 i4_status;
5891 i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_pre_enc_init);
5892
5893 if(OSAL_SUCCESS != i4_status)
5894 return 0;
5895 }
5896 if(i4_thrd_id == 0)
5897 {
5898 PROFILE_START(&ps_hle_ctxt->profile_pre_enc_l1l2[i4_resolution_id]);
5899 }
5900 /* ------------------------------------------------------------ */
5901 /* Layer Decomp and Pre Intra Analysis */
5902 /* ------------------------------------------------------------ */
5903 if(0 == i4_decomp_end_flag)
5904 {
5905 pre_enc_me_ctxt_t *ps_curr_out = ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_decomp_idx];
5906
5907 if(1 == ps_curr_out->i4_frm_proc_valid_flag)
5908 {
5909 ihevce_decomp_pre_intra_process(
5910 ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt,
5911 &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_decomp_idx]->s_lap_out,
5912 &ps_enc_ctxt->s_frm_ctb_prms,
5913 ps_multi_thrd,
5914 i4_thrd_id,
5915 i4_cur_decomp_idx);
5916 }
5917 }
5918
5919 /* ------------------------------------------------------------ */
5920 /* Layer Decomp and Pre Intra Deinit */
5921 /* ------------------------------------------------------------ */
5922
5923 /****** Lock the critical section for decomp deinit ******/
5924 {
5925 WORD32 i4_status;
5926 i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_decomp_deinit);
5927
5928 if(OSAL_SUCCESS != i4_status)
5929 return 0;
5930 }
5931
5932 ps_multi_thrd->ai4_num_thrds_processed_decomp[i4_cur_decomp_idx]++;
5933 i4_decomp_end_flag = ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx];
5934
5935 /* check for last thread condition */
5936 if(ps_multi_thrd->ai4_num_thrds_processed_decomp[i4_cur_decomp_idx] ==
5937 ps_multi_thrd->i4_num_pre_enc_proc_thrds)
5938 {
5939 ps_multi_thrd->ai4_num_thrds_processed_decomp[i4_cur_decomp_idx] = 0;
5940
5941 /* reset the init flag so that init happens by the first thread for the next frame
5942 of same ping_pong instance */
5943 ps_multi_thrd->ai4_pre_enc_init_done[i4_cur_decomp_idx] = 0;
5944
5945 /* update the pre enc l1 done in dep manager */
5946 ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_l1);
5947 }
5948
5949 /* index increment */
5950 i4_cur_decomp_idx = i4_cur_decomp_idx + 1;
5951
5952 /* wrap around case */
5953 if(i4_cur_decomp_idx >= ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe)
5954 {
5955 i4_cur_decomp_idx = 0;
5956 }
5957
5958 /****** UnLock the critical section after decomp pre_intra deinit ******/
5959 {
5960 WORD32 i4_status;
5961 i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_pre_enc_decomp_deinit);
5962
5963 if(OSAL_SUCCESS != i4_status)
5964 return 0;
5965 }
5966
5967 /* ------------------------------------------------------------ */
5968 /* HME Init */
5969 /* ------------------------------------------------------------ */
5970
5971 /* Wait till previous frame(instance)'s coarse_me is processed */
5972 {
5973 ihevce_dmgr_chk_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_coarse_me, i4_thrd_id);
5974 }
5975
5976 /****** Lock the critical section for hme init ******/
5977 {
5978 WORD32 i4_status;
5979
5980 i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_hme_init);
5981 if(OSAL_SUCCESS != i4_status)
5982 return 0;
5983 }
5984
5985 if(0 == ps_multi_thrd->ai4_pre_enc_hme_init_done[i4_cur_coarse_me_idx])
5986 {
5987 /* do the init processing if input frm data is valid */
5988 if(1 ==
5989 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->i4_frm_proc_valid_flag)
5990 {
5991 recon_pic_buf_t *ps_frm_recon = NULL;
5992
5993 /* DPB management for coarse me + HME init */
5994 ihevce_pre_enc_coarse_me_init(
5995 ps_enc_ctxt,
5996 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx],
5997 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx],
5998 &ps_frm_recon,
5999 ps_multi_thrd->ai4_decomp_lyr_buf_idx[i4_cur_coarse_me_idx],
6000 ps_multi_thrd->ai4_cur_frame_qp_pre_enc[i4_cur_coarse_me_idx],
6001 i4_cur_coarse_me_idx);
6002 }
6003
6004 ps_multi_thrd->ai4_pre_enc_hme_init_done[i4_cur_coarse_me_idx] = 1;
6005 }
6006
6007 /****** Unlock the critical section for hme init ******/
6008 {
6009 WORD32 i4_status;
6010
6011 i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_pre_enc_hme_init);
6012 if(OSAL_SUCCESS != i4_status)
6013 return 0;
6014 }
6015
6016 /* ------------------------------------------------------------ */
6017 /* Coarse Motion estimation and early intra-inter decision */
6018 /* ------------------------------------------------------------ */
6019 if(1 == ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->i4_frm_proc_valid_flag)
6020 {
6021 ihevce_coarse_me_process(
6022 ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
6023 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx],
6024 &ps_enc_ctxt->s_multi_thrd,
6025 i4_thrd_id,
6026 i4_cur_coarse_me_idx);
6027 }
6028
6029 /* update the end flag */
6030 i4_end_flag = ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_coarse_me_idx];
6031 i4_out_flush_flag =
6032 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx]->s_lap_out.i4_out_flush_flag;
6033
6034 /****** Lock the critical section for hme deinit ******/
6035 {
6036 WORD32 i4_status;
6037 i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_hme_deinit);
6038
6039 if(OSAL_SUCCESS != i4_status)
6040 return 0;
6041 }
6042
6043 /* last thread finishing pre_enc_process will update the flag indicating
6044 decomp and coarse ME is done. So that the next frame (next ping_pong instance)
6045 can start immediately after finishing current frame's IPE */
6046 if(1 == ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->i4_frm_proc_valid_flag)
6047 {
6048 ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx]++;
6049
6050 /* ------------------------------------------------------------ */
6051 /* Update qp used in based in L1 satd/act in case of scene cut */
6052 /* ------------------------------------------------------------ */
6053 {
6054 ihevce_lap_enc_buf_t *ps_curr_inp =
6055 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx];
6056
6057 if(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag)
6058 {
6059 WORD32 i4_prev_coarse_me_idx;
6060
6061 /* wrap around case */
6062 if(i4_cur_coarse_me_idx == 0)
6063 {
6064 i4_prev_coarse_me_idx = ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe - 1;
6065 }
6066 else
6067 {
6068 i4_prev_coarse_me_idx = i4_cur_coarse_me_idx - 1;
6069 }
6070
6071 ihevce_update_qp_L1_sad_based(
6072 ps_enc_ctxt,
6073 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx],
6074 ps_multi_thrd->aps_curr_inp_pre_enc[i4_prev_coarse_me_idx],
6075 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx],
6076 ((ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx] ==
6077 ps_multi_thrd->i4_num_pre_enc_proc_thrds)));
6078 }
6079 }
6080 /* check for last thread condition */
6081 if(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 ihevce_lap_enc_buf_t *ps_curr_inp =
6085 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx];
6086
6087 /* Frame END processing */
6088 ihevce_coarse_me_frame_end(ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt);
6089
6090 if(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag)
6091 {
6092 WORD32 i4_enable_noise_detection = 0;
6093 WORD32 i4_vqet = ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_vqet;
6094
6095 if(i4_vqet & (1 << BITPOS_IN_VQ_TOGGLE_FOR_CONTROL_TOGGLER))
6096 {
6097 if(i4_vqet & (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_NOISE_PRESERVATION))
6098 {
6099 i4_enable_noise_detection = 1;
6100 }
6101 }
6102
6103 if(1 != ((ps_curr_inp->s_lap_out.i4_pic_type == IV_B_FRAME) &&
6104 (ps_enc_ctxt->s_lap_stat_prms.ai4_quality_preset[i4_resolution_id] ==
6105 IHEVCE_QUALITY_P6)))
6106 {
6107 ihevce_decomp_pre_intra_curr_frame_pre_intra_deinit(
6108 ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt,
6109 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx],
6110 &ps_enc_ctxt->s_frm_ctb_prms);
6111 }
6112 }
6113
6114 ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_coarse_me_idx] = 1;
6115
6116 ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx] = 0;
6117
6118 /* get the layer 1 ctxt to be passed on to encode group */
6119 ihevce_coarse_me_get_lyr1_ctxt(
6120 ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
6121 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->pv_me_lyr_ctxt,
6122 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->pv_me_lyr_bnk_ctxt);
6123
6124 /* reset the init flag so that init happens by the first thread for the next frame
6125 of same ping_pong instance */
6126 ps_multi_thrd->ai4_pre_enc_hme_init_done[i4_cur_coarse_me_idx] = 0;
6127
6128 /* update the pre enc l1 done in dep manager */
6129 ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_coarse_me);
6130 }
6131
6132 i4_num_buf_prod_for_l0_ipe++;
6133
6134 /* index increment */
6135 i4_cur_coarse_me_idx = i4_cur_coarse_me_idx + 1;
6136
6137 /* wrap around case */
6138 if(i4_cur_coarse_me_idx >= ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe)
6139 {
6140 i4_cur_coarse_me_idx = 0;
6141 }
6142 }
6143 else
6144 {
6145 /* for invalid frame set the processed flag to 1 for L0 IPE */
6146 ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_coarse_me_idx] = 1;
6147
6148 if(1 == i4_out_flush_flag)
6149 {
6150 /* update the num thrds who have finished pre-enc processing */
6151 ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx]++;
6152
6153 if(ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx] ==
6154 ps_multi_thrd->i4_num_pre_enc_proc_thrds)
6155 {
6156 ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_coarse_me_idx] = 1;
6157
6158 /* reset num thread finished counter */
6159 ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx] = 0;
6160
6161 ps_multi_thrd->ai4_pre_enc_hme_init_done[i4_cur_coarse_me_idx] = 0;
6162
6163 /* update flag indicating coarse_me and decomp is done */
6164 ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_coarse_me);
6165 }
6166 }
6167
6168 i4_num_buf_prod_for_l0_ipe++;
6169
6170 /* index increment */
6171 i4_cur_coarse_me_idx = i4_cur_coarse_me_idx + 1;
6172
6173 /* wrap around case */
6174 if(i4_cur_coarse_me_idx >= ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe)
6175 {
6176 i4_cur_coarse_me_idx = 0;
6177 }
6178 }
6179
6180 /****** UnLock the critical section after hme deinit ******/
6181 {
6182 WORD32 i4_status;
6183 i4_status =
6184 osal_mutex_unlock(ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_hme_deinit);
6185
6186 if(OSAL_SUCCESS != i4_status)
6187 return 0;
6188 }
6189
6190 if(i4_thrd_id == 0)
6191 {
6192 PROFILE_STOP(&ps_hle_ctxt->profile_pre_enc_l1l2[i4_resolution_id], NULL);
6193 }
6194
6195 /* ----------------------------------------------------------- */
6196 /* IPE init and process */
6197 /* ----------------------------------------------------------- */
6198 if(i4_thrd_id == 0)
6199 {
6200 PROFILE_START(&ps_hle_ctxt->profile_pre_enc_l0ipe[i4_resolution_id]);
6201 }
6202 if(i4_num_buf_prod_for_l0_ipe >= ps_multi_thrd->i4_delay_pre_me_btw_l0_ipe || i4_end_flag ||
6203 i4_out_flush_flag)
6204 {
6205 do
6206 {
6207 /* Wait till previous frame(instance)'s IPE is processed */
6208 {
6209 ihevce_dmgr_chk_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_l0, i4_thrd_id);
6210 }
6211
6212 /* Wait till current frame(instance)'s L1 and below layers are processed */
6213 {
6214 volatile WORD32 *pi4_cur_l1_complete =
6215 &ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_ipe_idx];
6216
6217 while(1)
6218 {
6219 if(*pi4_cur_l1_complete)
6220 break;
6221 }
6222 }
6223
6224 /* ----------------------------------------------------------- */
6225 /* L0 IPE qp init */
6226 /* ----------------------------------------------------------- */
6227
6228 /****** Lock the critical section for init ******/
6229 {
6230 WORD32 i4_status;
6231 i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_l0_ipe_init);
6232
6233 if(OSAL_SUCCESS != i4_status)
6234 return 0;
6235 }
6236
6237 /* first thread that enters will calculate qp and write that to shared variable
6238 that will be accessed by other threads */
6239 if(ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx] == 0)
6240 {
6241 volatile WORD32 i4_is_qp_valid = -1;
6242 WORD32 i4_update_qp;
6243 WORD32 i4_cur_q_scale;
6244
6245 i4_cur_q_scale =
6246 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->i4_curr_frm_qp;
6247 i4_cur_q_scale = ps_enc_ctxt->s_rc_quant.pi4_qp_to_qscale[i4_cur_q_scale];
6248 i4_cur_q_scale = (i4_cur_q_scale + (1 << (QSCALE_Q_FAC_3 - 1))) >>
6249 QSCALE_Q_FAC_3;
6250 /* Get free buffer to store L0 IPE output to enc loop */
6251 ps_multi_thrd->ps_L0_IPE_curr_out_pre_enc =
6252 (pre_enc_L0_ipe_encloop_ctxt_t *)ihevce_q_get_free_buff(
6253 (void *)ps_enc_ctxt,
6254 IHEVCE_L0_IPE_ENC_Q,
6255 &ps_multi_thrd->i4_L0_IPE_out_buf_id,
6256 BUFF_QUE_BLOCKING_MODE);
6257 if(ps_enc_ctxt->ps_stat_prms->s_pass_prms.i4_pass != 2 &&
6258 ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode != 3)
6259 {
6260 complexity_RC_reset_marking(
6261 ps_enc_ctxt, i4_cur_ipe_idx, (i4_end_flag || i4_out_flush_flag));
6262 }
6263 if(1 == ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6264 ->s_input_buf.i4_inp_frm_data_valid_flag)
6265 {
6266 while(i4_is_qp_valid == -1)
6267 {
6268 /*this rate control call is outside mutex lock to avoid deadlock. If this acquires mutex lock enc will not be able to
6269 populate qp*/
6270 i4_is_qp_valid = ihevce_rc_check_is_pre_enc_qp_valid(
6271 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6272 (volatile WORD32 *)&ps_enc_ctxt->s_multi_thrd.i4_force_end_flag);
6273 if(1 == ps_enc_ctxt->s_multi_thrd.i4_force_end_flag)
6274 {
6275 /*** For force end condition break from this loop ***/
6276 i4_is_qp_valid = 1;
6277 break;
6278 }
6279 }
6280
6281 /*lock rate control context*/
6282 osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
6283
6284 /* Qp query has to happen irrespective of using it or not since producer consumer logic will be disturbed */
6285 i4_update_qp = ihevce_rc_pre_enc_qp_query(
6286 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6287 &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_rc_lap_out,
6288 0);
6289
6290 if(ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode != 3)
6291 {
6292 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6293 ->s_rc_lap_out.i8_frm_satd_act_accum_L0_frm_L1 =
6294 ihevce_get_L0_satd_based_on_L1(
6295 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6296 ->s_rc_lap_out.i8_frame_satd_by_act_L1_accum,
6297 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6298 ->s_rc_lap_out.i4_num_pels_in_frame_considered,
6299 i4_cur_q_scale);
6300
6301 if(ps_enc_ctxt->ps_stat_prms->s_pass_prms.i4_pass != 2)
6302 {
6303 if(ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6304 ->s_rc_lap_out.i4_rc_scene_type ==
6305 SCENE_TYPE_SCENE_CUT ||
6306 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6307 ->s_rc_lap_out.i4_is_I_only_scd ||
6308 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6309 ->s_rc_lap_out.i4_is_non_I_scd == 1)
6310 {
6311 float i_to_avg_rest_ratio;
6312 WORD32 i4_count = 0;
6313
6314 while(1)
6315 {
6316 i_to_avg_rest_ratio = ihevce_get_i_to_avg_ratio(
6317 ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6318 &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6319 ->s_rc_lap_out,
6320 1,
6321 0,
6322 0,
6323 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6324 ->s_rc_lap_out.ai4_offsets,
6325 0);
6326 /* HEVC_RC query rate control for qp */
6327 i4_update_qp = ihevce_get_L0_est_satd_based_scd_qp(
6328 ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6329 &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6330 ->s_rc_lap_out,
6331 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6332 ->s_rc_lap_out.i8_frm_satd_act_accum_L0_frm_L1,
6333 i_to_avg_rest_ratio);
6334
6335 ihevce_set_L0_scd_qp(
6336 ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6337 i4_update_qp);
6338
6339 if(ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6340 ->s_lap_out.i4_pic_type != IV_IDR_FRAME &&
6341 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6342 ->s_lap_out.i4_pic_type != IV_I_FRAME)
6343 {
6344 i4_update_qp +=
6345 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6346 ->s_lap_out.i4_temporal_lyr_id +
6347 1;
6348
6349 i4_update_qp =
6350 CLIP3(i4_update_qp, MIN_HEVC_QP, MAX_HEVC_QP);
6351 }
6352
6353 i4_count++;
6354 if((i4_update_qp ==
6355 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6356 ->s_rc_lap_out.i4_L0_qp) ||
6357 i4_count > 4)
6358 break;
6359
6360 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6361 ->s_rc_lap_out.i4_L0_qp = i4_update_qp;
6362 }
6363 }
6364 }
6365 else
6366 {
6367 //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);
6368 i4_update_qp = ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6369 ->s_rc_lap_out.ps_frame_info->i4_rc_hevc_qp;
6370 }
6371 }
6372
6373 {
6374 WORD32 i4_index = 0;
6375 rc_lap_out_params_t *ps_rc_lap_temp =
6376 &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_rc_lap_out;
6377 WORD32 i4_offset;
6378
6379 if(ps_rc_lap_temp->i4_rc_pic_type != IV_IDR_FRAME &&
6380 ps_rc_lap_temp->i4_rc_pic_type != IV_I_FRAME)
6381 {
6382 i4_index = ps_rc_lap_temp->i4_rc_temporal_lyr_id + 1;
6383 }
6384 i4_offset = ps_rc_lap_temp->ai4_offsets[i4_index];
6385 ASSERT(i4_offset >= 0);
6386 /* Map the current frame Qp to L0 Qp */
6387 ps_rc_lap_temp->i4_L0_qp = i4_update_qp - i4_offset;
6388 }
6389 osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
6390 ASSERT(ps_multi_thrd->i4_qp_update_l0_ipe == -1);
6391 ps_multi_thrd->i4_qp_update_l0_ipe = i4_update_qp;
6392 ps_multi_thrd->i4_rc_l0_qp = i4_update_qp;
6393 }
6394 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6395 ->s_lap_out.f_i_pic_lamda_modifier = CONST_LAMDA_MOD_VAL;
6396 }
6397 /* update qp only if it is not scene cut since it has already been
6398 populated in L1 for scene cut frames */
6399 if(1 == ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6400 ->s_input_buf.i4_inp_frm_data_valid_flag &&
6401 ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode != 3)
6402 {
6403 /*get relevant lambda params*/
6404 ihevce_get_frame_lambda_prms(
6405 ps_enc_ctxt,
6406 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx],
6407 ps_multi_thrd->i4_qp_update_l0_ipe,
6408 ps_enc_ctxt->s_runtime_src_prms.i4_field_pic,
6409 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_lap_out.i4_is_ref_pic,
6410 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6411 ->s_lap_out.i4_temporal_lyr_id,
6412 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6413 ->s_lap_out.f_i_pic_lamda_modifier,
6414 0,
6415 PRE_ENC_LAMBDA_TYPE);
6416
6417 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->i4_curr_frm_qp =
6418 ps_multi_thrd->i4_qp_update_l0_ipe;
6419 }
6420 /* Compute accumulated activity and strength */
6421 if(1 == ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6422 ->s_input_buf.i4_inp_frm_data_valid_flag &&
6423 ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx] == 0)
6424 {
6425 ihevce_variance_calc_acc_activity(ps_enc_ctxt, i4_cur_ipe_idx);
6426 }
6427
6428 /* Mark qp as read by last thread */
6429 ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx]++;
6430 if(ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx] ==
6431 ps_multi_thrd->i4_num_pre_enc_proc_thrds)
6432 {
6433 ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx] = 0;
6434 ps_multi_thrd->i4_qp_update_l0_ipe = -1;
6435 }
6436
6437 /****** UnLock the critical section after deinit ******/
6438 {
6439 WORD32 i4_status;
6440 i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_l0_ipe_init);
6441
6442 if(OSAL_SUCCESS != i4_status)
6443 return 0;
6444 }
6445
6446 if(1 == ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6447 ->s_input_buf.i4_inp_frm_data_valid_flag)
6448 {
6449 WORD32 i4_slice_type =
6450 (WORD32)ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]
6451 ->s_slice_hdr.i1_slice_type;
6452 WORD32 i4_quality_preset =
6453 (WORD32)ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6454 ->s_lap_out.i4_quality_preset;
6455 WORD32 i4_temporal_layer_id =
6456 (WORD32)ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6457 ->s_lap_out.i4_temporal_lyr_id;
6458 #if DISABLE_L0_IPE_INTRA_IN_BPICS
6459 if(1 != ((i4_quality_preset == IHEVCE_QUALITY_P6) &&
6460 (i4_temporal_layer_id > TEMPORAL_LAYER_DISABLE)))
6461 #endif
6462 {
6463 UWORD8 i1_cu_qp_delta_enabled_flag =
6464 ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_cu_level_rc;
6465
6466 ihevce_populate_ipe_frame_init(
6467 ps_enc_ctxt->s_module_ctxt.pv_ipe_ctxt,
6468 ps_enc_ctxt->ps_stat_prms,
6469 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->i4_curr_frm_qp,
6470 i4_slice_type,
6471 i4_thrd_id,
6472 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx],
6473 i1_cu_qp_delta_enabled_flag,
6474 &ps_enc_ctxt->s_rc_quant,
6475 i4_quality_preset,
6476 i4_temporal_layer_id,
6477 &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_lap_out);
6478
6479 ihevce_ipe_process(
6480 ps_enc_ctxt->s_module_ctxt.pv_ipe_ctxt,
6481 &ps_enc_ctxt->s_frm_ctb_prms,
6482 &ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->as_lambda_prms[0],
6483 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx],
6484 ps_multi_thrd->ps_L0_IPE_curr_out_pre_enc,
6485 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->ps_ctb_analyse,
6486 ps_multi_thrd->ps_L0_IPE_curr_out_pre_enc->ps_ipe_analyse_ctb,
6487 &ps_enc_ctxt->s_multi_thrd,
6488 i4_slice_type,
6489 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->ps_layer1_buf,
6490 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->ps_layer2_buf,
6491 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->ps_ed_ctb_l1,
6492 i4_thrd_id,
6493 i4_cur_ipe_idx);
6494 }
6495 }
6496
6497 /* ----------------------------------------------------------- */
6498 /* pre-enc de-init */
6499 /* ----------------------------------------------------------- */
6500
6501 /****** Lock the critical section for deinit ******/
6502 {
6503 WORD32 i4_status;
6504 i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_deinit);
6505
6506 if(OSAL_SUCCESS != i4_status)
6507 return 0;
6508 }
6509
6510 ps_multi_thrd->ai4_num_thrds_processed_pre_enc[i4_cur_ipe_idx]++;
6511 if(ps_multi_thrd->ai4_num_thrds_processed_pre_enc[i4_cur_ipe_idx] ==
6512 ps_multi_thrd->i4_num_pre_enc_proc_thrds)
6513 {
6514 ps_multi_thrd->ai4_pre_enc_deinit_done[i4_cur_ipe_idx] = 0;
6515 ps_multi_thrd->ai4_num_thrds_processed_pre_enc[i4_cur_ipe_idx] = 0;
6516
6517 /* reset the init flag so that init happens by the first thread for the
6518 next frame of same ping_pnog instnace */
6519 ps_multi_thrd->ai4_pre_enc_init_done[i4_cur_ipe_idx] = 0;
6520 }
6521
6522 /* de-init */
6523 if(0 == ps_multi_thrd->ai4_pre_enc_deinit_done[i4_cur_ipe_idx])
6524 {
6525 ihevce_lap_enc_buf_t *ps_curr_inp =
6526 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx];
6527 pre_enc_me_ctxt_t *ps_curr_out =
6528 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx];
6529
6530 /* set the flag saying de init is done so that other cores dont do it */
6531 ps_multi_thrd->ai4_pre_enc_deinit_done[i4_cur_ipe_idx] = 1;
6532
6533 if(1 == ps_curr_out->i4_frm_proc_valid_flag)
6534 {
6535 LWORD64 frame_acc_satd_by_modqp;
6536 float L1_full_processed_ratio;
6537
6538 if(ps_curr_inp->s_rc_lap_out.i8_satd_by_act_L1_accum_evaluated)
6539 {
6540 L1_full_processed_ratio =
6541 ((float)ps_curr_inp->s_rc_lap_out.i8_frame_satd_by_act_L1_accum /
6542 ps_curr_inp->s_rc_lap_out.i8_satd_by_act_L1_accum_evaluated);
6543 }
6544 else
6545 {
6546 L1_full_processed_ratio = 1.0;
6547 }
6548 /* Get frame-level satd cost and mode bit cost from IPE */
6549 ps_curr_out->i8_frame_acc_satd_cost = ihevce_ipe_get_frame_intra_satd_cost(
6550 ps_enc_ctxt->s_module_ctxt.pv_ipe_ctxt,
6551 &frame_acc_satd_by_modqp,
6552 &ps_curr_inp->s_rc_lap_out.i8_est_I_pic_header_bits,
6553 &ps_curr_inp->s_lap_out.i8_frame_level_activity_fact,
6554 &ps_curr_inp->s_lap_out.i8_frame_l0_acc_satd);
6555
6556 if((ps_curr_inp->s_lap_out.i4_quality_preset == IHEVCE_QUALITY_P6) &&
6557 (ps_curr_inp->s_lap_out.i4_temporal_lyr_id > TEMPORAL_LAYER_DISABLE))
6558 {
6559 ps_curr_inp->s_rc_lap_out.i8_est_I_pic_header_bits = -1;
6560 }
6561
6562 {
6563 WORD32 i4_cur_q_scale = (ps_enc_ctxt->s_rc_quant.pi4_qp_to_qscale
6564 [ps_enc_ctxt->s_multi_thrd.i4_rc_l0_qp +
6565 ps_enc_ctxt->s_rc_quant.i1_qp_offset] +
6566 (1 << (QSCALE_Q_FAC_3 - 1))) >>
6567 QSCALE_Q_FAC_3;
6568
6569 /* calculate satd/act_fac = satd/qm * (qp_used_at_L0_analysis) */
6570 ps_curr_inp->s_rc_lap_out.i8_frame_satd_act_accum =
6571 frame_acc_satd_by_modqp * i4_cur_q_scale;
6572 }
6573
6574 /* Because of early intra inter decision, L0 intra analysis might not happen for entire frame, correct the error
6575 based on L1 data */
6576 ps_curr_inp->s_rc_lap_out.i8_est_I_pic_header_bits = (LWORD64)(
6577 ps_curr_inp->s_rc_lap_out.i8_est_I_pic_header_bits *
6578 L1_full_processed_ratio);
6579
6580 if(L1_full_processed_ratio < 1.5)
6581 {
6582 ps_curr_inp->s_rc_lap_out.i8_frame_satd_act_accum = (LWORD64)(
6583 ps_curr_inp->s_rc_lap_out.i8_frame_satd_act_accum *
6584 L1_full_processed_ratio);
6585 }
6586 else
6587 {
6588 /* This is the case when too many candidates would not have gone through intra analysis, scaling based on L1 is found to be inappropriate,
6589 Hence directly estimating L0 satd from L1 satd */
6590 ps_curr_inp->s_rc_lap_out.i8_frame_satd_act_accum =
6591 ps_curr_inp->s_rc_lap_out.i8_frm_satd_act_accum_L0_frm_L1;
6592 }
6593 }
6594
6595 /* register the current input buffer to be cnosumed by encode group threads */
6596 ps_curr_out->curr_inp_buf_id =
6597 ps_multi_thrd->ai4_in_buf_id_pre_enc[i4_cur_ipe_idx];
6598 ps_curr_out->ps_curr_inp = ps_curr_inp;
6599
6600 /* set the output buffer as produced */
6601 ihevce_q_set_buff_prod(
6602 (void *)ps_enc_ctxt,
6603 IHEVCE_PRE_ENC_ME_Q,
6604 ps_multi_thrd->ai4_out_buf_id_pre_enc[i4_cur_ipe_idx]);
6605
6606 /* set the output buffer of L0 IPE as produced */
6607 ihevce_q_set_buff_prod(
6608 (void *)ps_enc_ctxt,
6609 IHEVCE_L0_IPE_ENC_Q,
6610 ps_multi_thrd->i4_L0_IPE_out_buf_id);
6611
6612 /* update flag indicating ipe is done */
6613 ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_l0);
6614 }
6615
6616 {
6617 /* index increment */
6618 i4_cur_ipe_idx = i4_cur_ipe_idx + 1;
6619
6620 /* wrap around case */
6621 if(i4_cur_ipe_idx >= ps_multi_thrd->i4_max_delay_pre_me_btw_l0_ipe)
6622 {
6623 i4_cur_ipe_idx = 0;
6624 }
6625
6626 i4_num_buf_prod_for_l0_ipe--;
6627 }
6628 /*NOTE: update of above indices should mark end if ipe.do not access below this*/
6629
6630 /****** UnLock the critical section after deinit ******/
6631 {
6632 WORD32 i4_status;
6633 i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_pre_enc_deinit);
6634
6635 if(OSAL_SUCCESS != i4_status)
6636 return 0;
6637 }
6638
6639 if(1 == ps_multi_thrd->i4_force_end_flag)
6640 {
6641 i4_end_flag = 1;
6642 break;
6643 }
6644 } while((i4_end_flag || i4_out_flush_flag) && i4_num_buf_prod_for_l0_ipe);
6645 }
6646 if(i4_thrd_id == 0)
6647 {
6648 PROFILE_STOP(&ps_hle_ctxt->profile_pre_enc_l0ipe[i4_resolution_id], NULL);
6649 }
6650 }
6651
6652 return 0;
6653 }
6654
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)6655 void calc_l1_level_hme_intra_sad_different_qp(
6656 enc_ctxt_t *ps_enc_ctxt,
6657 pre_enc_me_ctxt_t *ps_curr_out,
6658 ihevce_lap_enc_buf_t *ps_curr_inp,
6659 WORD32 i4_tot_ctb_l1_x,
6660 WORD32 i4_tot_ctb_l1_y)
6661 {
6662 ihevce_ed_ctb_l1_t *ps_ed_ctb_l1;
6663 WORD32 i4_qp_counter, i4_qp_start = 0, i4_qp_end = 0, i, i4_j, i4_new_frame_qp;
6664 LWORD64 i8_l1_intra_sad_nc_accounted = 0, cur_intra_sad, raw_hme_sad = 0;
6665 LWORD64 cur_hme_sad = 0, cur_hme_sad_for_offset = 0, acc_hme_l1_sad = 0,
6666 acc_hme_l1_sad_for_offset = 0;
6667 i4_qp_start = 1;
6668 i4_qp_end = 51;
6669
6670 for(i4_qp_counter = i4_qp_start; i4_qp_counter <= i4_qp_end; i4_qp_counter = i4_qp_counter + 3)
6671 {
6672 i8_l1_intra_sad_nc_accounted = 0;
6673 cur_intra_sad = 0;
6674 raw_hme_sad = 0;
6675 cur_hme_sad = 0;
6676 cur_hme_sad_for_offset = 0;
6677 acc_hme_l1_sad = 0;
6678 ps_ed_ctb_l1 = ps_curr_out->ps_ed_ctb_l1;
6679 i4_new_frame_qp = i4_qp_counter;
6680 acc_hme_l1_sad = 0;
6681
6682 for(i = 0; i < (i4_tot_ctb_l1_x * i4_tot_ctb_l1_y); i += 1)
6683 {
6684 for(i4_j = 0; i4_j < 16; i4_j++)
6685 {
6686 if(ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j] != -1)
6687 {
6688 ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j] >= 0);
6689 if(ps_curr_inp->s_rc_lap_out.i4_rc_pic_type != IV_I_FRAME &&
6690 ps_curr_inp->s_rc_lap_out.i4_rc_pic_type != IV_IDR_FRAME)
6691 {
6692 /*When l1 is disabled for B pics i4_best_sad_8x8_l1_ipe is set to max value always,
6693 so will enter this path even for incomplete ctb, hence the assert holdsto good only for P pic */
6694 if(ps_curr_inp->s_rc_lap_out.i4_rc_quality_preset == IHEVCE_QUALITY_P6)
6695 {
6696 if(ps_curr_inp->s_rc_lap_out.i4_rc_pic_type == IV_P_FRAME)
6697 {
6698 ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j] >= 0);
6699 ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_me_for_decide[i4_j] >= 0);
6700 }
6701 }
6702 else
6703 {
6704 ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j] >= 0);
6705 ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_me_for_decide[i4_j] >= 0);
6706 }
6707
6708 #if 1 //DISABLE_L1_L2_IPE_INTRA_IN_BPICS && RC_DEPENDENCY_FOR_BPIC
6709 if((ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j] != -1))
6710 #endif
6711 {
6712 cur_hme_sad = ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j] -
6713 (QP2QUANT_MD[i4_new_frame_qp] << 3);
6714 }
6715 raw_hme_sad += ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j];
6716
6717 if(cur_hme_sad > 0)
6718 acc_hme_l1_sad += cur_hme_sad;
6719 }
6720 if(cur_hme_sad_for_offset > 0)
6721 {
6722 acc_hme_l1_sad_for_offset += cur_hme_sad_for_offset;
6723 }
6724 ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j] >= 0);
6725 /*intra sad is scaled by 1.17 to be account for 1/3 vs 1/6th rounding*/
6726 cur_intra_sad = (LWORD64)(
6727 (ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j] * 1.17) -
6728 (QP2QUANT_MD[i4_new_frame_qp] << 3));
6729
6730 if(cur_intra_sad > 0)
6731 i8_l1_intra_sad_nc_accounted += cur_intra_sad;
6732 }
6733 }
6734 ps_ed_ctb_l1 += 1;
6735 }
6736 if((ps_curr_inp->s_rc_lap_out.i4_rc_quality_preset == IHEVCE_QUALITY_P6) &&
6737 (ps_curr_inp->s_rc_lap_out.i4_rc_pic_type == IV_B_FRAME))
6738 {
6739 ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter] = -1;
6740 ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter + 1] = -1;
6741 ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter + 2] = -1;
6742 }
6743 else
6744 {
6745 ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter] =
6746 i8_l1_intra_sad_nc_accounted;
6747 ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter + 1] =
6748 i8_l1_intra_sad_nc_accounted;
6749 ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter + 2] =
6750 i8_l1_intra_sad_nc_accounted;
6751 }
6752 ps_curr_inp->s_rc_lap_out.ai8_frame_acc_coarse_me_sad[i4_qp_counter] = acc_hme_l1_sad;
6753 ps_curr_inp->s_rc_lap_out.ai8_frame_acc_coarse_me_sad[i4_qp_counter + 1] = acc_hme_l1_sad;
6754 ps_curr_inp->s_rc_lap_out.ai8_frame_acc_coarse_me_sad[i4_qp_counter + 2] = acc_hme_l1_sad;
6755 ps_curr_inp->s_rc_lap_out.i8_raw_l1_coarse_me_sad = raw_hme_sad;
6756 }
6757 }
6758