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