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_me_pass.c 24 * 25 * \brief 26 * Converts the language of the encoder to language of me. This is an i/f 27 * between the encoder style APIs and ME style APIs. This is basically 28 * a memoryless glue layer. 29 * 30 * \date 31 * 22/10/2012 32 * 33 * \author 34 * Ittiam 35 * 36 * 37 * List of Functions 38 * 39 * 40 ****************************************************************************** 41 */ 42 43 /*****************************************************************************/ 44 /* File Includes */ 45 /*****************************************************************************/ 46 /* System include files */ 47 #include <stdio.h> 48 #include <string.h> 49 #include <stdlib.h> 50 #include <assert.h> 51 #include <stdarg.h> 52 #include <math.h> 53 54 /* User include files */ 55 #include "ihevc_typedefs.h" 56 #include "itt_video_api.h" 57 #include "ihevce_api.h" 58 59 #include "rc_cntrl_param.h" 60 #include "rc_frame_info_collector.h" 61 #include "rc_look_ahead_params.h" 62 63 #include "ihevc_debug.h" 64 #include "ihevc_defs.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 81 #include "ihevce_defs.h" 82 #include "ihevce_lap_enc_structs.h" 83 #include "ihevce_multi_thrd_structs.h" 84 #include "ihevce_me_common_defs.h" 85 #include "ihevce_had_satd.h" 86 #include "ihevce_error_codes.h" 87 #include "ihevce_bitstream.h" 88 #include "ihevce_cabac.h" 89 #include "ihevce_rdoq_macros.h" 90 #include "ihevce_function_selector.h" 91 #include "ihevce_enc_structs.h" 92 #include "ihevce_entropy_structs.h" 93 #include "ihevce_cmn_utils_instr_set_router.h" 94 #include "ihevce_enc_loop_structs.h" 95 #include "ihevce_inter_pred.h" 96 97 #include "hme_datatype.h" 98 #include "hme_interface.h" 99 #include "hme_common_defs.h" 100 #include "hme_defs.h" 101 #include "ihevce_me_instr_set_router.h" 102 #include "hme_utils.h" 103 #include "hme_coarse.h" 104 #include "hme_refine.h" 105 #include "hme_function_selector.h" 106 #include "ihevce_me_pass.h" 107 108 #include "cast_types.h" 109 #include "osal.h" 110 #include "osal_defaults.h" 111 112 /*****************************************************************************/ 113 /* Macros */ 114 /*****************************************************************************/ 115 116 /** orig simple five tap scaler */ 117 #define FIVE_TAP_ORIG_SCALER 0 118 119 /** simple gaussian filter, blurs the image a bit */ 120 #define SIMPLE_GAUSSIAN_SCALER 0 121 122 /** lanczos scaler gives sharper images */ 123 #define LANCZOS_SCALER 1 124 125 // Saturated addition z = x + y 126 // overflow condition: z<x or z<y 127 #define SATURATED_ADD(z, x, y) \ 128 { \ 129 (z) = (x) + (y); \ 130 if(((z) < (x)) || ((z) < (y))) \ 131 (z) = MAX_INTRA_COST_IPE; \ 132 } 133 134 #define SATURATED_SUB(z, x, y) \ 135 { \ 136 (z) = (x) - (y); \ 137 if((z) < 0) /*if (((z) > (x)) || ((z) > (y))) */ \ 138 (z) = 0; \ 139 } 140 141 #if(FIVE_TAP_ORIG_SCALER + SIMPLE_GAUSSIAN_SCALER + LANCZOS_SCALER) > 1 142 #error "HME ERROR: Only one scaler can be enabled at a time" 143 #endif 144 145 /*****************************************************************************/ 146 /* Function Definitions */ 147 /*****************************************************************************/ 148 149 /*! 150 ****************************************************************************** 151 * \if Function name : ihevce_me_get_num_mem_recs \endif 152 * 153 * \brief 154 * Number of memory records are returned for ME module 155 * Note : Include TOT MEM. req. for ME + TOT MEM. req. for Dep Mngr for L0 ME 156 * 157 * \return 158 * Number of memory records 159 * 160 * \author 161 * Ittiam 162 * 163 ***************************************************************************** 164 */ 165 WORD32 ihevce_me_get_num_mem_recs(WORD32 i4_num_me_frm_pllel) 166 { 167 WORD32 me_mem_recs = hme_enc_num_alloc(i4_num_me_frm_pllel); 168 169 return (me_mem_recs); 170 } 171 172 void ihevce_derive_me_init_prms( 173 ihevce_static_cfg_params_t *ps_init_prms, 174 hme_init_prms_t *ps_hme_init_prms, 175 S32 i4_num_proc_thrds, 176 S32 i4_resolution_id) 177 { 178 WORD32 i4_field_pic = ps_init_prms->s_src_prms.i4_field_pic; 179 WORD32 min_cu_size; 180 181 /* max number of ref frames. This should be > ref frms sent any frm */ 182 ps_hme_init_prms->max_num_ref = ((DEFAULT_MAX_REFERENCE_PICS) << i4_field_pic); 183 184 /* get the min cu size from config params */ 185 min_cu_size = ps_init_prms->s_config_prms.i4_min_log2_cu_size; 186 187 min_cu_size = 1 << min_cu_size; 188 189 /* Width and height for the layer being encoded */ 190 ps_hme_init_prms->a_wd[0] = 191 ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width + 192 SET_CTB_ALIGN( 193 ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width, min_cu_size); 194 195 ps_hme_init_prms->a_ht[0] = 196 ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height + 197 SET_CTB_ALIGN( 198 ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height, min_cu_size); 199 200 /* we store 4 results in coarsest layer per blk. 8x4L, 8x4R, 4x8T, 4x8B */ 201 ps_hme_init_prms->max_num_results_coarse = 4; 202 203 /* Every refinement layer stores a max of 2 results per partition */ 204 ps_hme_init_prms->max_num_results = 2; 205 206 /* Assuming abt 4 layers for 1080p, we do explicit search across all ref */ 207 /* frames in all but final layer In final layer, it could be 1/2 */ 208 ps_hme_init_prms->num_layers_explicit_search = 3; 209 210 /* Populate the max_tr_depth for Inter */ 211 ps_hme_init_prms->u1_max_tr_depth = ps_init_prms->s_config_prms.i4_max_tr_tree_depth_nI; 212 213 ps_hme_init_prms->log_ctb_size = ps_init_prms->s_config_prms.i4_max_log2_cu_size; 214 ASSERT(ps_hme_init_prms->log_ctb_size == 6); 215 216 /* currently encoding only 1 layer */ 217 ps_hme_init_prms->num_simulcast_layers = 1; 218 219 /* this feature not yet supported */ 220 ps_hme_init_prms->segment_higher_layers = 0; 221 222 /* Allow 4x4 in refinement layers. Unconditionally enabled in coarse lyr */ 223 /* And not enabled in encode layers, this is just for intermediate refine*/ 224 /* layers, where it could be used for better accuracy of motion. */ 225 226 #if !OLD_XTREME_SPEED 227 if((IHEVCE_QUALITY_P6 == 228 ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_quality_preset) || 229 (IHEVCE_QUALITY_P7 == 230 ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_quality_preset) || 231 (IHEVCE_QUALITY_P5 == 232 ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_quality_preset) || 233 (IHEVCE_QUALITY_P4 == 234 ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_quality_preset)) 235 ps_hme_init_prms->use_4x4 = 0; 236 else 237 ps_hme_init_prms->use_4x4 = 1; 238 #else 239 ps_hme_init_prms->use_4x4 = 1; 240 #endif 241 242 ps_hme_init_prms->num_b_frms = 243 (1 << ps_init_prms->s_coding_tools_prms.i4_max_temporal_layers) - 1; 244 245 ps_hme_init_prms->i4_num_proc_thrds = i4_num_proc_thrds; 246 247 if(IHEVCE_QUALITY_P0 == 248 ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_quality_preset) 249 { 250 ps_hme_init_prms->s_me_coding_tools.e_me_quality_presets = ME_PRISTINE_QUALITY; 251 ps_hme_init_prms->s_me_coding_tools.i4_num_steps_hpel_refine = 3; 252 ps_hme_init_prms->s_me_coding_tools.i4_num_steps_qpel_refine = 3; 253 } 254 else if( 255 IHEVCE_QUALITY_P2 == 256 ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_quality_preset) 257 { 258 ps_hme_init_prms->s_me_coding_tools.e_me_quality_presets = ME_HIGH_QUALITY; 259 ps_hme_init_prms->s_me_coding_tools.i4_num_steps_hpel_refine = 3; 260 ps_hme_init_prms->s_me_coding_tools.i4_num_steps_qpel_refine = 3; 261 } 262 else if( 263 IHEVCE_QUALITY_P3 == 264 ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_quality_preset) 265 { 266 ps_hme_init_prms->s_me_coding_tools.e_me_quality_presets = ME_MEDIUM_SPEED; 267 ps_hme_init_prms->s_me_coding_tools.i4_num_steps_hpel_refine = 2; 268 ps_hme_init_prms->s_me_coding_tools.i4_num_steps_qpel_refine = 2; 269 } 270 else if( 271 IHEVCE_QUALITY_P4 == 272 ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_quality_preset) 273 { 274 ps_hme_init_prms->s_me_coding_tools.e_me_quality_presets = ME_HIGH_SPEED; 275 ps_hme_init_prms->s_me_coding_tools.i4_num_steps_hpel_refine = 1; 276 ps_hme_init_prms->s_me_coding_tools.i4_num_steps_qpel_refine = 1; 277 } 278 else if( 279 IHEVCE_QUALITY_P5 == 280 ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_quality_preset) 281 { 282 ps_hme_init_prms->s_me_coding_tools.e_me_quality_presets = ME_XTREME_SPEED; 283 ps_hme_init_prms->s_me_coding_tools.i4_num_steps_hpel_refine = 1; 284 ps_hme_init_prms->s_me_coding_tools.i4_num_steps_qpel_refine = 1; 285 } 286 else if( 287 IHEVCE_QUALITY_P6 == 288 ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_quality_preset) 289 { 290 ps_hme_init_prms->s_me_coding_tools.e_me_quality_presets = ME_XTREME_SPEED_25; 291 ps_hme_init_prms->s_me_coding_tools.i4_num_steps_hpel_refine = 1; 292 ps_hme_init_prms->s_me_coding_tools.i4_num_steps_qpel_refine = 1; 293 } 294 else if( 295 IHEVCE_QUALITY_P7 == 296 ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_quality_preset) 297 { 298 ps_hme_init_prms->s_me_coding_tools.e_me_quality_presets = ME_XTREME_SPEED_25; 299 ps_hme_init_prms->s_me_coding_tools.i4_num_steps_hpel_refine = 1; 300 ps_hme_init_prms->s_me_coding_tools.i4_num_steps_qpel_refine = 0; 301 } 302 303 ps_hme_init_prms->s_me_coding_tools.u1_l0_me_controlled_via_cmd_line = 0; 304 305 /* Register the search range params from static params */ 306 ps_hme_init_prms->max_horz_search_range = ps_init_prms->s_config_prms.i4_max_search_range_horz; 307 ps_hme_init_prms->max_vert_search_range = ps_init_prms->s_config_prms.i4_max_search_range_vert; 308 ps_hme_init_prms->e_arch_type = ps_init_prms->e_arch_type; 309 ps_hme_init_prms->is_interlaced = (ps_init_prms->s_src_prms.i4_field_pic == IV_INTERLACED); 310 311 ps_hme_init_prms->u1_is_stasino_enabled = 312 ((ps_init_prms->s_coding_tools_prms.i4_vqet & 313 (1 << BITPOS_IN_VQ_TOGGLE_FOR_CONTROL_TOGGLER)) && 314 (ps_init_prms->s_coding_tools_prms.i4_vqet & 315 (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_NOISE_PRESERVATION))); 316 } 317 318 /*! 319 ****************************************************************************** 320 * \if Function name : ihevce_me_get_mem_recs \endif 321 * 322 * \brief 323 * Memory requirements are returned for ME. 324 * 325 * \param[in,out] ps_mem_tab : pointer to memory descriptors table 326 * \param[in] ps_init_prms : Create time static parameters 327 * \param[in] i4_num_proc_thrds : Number of processing threads for this module 328 * \param[in] i4_mem_space : memspace in whihc memory request should be done 329 * 330 * \return 331 * Number of records 332 * 333 * \author 334 * Ittiam 335 * 336 ***************************************************************************** 337 */ 338 WORD32 ihevce_me_get_mem_recs( 339 iv_mem_rec_t *ps_mem_tab, 340 ihevce_static_cfg_params_t *ps_init_prms, 341 WORD32 i4_num_proc_thrds, 342 WORD32 i4_mem_space, 343 WORD32 i4_resolution_id, 344 WORD32 i4_num_me_frm_pllel) 345 { 346 hme_memtab_t as_memtabs[MAX_HME_ENC_TOT_MEMTABS]; 347 WORD32 n_tabs, i; 348 349 /* Init prms structure specific to HME */ 350 hme_init_prms_t s_hme_init_prms; 351 352 /*************************************************************************/ 353 /* code flow: we call hme alloc function and then remap those memtabs */ 354 /* to a different type of memtab structure. */ 355 /*************************************************************************/ 356 if(i4_num_me_frm_pllel > 1) 357 { 358 ASSERT(MAX_HME_ENC_TOT_MEMTABS >= hme_enc_num_alloc(i4_num_me_frm_pllel)); 359 } 360 else 361 { 362 ASSERT(MIN_HME_ENC_TOT_MEMTABS >= hme_enc_num_alloc(i4_num_me_frm_pllel)); 363 } 364 365 /*************************************************************************/ 366 /* POPULATE THE HME INIT PRMS */ 367 /*************************************************************************/ 368 ihevce_derive_me_init_prms(ps_init_prms, &s_hme_init_prms, i4_num_proc_thrds, i4_resolution_id); 369 370 /*************************************************************************/ 371 /* CALL THE ME FUNCTION TO GET MEMTABS */ 372 /*************************************************************************/ 373 n_tabs = hme_enc_alloc(&as_memtabs[0], &s_hme_init_prms, i4_num_me_frm_pllel); 374 ASSERT(n_tabs == hme_enc_num_alloc(i4_num_me_frm_pllel)); 375 376 /*************************************************************************/ 377 /* REMAP RESULTS TO ENCODER MEMTAB STRUCTURE */ 378 /*************************************************************************/ 379 for(i = 0; i < n_tabs; i++) 380 { 381 ps_mem_tab[i].i4_mem_size = as_memtabs[i].size; 382 ps_mem_tab[i].i4_mem_alignment = as_memtabs[i].align; 383 ps_mem_tab[i].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space; 384 ps_mem_tab[i].i4_size = sizeof(iv_mem_rec_t); 385 } 386 387 /*************************************************************************/ 388 /* --- L0 ME sync Dep Mngr Mem requests -- */ 389 /*************************************************************************/ 390 ps_mem_tab += n_tabs; 391 392 return (n_tabs); 393 } 394 395 /*! 396 ****************************************************************************** 397 * \if Function name : ihevce_me_init \endif 398 * 399 * \brief 400 * Intialization for ME context state structure . 401 * 402 * \param[in] ps_mem_tab : pointer to memory descriptors table 403 * \param[in] ps_init_prms : Create time static parameters 404 * \param[in] pv_osal_handle : Osal handle 405 * 406 * \return 407 * Handle to the ME context 408 * 409 * \author 410 * Ittiam 411 * 412 ***************************************************************************** 413 */ 414 void *ihevce_me_init( 415 iv_mem_rec_t *ps_mem_tab, 416 ihevce_static_cfg_params_t *ps_init_prms, 417 WORD32 i4_num_proc_thrds, 418 void *pv_osal_handle, 419 rc_quant_t *ps_rc_quant_ctxt, 420 void *pv_tile_params_base, 421 WORD32 i4_resolution_id, 422 WORD32 i4_num_me_frm_pllel, 423 UWORD8 u1_is_popcnt_available) 424 { 425 /* ME handle to be returned */ 426 void *pv_me_ctxt; 427 WORD32 status; 428 me_master_ctxt_t *ps_me_ctxt; 429 IV_ARCH_T e_arch_type; 430 431 /* Init prms structure specific to HME */ 432 hme_init_prms_t s_hme_init_prms; 433 434 /* memtabs to be passed to hme */ 435 hme_memtab_t as_memtabs[MAX_HME_ENC_TOT_MEMTABS]; 436 WORD32 n_tabs, i; 437 438 /*************************************************************************/ 439 /* POPULATE THE HME INIT PRMS */ 440 /*************************************************************************/ 441 ihevce_derive_me_init_prms(ps_init_prms, &s_hme_init_prms, i4_num_proc_thrds, i4_resolution_id); 442 443 /*************************************************************************/ 444 /* Ensure local declaration is sufficient */ 445 /*************************************************************************/ 446 n_tabs = hme_enc_num_alloc(i4_num_me_frm_pllel); 447 448 if(i4_num_me_frm_pllel > 1) 449 { 450 ASSERT(MAX_HME_ENC_TOT_MEMTABS >= n_tabs); 451 } 452 else 453 { 454 ASSERT(MIN_HME_ENC_TOT_MEMTABS >= n_tabs); 455 } 456 457 /*************************************************************************/ 458 /* MAP RESULTS TO HME MEMTAB STRUCTURE */ 459 /*************************************************************************/ 460 for(i = 0; i < n_tabs; i++) 461 { 462 as_memtabs[i].size = ps_mem_tab[i].i4_mem_size; 463 as_memtabs[i].align = ps_mem_tab[i].i4_mem_alignment; 464 as_memtabs[i].pu1_mem = (U08 *)ps_mem_tab[i].pv_base; 465 } 466 /*************************************************************************/ 467 /* CALL THE ME FUNCTION TO GET MEMTABS */ 468 /*************************************************************************/ 469 pv_me_ctxt = (void *)as_memtabs[0].pu1_mem; 470 ps_me_ctxt = (me_master_ctxt_t *)pv_me_ctxt; 471 /* Store Tile params base into ME context */ 472 ps_me_ctxt->pv_tile_params_base = pv_tile_params_base; 473 474 status = hme_enc_init( 475 pv_me_ctxt, &as_memtabs[0], &s_hme_init_prms, ps_rc_quant_ctxt, i4_num_me_frm_pllel); 476 477 if(status == -1) 478 return NULL; 479 480 /*************************************************************************/ 481 /* --- L0 ME sync Dep Mngr Mem init -- */ 482 /*************************************************************************/ 483 /* Update numer of ME frames running in parallel in me master context */ 484 ps_me_ctxt->i4_num_me_frm_pllel = i4_num_me_frm_pllel; 485 486 e_arch_type = ps_init_prms->e_arch_type; 487 488 hme_init_function_ptr(ps_me_ctxt, e_arch_type); 489 490 ihevce_me_instr_set_router( 491 (ihevce_me_optimised_function_list_t *)ps_me_ctxt->pv_me_optimised_function_list, 492 e_arch_type); 493 494 ihevce_cmn_utils_instr_set_router( 495 &ps_me_ctxt->s_cmn_opt_func, u1_is_popcnt_available, e_arch_type); 496 497 ps_mem_tab += n_tabs; 498 499 return (pv_me_ctxt); 500 } 501 502 /** 503 ******************************************************************************* 504 * \if Function name : ihevce_me_set_resolution \endif 505 * 506 * \brief 507 * Sets the resolution for ME state 508 * 509 * \par Description: 510 * ME requires information of resolution to prime up its layer descriptors 511 * and contexts. This API is called whenever a control call from application 512 * causes a change of resolution. Has to be called once initially before 513 * processing any frame. Again this is just a glue function and calls the 514 * actual ME API for the same. 515 * 516 * \param[in,out] pv_me_ctxt: Handle to the ME context 517 * \param[in] n_enc_layers: Number of layers getting encoded 518 * \param[in] p_wd : Pointer containing widths of each layer getting encoded. 519 * \param[in] p_ht : Pointer containing heights of each layer getting encoded. 520 * 521 * \returns 522 * none 523 * 524 * \author 525 * Ittiam 526 * 527 ******************************************************************************* 528 */ 529 void ihevce_me_set_resolution(void *pv_me_ctxt, WORD32 n_enc_layers, WORD32 *p_wd, WORD32 *p_ht) 530 { 531 /* local variables */ 532 me_master_ctxt_t *ps_master_ctxt = (me_master_ctxt_t *)pv_me_ctxt; 533 WORD32 thrds; 534 WORD32 i; 535 536 for(thrds = 0; thrds < ps_master_ctxt->i4_num_proc_thrds; thrds++) 537 { 538 me_ctxt_t *ps_me_thrd_ctxt; 539 540 ps_me_thrd_ctxt = ps_master_ctxt->aps_me_ctxt[thrds]; 541 542 for(i = 0; i < MAX_NUM_ME_PARALLEL; i++) 543 { 544 hme_set_resolution((void *)ps_me_thrd_ctxt, n_enc_layers, p_wd, p_ht, i); 545 } 546 } 547 } 548 549 void ihevce_populate_me_ctb_data( 550 me_ctxt_t *ps_ctxt, 551 me_frm_ctxt_t *ps_frm_ctxt, 552 cur_ctb_cu_tree_t *ps_cu_tree, 553 me_ctb_data_t *ps_me_ctb_data, 554 CU_POS_T e_grandparent_blk_pos, 555 CU_POS_T e_parent_blk_pos, 556 CU_POS_T e_cur_blk_pos) 557 { 558 inter_cu_results_t *ps_cu_results; 559 560 switch(ps_cu_tree->u1_cu_size) 561 { 562 case 64: 563 { 564 block_data_64x64_t *ps_data = &ps_me_ctb_data->s_64x64_block_data; 565 566 ps_cu_results = &ps_frm_ctxt->s_cu64x64_results; 567 ps_data->num_best_results = (ps_cu_tree->is_node_valid) ? ps_cu_results->u1_num_best_results 568 : 0; 569 570 break; 571 } 572 case 32: 573 { 574 block_data_32x32_t *ps_data = &ps_me_ctb_data->as_32x32_block_data[e_cur_blk_pos]; 575 576 ps_cu_results = &ps_frm_ctxt->as_cu32x32_results[e_cur_blk_pos]; 577 ps_data->num_best_results = (ps_cu_tree->is_node_valid) ? ps_cu_results->u1_num_best_results 578 : 0; 579 580 break; 581 } 582 case 16: 583 { 584 WORD32 i4_blk_id = e_cur_blk_pos + (e_parent_blk_pos << 2); 585 586 block_data_16x16_t *ps_data = &ps_me_ctb_data->as_block_data[i4_blk_id]; 587 588 ps_cu_results = &ps_frm_ctxt->as_cu16x16_results[i4_blk_id]; 589 ps_data->num_best_results = (ps_cu_tree->is_node_valid) ? ps_cu_results->u1_num_best_results 590 : 0; 591 592 break; 593 } 594 case 8: 595 { 596 WORD32 i4_blk_id = e_cur_blk_pos + (e_parent_blk_pos << 2) + (e_grandparent_blk_pos << 4); 597 598 block_data_8x8_t *ps_data = &ps_me_ctb_data->as_8x8_block_data[i4_blk_id]; 599 600 ps_cu_results = &ps_frm_ctxt->as_cu8x8_results[i4_blk_id]; 601 ps_data->num_best_results = (ps_cu_tree->is_node_valid) ? ps_cu_results->u1_num_best_results 602 : 0; 603 604 break; 605 } 606 } 607 608 if(ps_cu_tree->is_node_valid) 609 { 610 if((ps_ctxt->s_init_prms.s_me_coding_tools.e_me_quality_presets == ME_PRISTINE_QUALITY) && 611 (ps_cu_tree->u1_cu_size != 8)) 612 { 613 ihevce_populate_me_ctb_data( 614 ps_ctxt, 615 ps_frm_ctxt, 616 ps_cu_tree->ps_child_node_tl, 617 ps_me_ctb_data, 618 e_parent_blk_pos, 619 e_cur_blk_pos, 620 POS_TL); 621 622 ihevce_populate_me_ctb_data( 623 ps_ctxt, 624 ps_frm_ctxt, 625 ps_cu_tree->ps_child_node_tr, 626 ps_me_ctb_data, 627 e_parent_blk_pos, 628 e_cur_blk_pos, 629 POS_TR); 630 631 ihevce_populate_me_ctb_data( 632 ps_ctxt, 633 ps_frm_ctxt, 634 ps_cu_tree->ps_child_node_bl, 635 ps_me_ctb_data, 636 e_parent_blk_pos, 637 e_cur_blk_pos, 638 POS_BL); 639 640 ihevce_populate_me_ctb_data( 641 ps_ctxt, 642 ps_frm_ctxt, 643 ps_cu_tree->ps_child_node_br, 644 ps_me_ctb_data, 645 e_parent_blk_pos, 646 e_cur_blk_pos, 647 POS_BR); 648 } 649 } 650 else if(ps_cu_tree->u1_cu_size != 8) 651 { 652 ihevce_populate_me_ctb_data( 653 ps_ctxt, 654 ps_frm_ctxt, 655 ps_cu_tree->ps_child_node_tl, 656 ps_me_ctb_data, 657 e_parent_blk_pos, 658 e_cur_blk_pos, 659 POS_TL); 660 661 ihevce_populate_me_ctb_data( 662 ps_ctxt, 663 ps_frm_ctxt, 664 ps_cu_tree->ps_child_node_tr, 665 ps_me_ctb_data, 666 e_parent_blk_pos, 667 e_cur_blk_pos, 668 POS_TR); 669 670 ihevce_populate_me_ctb_data( 671 ps_ctxt, 672 ps_frm_ctxt, 673 ps_cu_tree->ps_child_node_bl, 674 ps_me_ctb_data, 675 e_parent_blk_pos, 676 e_cur_blk_pos, 677 POS_BL); 678 679 ihevce_populate_me_ctb_data( 680 ps_ctxt, 681 ps_frm_ctxt, 682 ps_cu_tree->ps_child_node_br, 683 ps_me_ctb_data, 684 e_parent_blk_pos, 685 e_cur_blk_pos, 686 POS_BR); 687 } 688 } 689 690 void ihevce_me_update_ctb_results( 691 void *pv_me_ctxt, void *pv_me_frm_ctxt, WORD32 i4_ctb_x, WORD32 i4_ctb_y) 692 { 693 ctb_analyse_t *ps_ctb_out; 694 cur_ctb_cu_tree_t *ps_cu_tree; 695 me_ctb_data_t *ps_me_ctb_data; 696 697 me_ctxt_t *ps_ctxt = (me_ctxt_t *)pv_me_ctxt; 698 me_frm_ctxt_t *ps_frm_ctxt = (me_frm_ctxt_t *)pv_me_frm_ctxt; 699 700 ps_ctb_out = ps_frm_ctxt->ps_ctb_analyse_curr_row + i4_ctb_x; 701 702 ps_me_ctb_data = ps_frm_ctxt->ps_me_ctb_data_curr_row + i4_ctb_x; 703 ps_cu_tree = ps_frm_ctxt->ps_cu_tree_curr_row + (i4_ctb_x * MAX_NUM_NODES_CU_TREE); 704 705 ps_ctb_out->ps_cu_tree = ps_cu_tree; 706 ps_ctb_out->ps_me_ctb_data = ps_me_ctb_data; 707 708 ihevce_populate_me_ctb_data( 709 ps_ctxt, ps_frm_ctxt, ps_cu_tree, ps_me_ctb_data, POS_NA, POS_NA, POS_NA); 710 } 711 712 WORD32 ihevce_me_find_poc_in_list( 713 recon_pic_buf_t **pps_rec_list, WORD32 poc, WORD32 i4_idr_gop_num, WORD32 num_ref) 714 { 715 WORD32 i; 716 717 for(i = 0; i < num_ref; i++) 718 { 719 if(pps_rec_list[i]->i4_poc == poc && pps_rec_list[i]->i4_idr_gop_num == i4_idr_gop_num) 720 return (i); 721 } 722 723 /* should never come here */ 724 ASSERT(0); 725 return (-1); 726 } 727 void ihevc_me_update_ref_desc( 728 hme_ref_desc_t *ps_ref_desc, 729 recon_pic_buf_t *ps_recon_pic, 730 WORD32 ref_id_l0, 731 WORD32 ref_id_l1, 732 WORD32 ref_id_lc, 733 WORD32 is_fwd) 734 { 735 hme_ref_buf_info_t *ps_ref_info = &ps_ref_desc->as_ref_info[0]; 736 iv_enc_yuv_buf_t *ps_yuv_desc = (iv_enc_yuv_buf_t *)&ps_recon_pic->s_yuv_buf_desc; 737 iv_enc_yuv_buf_t *ps_src_yuv_desc = (iv_enc_yuv_buf_t *)&ps_recon_pic->s_yuv_buf_desc_src; 738 S32 offset; 739 740 /* Padding beyond 64 is not of use to ME */ 741 ps_ref_info->u1_pad_x = MIN(64, PAD_HORZ); 742 ps_ref_info->u1_pad_y = MIN(64, PAD_VERT); 743 744 /* Luma stride and offset. Assuming here that supplied ptr is */ 745 /* 0, 0 position and hence setting offset to 0. In fact, it is */ 746 /* not used inside ME as of now. */ 747 ps_ref_info->luma_stride = ps_yuv_desc->i4_y_strd; 748 ps_ref_info->luma_offset = 0; 749 750 /* 4 planes, fxfy is the direct recon buf, others are from subpel planes */ 751 //offset = ps_ref_info->luma_stride * PAD_VERT + PAD_HORZ; 752 offset = 0; 753 ps_ref_info->pu1_rec_fxfy = (UWORD8 *)ps_yuv_desc->pv_y_buf + offset; 754 ps_ref_info->pu1_rec_hxfy = ps_recon_pic->apu1_y_sub_pel_planes[0] + offset; 755 ps_ref_info->pu1_rec_fxhy = ps_recon_pic->apu1_y_sub_pel_planes[1] + offset; 756 ps_ref_info->pu1_rec_hxhy = ps_recon_pic->apu1_y_sub_pel_planes[2] + offset; 757 ps_ref_info->pu1_ref_src = (UWORD8 *)ps_src_yuv_desc->pv_y_buf + offset; 758 759 /* U V ptrs though they are not used */ 760 ps_ref_info->pu1_rec_u = (U08 *)ps_yuv_desc->pv_u_buf; 761 ps_ref_info->pu1_rec_v = (U08 *)ps_yuv_desc->pv_v_buf; 762 763 /* uv offsets and strides, same treatment sa luma */ 764 ps_ref_info->chroma_offset = 0; 765 ps_ref_info->chroma_stride = ps_yuv_desc->i4_uv_strd; 766 767 ps_ref_info->pv_dep_mngr = ps_recon_pic->pv_dep_mngr_recon; 768 769 /* L0, L1 and LC id. */ 770 ps_ref_desc->i1_ref_id_l0 = ref_id_l0; 771 ps_ref_desc->i1_ref_id_l1 = ref_id_l1; 772 ps_ref_desc->i1_ref_id_lc = ref_id_lc; 773 774 /* POC of the ref pic */ 775 ps_ref_desc->i4_poc = ps_recon_pic->i4_poc; 776 777 /* Display num of the ref pic */ 778 ps_ref_desc->i4_display_num = ps_recon_pic->i4_display_num; 779 780 /* GOP number of the reference pic*/ 781 ps_ref_desc->i4_GOP_num = ps_recon_pic->i4_idr_gop_num; 782 783 /* Whether this picture is in past (fwd) or future (bck) */ 784 ps_ref_desc->u1_is_fwd = is_fwd; 785 786 /* store the weight and offsets fo refernce picture */ 787 ps_ref_desc->i2_weight = ps_recon_pic->s_weight_offset.i2_luma_weight; 788 ps_ref_desc->i2_offset = ps_recon_pic->s_weight_offset.i2_luma_offset; 789 } 790 791 /* Create the reference map for ME */ 792 void ihevce_me_create_ref_map( 793 recon_pic_buf_t **pps_rec_list_l0, 794 recon_pic_buf_t **pps_rec_list_l1, 795 WORD32 num_ref_l0_active, 796 WORD32 num_ref_l1_active, 797 WORD32 num_ref, 798 hme_ref_map_t *ps_ref_map) 799 { 800 WORD32 min_ref, i, poc, ref_id_l0, ref_id_l1; 801 802 /* tracks running count of ref pics */ 803 WORD32 ref_count = 0, i4_idr_gop_num; 804 805 /* points to One instance of a ref pic structure */ 806 recon_pic_buf_t *ps_recon_pic; 807 808 /* points to one instance of ref desc str used by ME */ 809 hme_ref_desc_t *ps_ref_desc; 810 811 min_ref = MIN(num_ref_l0_active, num_ref_l1_active); 812 813 for(i = 0; i < min_ref; i++) 814 { 815 /* Create interleaved L0 and L1 entries */ 816 ps_ref_desc = &ps_ref_map->as_ref_desc[ref_count]; 817 ps_recon_pic = pps_rec_list_l0[i]; 818 poc = ps_recon_pic->i4_poc; 819 i4_idr_gop_num = ps_recon_pic->i4_idr_gop_num; 820 ref_id_l0 = i; 821 ref_id_l1 = ihevce_me_find_poc_in_list(pps_rec_list_l1, poc, i4_idr_gop_num, num_ref); 822 ihevc_me_update_ref_desc(ps_ref_desc, ps_recon_pic, ref_id_l0, ref_id_l1, 2 * i, 1); 823 824 ref_count++; 825 826 ps_ref_desc = &ps_ref_map->as_ref_desc[ref_count]; 827 ps_recon_pic = pps_rec_list_l1[i]; 828 poc = ps_recon_pic->i4_poc; 829 i4_idr_gop_num = ps_recon_pic->i4_idr_gop_num; 830 ref_id_l1 = i; 831 ref_id_l0 = ihevce_me_find_poc_in_list(pps_rec_list_l0, poc, i4_idr_gop_num, num_ref); 832 ihevc_me_update_ref_desc(ps_ref_desc, ps_recon_pic, ref_id_l0, ref_id_l1, 2 * i + 1, 0); 833 834 ref_count++; 835 } 836 837 if(num_ref_l0_active > min_ref) 838 { 839 for(i = 0; i < (num_ref_l0_active - min_ref); i++) 840 { 841 ps_ref_desc = &ps_ref_map->as_ref_desc[ref_count]; 842 ref_id_l0 = i + min_ref; 843 ps_recon_pic = pps_rec_list_l0[ref_id_l0]; 844 poc = ps_recon_pic->i4_poc; 845 i4_idr_gop_num = ps_recon_pic->i4_idr_gop_num; 846 ref_id_l1 = ihevce_me_find_poc_in_list(pps_rec_list_l1, poc, i4_idr_gop_num, num_ref); 847 ihevc_me_update_ref_desc( 848 ps_ref_desc, ps_recon_pic, ref_id_l0, ref_id_l1, 2 * min_ref + i, 1); 849 ref_count++; 850 } 851 } 852 else 853 { 854 for(i = 0; i < (num_ref_l1_active - min_ref); i++) 855 { 856 ps_ref_desc = &ps_ref_map->as_ref_desc[ref_count]; 857 ref_id_l1 = i + min_ref; 858 ps_recon_pic = pps_rec_list_l1[ref_id_l1]; 859 poc = ps_recon_pic->i4_poc; 860 i4_idr_gop_num = ps_recon_pic->i4_idr_gop_num; 861 ref_id_l0 = ihevce_me_find_poc_in_list(pps_rec_list_l0, poc, i4_idr_gop_num, num_ref); 862 ihevc_me_update_ref_desc( 863 ps_ref_desc, ps_recon_pic, ref_id_l0, ref_id_l1, 2 * min_ref + i, 0); 864 ref_count++; 865 } 866 } 867 868 ps_ref_map->i4_num_ref = ref_count; 869 ASSERT(ref_count == (num_ref_l0_active + num_ref_l1_active)); 870 871 /* TODO : Fill better values in lambda depending on ref dist */ 872 for(i = 0; i < ps_ref_map->i4_num_ref; i++) 873 ps_ref_map->as_ref_desc[i].lambda = 20; 874 } 875 876 /*! 877 ****************************************************************************** 878 * \if Function name : ihevce_me_process \endif 879 * 880 * \brief 881 * Frame level ME function 882 * 883 * \par Description: 884 * Processing of all layers starting from coarse and going 885 * to the refinement layers, all layers 886 * that are encoded go CTB by CTB. Outputs of this function are populated 887 * ctb_analyse_t structures, one per CTB. 888 * 889 * \param[in] pv_ctxt : pointer to ME module 890 * \param[in] ps_enc_lap_inp : pointer to input yuv buffer (frame buffer) 891 * \param[in,out] ps_ctb_out : pointer to CTB analyse output structure (frame buffer) 892 * \param[out] ps_cu_out : pointer to CU analyse output structure (frame buffer) 893 * \param[in] pd_intra_costs : pointerto intra cost buffer 894 * \param[in] ps_multi_thrd_ctxt : pointer to multi thread ctxt 895 * \param[in] thrd_id : Thread id of the current thrd in which function is executed 896 * 897 * \return 898 * None 899 * 900 * \author 901 * Ittiam 902 * 903 ***************************************************************************** 904 */ 905 void ihevce_me_process( 906 void *pv_me_ctxt, 907 ihevce_lap_enc_buf_t *ps_enc_lap_inp, 908 ctb_analyse_t *ps_ctb_out, 909 me_enc_rdopt_ctxt_t *ps_cur_out_me_prms, 910 double *pd_intra_costs, 911 ipe_l0_ctb_analyse_for_me_t *ps_ipe_analyse_ctb, 912 pre_enc_L0_ipe_encloop_ctxt_t *ps_l0_ipe_input, 913 void *pv_coarse_layer, 914 multi_thrd_ctxt_t *ps_multi_thrd_ctxt, 915 WORD32 i4_frame_parallelism_level, 916 WORD32 thrd_id, 917 WORD32 i4_me_frm_id) 918 { 919 me_ctxt_t *ps_thrd_ctxt; 920 me_frm_ctxt_t *ps_ctxt; 921 922 PF_EXT_UPDATE_FXN_T pf_ext_update_fxn; 923 924 me_master_ctxt_t *ps_master_ctxt = (me_master_ctxt_t *)pv_me_ctxt; 925 cur_ctb_cu_tree_t *ps_cu_tree_out = ps_cur_out_me_prms->ps_cur_ctb_cu_tree; 926 me_ctb_data_t *ps_me_ctb_data_out = ps_cur_out_me_prms->ps_cur_ctb_me_data; 927 layer_ctxt_t *ps_coarse_layer = (layer_ctxt_t *)pv_coarse_layer; 928 929 pf_ext_update_fxn = (PF_EXT_UPDATE_FXN_T)ihevce_me_update_ctb_results; 930 931 /* get the current thread ctxt pointer */ 932 ps_thrd_ctxt = ps_master_ctxt->aps_me_ctxt[thrd_id]; 933 ps_ctxt = ps_thrd_ctxt->aps_me_frm_prms[i4_me_frm_id]; 934 ps_ctxt->thrd_id = thrd_id; 935 936 /* store the ctb out and cu out base pointers */ 937 ps_ctxt->ps_ctb_analyse_base = ps_ctb_out; 938 939 ps_ctxt->ps_cu_tree_base = ps_cu_tree_out; 940 ps_ctxt->ps_ipe_l0_ctb_frm_base = ps_ipe_analyse_ctb; 941 ps_ctxt->ps_me_ctb_data_base = ps_me_ctb_data_out; 942 ps_ctxt->ps_func_selector = &ps_master_ctxt->s_func_selector; 943 944 /** currently in master context. Copying that to me context **/ 945 /* frame level processing function */ 946 hme_process_frm( 947 (void *)ps_thrd_ctxt, 948 ps_l0_ipe_input, 949 &ps_master_ctxt->as_ref_map[i4_me_frm_id], 950 &pd_intra_costs, 951 &ps_master_ctxt->as_frm_prms[i4_me_frm_id], 952 pf_ext_update_fxn, 953 ps_coarse_layer, 954 ps_multi_thrd_ctxt, 955 i4_frame_parallelism_level, 956 thrd_id, 957 i4_me_frm_id); 958 } 959 /*! 960 ****************************************************************************** 961 * \if Function name : ihevce_me_frame_dpb_update \endif 962 * 963 * \brief 964 * Frame level ME initialisation function 965 * 966 * \par Description: 967 * Updation of ME's internal DPB 968 * based on available ref list information 969 * 970 * \param[in] pv_ctxt : pointer to ME module 971 * \param[in] num_ref_l0 : Number of reference pics in L0 list 972 * \param[in] num_ref_l1 : Number of reference pics in L1 list 973 * \param[in] pps_rec_list_l0 : List of recon pics in L0 list 974 * \param[in] pps_rec_list_l1 : List of recon pics in L1 list 975 * 976 * \return 977 * None 978 * 979 * \author 980 * Ittiam 981 * 982 ***************************************************************************** 983 */ 984 void ihevce_me_frame_dpb_update( 985 void *pv_me_ctxt, 986 WORD32 num_ref_l0, 987 WORD32 num_ref_l1, 988 recon_pic_buf_t **pps_rec_list_l0, 989 recon_pic_buf_t **pps_rec_list_l1, 990 WORD32 i4_thrd_id) 991 { 992 me_master_ctxt_t *ps_master_ctxt = (me_master_ctxt_t *)pv_me_ctxt; 993 me_ctxt_t *ps_thrd0_ctxt; 994 WORD32 a_pocs_to_remove[MAX_NUM_REF + 2]; 995 WORD32 i, i4_is_buffer_full; 996 WORD32 i4_least_POC = 0x7FFFFFFF; 997 WORD32 i4_least_GOP_num = 0x7FFFFFFF; 998 me_ctxt_t *ps_ctxt; 999 1000 /* All processing done using shared / common memory across */ 1001 /* threads is done using thrd ctxt */ 1002 ps_thrd0_ctxt = ps_master_ctxt->aps_me_ctxt[i4_thrd_id]; 1003 1004 ps_ctxt = (me_ctxt_t *)ps_thrd0_ctxt; 1005 a_pocs_to_remove[0] = INVALID_POC; 1006 /*************************************************************************/ 1007 /* Updation of ME's DPB list. This involves the following steps: */ 1008 /* 1. Obtain list of active POCs maintained within ME. */ 1009 /* 2. Search each of them in the ref list. Whatever is not found goes to */ 1010 /* the list to be removed. Note: a_pocs_buffered_in_me holds the */ 1011 /* currently active POC list within ME. a_pocs_to_remove holds the */ 1012 /* list of POCs to be removed, terminated by -1. */ 1013 /*************************************************************************/ 1014 i4_is_buffer_full = 1015 hme_get_active_pocs_list((void *)ps_thrd0_ctxt, ps_master_ctxt->i4_num_me_frm_pllel); 1016 1017 if(i4_is_buffer_full) 1018 { 1019 /* remove if any non-reference pictures are present */ 1020 for(i = 0; 1021 i < 1022 (ps_ctxt->aps_me_frm_prms[0]->max_num_ref * ps_master_ctxt->i4_num_me_frm_pllel) + 1; 1023 i++) 1024 { 1025 if(ps_ctxt->as_ref_descr[i].aps_layers[0]->i4_is_reference == 0 && 1026 ps_ctxt->as_ref_descr[i].aps_layers[0]->i4_non_ref_free == 1) 1027 { 1028 i4_least_POC = ps_ctxt->as_ref_descr[i].aps_layers[0]->i4_poc; 1029 i4_least_GOP_num = ps_ctxt->as_ref_descr[i].aps_layers[0]->i4_idr_gop_num; 1030 } 1031 } 1032 /* if all non reference pictures are removed, then find the least poc 1033 in the least gop number*/ 1034 if(i4_least_POC == 0x7FFFFFFF) 1035 { 1036 ASSERT(i4_least_GOP_num == 0x7FFFFFFF); 1037 for(i = 0; i < (ps_ctxt->aps_me_frm_prms[0]->max_num_ref * 1038 ps_master_ctxt->i4_num_me_frm_pllel) + 1039 1; 1040 i++) 1041 { 1042 if(i4_least_GOP_num > ps_ctxt->as_ref_descr[i].aps_layers[0]->i4_idr_gop_num) 1043 { 1044 i4_least_GOP_num = ps_ctxt->as_ref_descr[i].aps_layers[0]->i4_idr_gop_num; 1045 } 1046 } 1047 for(i = 0; i < (ps_ctxt->aps_me_frm_prms[0]->max_num_ref * 1048 ps_master_ctxt->i4_num_me_frm_pllel) + 1049 1; 1050 i++) 1051 { 1052 if(i4_least_POC > ps_ctxt->as_ref_descr[i].aps_layers[0]->i4_poc && 1053 ps_ctxt->as_ref_descr[i].aps_layers[0]->i4_idr_gop_num == i4_least_GOP_num) 1054 { 1055 i4_least_POC = ps_ctxt->as_ref_descr[i].aps_layers[0]->i4_poc; 1056 } 1057 } 1058 } 1059 ASSERT(i4_least_POC != 0x7FFFFFFF); 1060 a_pocs_to_remove[0] = i4_least_POC; 1061 a_pocs_to_remove[1] = INVALID_POC; 1062 } 1063 1064 /* Call the ME API to remove "outdated" POCs */ 1065 hme_discard_frm( 1066 ps_thrd0_ctxt, a_pocs_to_remove, i4_least_GOP_num, ps_master_ctxt->i4_num_me_frm_pllel); 1067 } 1068 /*! 1069 ****************************************************************************** 1070 * \if Function name : ihevce_me_frame_init \endif 1071 * 1072 * \brief 1073 * Frame level ME initialisation function 1074 * 1075 * \par Description: 1076 * The following pre-conditions exist for this function: a. We have the input 1077 * pic ready for encode, b. We have the reference list with POC, L0/L1 IDs 1078 * and ref ptrs ready for this picture and c. ihevce_me_set_resolution has 1079 * been called atleast once. Once these are supplied, the following are 1080 * done here: a. Input pyramid creation, b. Updation of ME's internal DPB 1081 * based on available ref list information 1082 * 1083 * \param[in] pv_ctxt : pointer to ME module 1084 * \param[in] ps_frm_ctb_prms : CTB characteristics parameters 1085 * \param[in] ps_frm_lamda : Frame level Lambda params 1086 * \param[in] num_ref_l0 : Number of reference pics in L0 list 1087 * \param[in] num_ref_l1 : Number of reference pics in L1 list 1088 * \param[in] num_ref_l0_active : Active reference pics in L0 dir for current frame (shall be <= num_ref_l0) 1089 * \param[in] num_ref_l1_active : Active reference pics in L1 dir for current frame (shall be <= num_ref_l1) 1090 * \param[in] pps_rec_list_l0 : List of recon pics in L0 list 1091 * \param[in] pps_rec_list_l1 : List of recon pics in L1 list 1092 * \param[in] ps_enc_lap_inp : pointer to input yuv buffer (frame buffer) 1093 * \param[in] i4_frm_qp : current picture QP 1094 * 1095 * \return 1096 * None 1097 * 1098 * \author 1099 * Ittiam 1100 * 1101 ***************************************************************************** 1102 */ 1103 void ihevce_me_frame_init( 1104 void *pv_me_ctxt, 1105 me_enc_rdopt_ctxt_t *ps_cur_out_me_prms, 1106 ihevce_static_cfg_params_t *ps_stat_prms, 1107 frm_ctb_ctxt_t *ps_frm_ctb_prms, 1108 frm_lambda_ctxt_t *ps_frm_lamda, 1109 WORD32 num_ref_l0, 1110 WORD32 num_ref_l1, 1111 WORD32 num_ref_l0_active, 1112 WORD32 num_ref_l1_active, 1113 recon_pic_buf_t **pps_rec_list_l0, 1114 recon_pic_buf_t **pps_rec_list_l1, 1115 recon_pic_buf_t *(*aps_ref_list)[HEVCE_MAX_REF_PICS * 2], 1116 func_selector_t *ps_func_selector, 1117 ihevce_lap_enc_buf_t *ps_enc_lap_inp, 1118 void *pv_coarse_layer, 1119 WORD32 i4_me_frm_id, 1120 WORD32 i4_thrd_id, 1121 WORD32 i4_frm_qp, 1122 WORD32 i4_temporal_layer_id, 1123 WORD8 i1_cu_qp_delta_enabled_flag, 1124 void *pv_dep_mngr_encloop_dep_me) 1125 { 1126 me_ctxt_t *ps_thrd_ctxt; 1127 me_ctxt_t *ps_thrd0_ctxt; 1128 me_frm_ctxt_t *ps_ctxt; 1129 hme_inp_desc_t s_inp_desc; 1130 1131 WORD32 inp_poc, num_ref; 1132 WORD32 i; 1133 1134 me_master_ctxt_t *ps_master_ctxt = (me_master_ctxt_t *)pv_me_ctxt; 1135 layer_ctxt_t *ps_coarse_layer = (layer_ctxt_t *)pv_coarse_layer; 1136 1137 /* Input POC is derived from input buffer */ 1138 inp_poc = ps_enc_lap_inp->s_lap_out.i4_poc; 1139 num_ref = num_ref_l0 + num_ref_l1; 1140 1141 /* All processing done using shared / common memory across */ 1142 /* threads is done using thrd ctxt */ 1143 ps_thrd0_ctxt = ps_master_ctxt->aps_me_ctxt[i4_thrd_id]; 1144 1145 ps_ctxt = ps_thrd0_ctxt->aps_me_frm_prms[i4_me_frm_id]; 1146 1147 /* Update the paarameters "num_ref_l0_active" and "num_ref_l1_active" in hme_frm_prms */ 1148 ps_master_ctxt->as_frm_prms[i4_me_frm_id].u1_num_active_ref_l0 = num_ref_l0_active; 1149 ps_master_ctxt->as_frm_prms[i4_me_frm_id].u1_num_active_ref_l1 = num_ref_l1_active; 1150 1151 /*************************************************************************/ 1152 /* Add the current input to ME's DPB. This will also create the pyramids */ 1153 /* for the HME layers tha are not "encoded". */ 1154 /*************************************************************************/ 1155 s_inp_desc.i4_poc = inp_poc; 1156 s_inp_desc.i4_idr_gop_num = ps_enc_lap_inp->s_lap_out.i4_idr_gop_num; 1157 s_inp_desc.i4_is_reference = ps_enc_lap_inp->s_lap_out.i4_is_ref_pic; 1158 s_inp_desc.s_layer_desc[0].pu1_y = (UWORD8 *)ps_enc_lap_inp->s_lap_out.s_input_buf.pv_y_buf; 1159 s_inp_desc.s_layer_desc[0].pu1_u = (UWORD8 *)ps_enc_lap_inp->s_lap_out.s_input_buf.pv_u_buf; 1160 s_inp_desc.s_layer_desc[0].pu1_v = (UWORD8 *)ps_enc_lap_inp->s_lap_out.s_input_buf.pv_v_buf; 1161 1162 s_inp_desc.s_layer_desc[0].luma_stride = ps_enc_lap_inp->s_lap_out.s_input_buf.i4_y_strd; 1163 s_inp_desc.s_layer_desc[0].chroma_stride = ps_enc_lap_inp->s_lap_out.s_input_buf.i4_uv_strd; 1164 1165 hme_add_inp(pv_me_ctxt, &s_inp_desc, i4_me_frm_id, i4_thrd_id); 1166 1167 /* store the frm ctb ctxt to all the thrd ctxt */ 1168 { 1169 WORD32 num_thrds; 1170 1171 /* initialise the parameters for all the threads */ 1172 for(num_thrds = 0; num_thrds < ps_master_ctxt->i4_num_proc_thrds; num_thrds++) 1173 { 1174 me_frm_ctxt_t *ps_me_tmp_frm_ctxt; 1175 1176 ps_thrd_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds]; 1177 1178 ps_me_tmp_frm_ctxt = ps_thrd_ctxt->aps_me_frm_prms[i4_me_frm_id]; 1179 1180 ps_thrd_ctxt->pv_ext_frm_prms = (void *)ps_frm_ctb_prms; 1181 ps_me_tmp_frm_ctxt->i4_l0me_qp_mod = ps_stat_prms->s_config_prms.i4_cu_level_rc & 1; 1182 1183 /* intialize the inter pred (MC) context at frame level */ 1184 ps_me_tmp_frm_ctxt->s_mc_ctxt.ps_ref_list = aps_ref_list; 1185 ps_me_tmp_frm_ctxt->s_mc_ctxt.i1_weighted_pred_flag = 1186 ps_enc_lap_inp->s_lap_out.i1_weighted_pred_flag; 1187 ps_me_tmp_frm_ctxt->s_mc_ctxt.i1_weighted_bipred_flag = 1188 ps_enc_lap_inp->s_lap_out.i1_weighted_bipred_flag; 1189 ps_me_tmp_frm_ctxt->s_mc_ctxt.i4_log2_luma_wght_denom = 1190 ps_enc_lap_inp->s_lap_out.i4_log2_luma_wght_denom; 1191 ps_me_tmp_frm_ctxt->s_mc_ctxt.i4_log2_chroma_wght_denom = 1192 ps_enc_lap_inp->s_lap_out.i4_log2_chroma_wght_denom; 1193 ps_me_tmp_frm_ctxt->s_mc_ctxt.i4_bit_depth = 8; 1194 ps_me_tmp_frm_ctxt->s_mc_ctxt.u1_chroma_array_type = 1; 1195 ps_me_tmp_frm_ctxt->s_mc_ctxt.ps_func_selector = ps_func_selector; 1196 /* Initiallization for non-distributed mode */ 1197 memset( 1198 ps_me_tmp_frm_ctxt->s_mc_ctxt.ai4_tile_xtra_pel, 1199 0, 1200 sizeof(ps_me_tmp_frm_ctxt->s_mc_ctxt.ai4_tile_xtra_pel)); 1201 1202 ps_me_tmp_frm_ctxt->i4_pic_type = ps_enc_lap_inp->s_lap_out.i4_pic_type; 1203 1204 ps_me_tmp_frm_ctxt->i4_rc_pass = ps_stat_prms->s_pass_prms.i4_pass; 1205 ps_me_tmp_frm_ctxt->i4_temporal_layer = ps_enc_lap_inp->s_lap_out.i4_temporal_lyr_id; 1206 ps_me_tmp_frm_ctxt->i4_use_const_lamda_modifier = USE_CONSTANT_LAMBDA_MODIFIER; 1207 ps_me_tmp_frm_ctxt->i4_use_const_lamda_modifier = 1208 ps_ctxt->i4_use_const_lamda_modifier || 1209 ((ps_stat_prms->s_coding_tools_prms.i4_vqet & 1210 (1 << BITPOS_IN_VQ_TOGGLE_FOR_CONTROL_TOGGLER)) && 1211 ((ps_stat_prms->s_coding_tools_prms.i4_vqet & 1212 (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_NOISE_PRESERVATION)) || 1213 (ps_stat_prms->s_coding_tools_prms.i4_vqet & 1214 (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_PSYRDOPT_1)) || 1215 (ps_stat_prms->s_coding_tools_prms.i4_vqet & 1216 (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_PSYRDOPT_2)) || 1217 (ps_stat_prms->s_coding_tools_prms.i4_vqet & 1218 (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_PSYRDOPT_3)))); 1219 { 1220 ps_me_tmp_frm_ctxt->f_i_pic_lamda_modifier = 1221 ps_enc_lap_inp->s_lap_out.f_i_pic_lamda_modifier; 1222 } 1223 /* weighted pred enable flag */ 1224 ps_me_tmp_frm_ctxt->i4_wt_pred_enable_flag = 1225 ps_enc_lap_inp->s_lap_out.i1_weighted_pred_flag | 1226 ps_enc_lap_inp->s_lap_out.i1_weighted_bipred_flag; 1227 1228 if(1 == ps_me_tmp_frm_ctxt->i4_wt_pred_enable_flag) 1229 { 1230 /* log2 weight denom */ 1231 ps_me_tmp_frm_ctxt->s_wt_pred.wpred_log_wdc = 1232 ps_enc_lap_inp->s_lap_out.i4_log2_luma_wght_denom; 1233 } 1234 else 1235 { 1236 /* default value */ 1237 ps_me_tmp_frm_ctxt->s_wt_pred.wpred_log_wdc = DENOM_DEFAULT; 1238 } 1239 1240 ps_me_tmp_frm_ctxt->u1_is_curFrame_a_refFrame = ps_enc_lap_inp->s_lap_out.i4_is_ref_pic; 1241 1242 ps_thrd_ctxt->pv_me_optimised_function_list = 1243 ps_master_ctxt->pv_me_optimised_function_list; 1244 ps_thrd_ctxt->ps_cmn_utils_optimised_function_list = &ps_master_ctxt->s_cmn_opt_func; 1245 } 1246 } 1247 1248 /* Create the reference map for ME */ 1249 ihevce_me_create_ref_map( 1250 pps_rec_list_l0, 1251 pps_rec_list_l1, 1252 num_ref_l0_active, 1253 num_ref_l1_active, 1254 num_ref, 1255 &ps_master_ctxt->as_ref_map[i4_me_frm_id]); 1256 1257 /** Remember the pointers to recon list parmas for L0 and L1 lists in the context */ 1258 ps_ctxt->ps_hme_ref_map->pps_rec_list_l0 = pps_rec_list_l0; 1259 ps_ctxt->ps_hme_ref_map->pps_rec_list_l1 = pps_rec_list_l1; 1260 1261 /*************************************************************************/ 1262 /* Call the ME frame level processing for further actiion. */ 1263 /* ToDo: Support Row Level API. */ 1264 /*************************************************************************/ 1265 ps_master_ctxt->as_frm_prms[i4_me_frm_id].i2_mv_range_x = 1266 ps_thrd0_ctxt->s_init_prms.max_horz_search_range; 1267 ps_master_ctxt->as_frm_prms[i4_me_frm_id].i2_mv_range_y = 1268 ps_thrd0_ctxt->s_init_prms.max_vert_search_range; 1269 ps_master_ctxt->as_frm_prms[i4_me_frm_id].is_i_pic = 0; 1270 ps_master_ctxt->as_frm_prms[i4_me_frm_id].is_pic_second_field = 1271 (!(ps_enc_lap_inp->s_input_buf.i4_bottom_field ^ 1272 ps_enc_lap_inp->s_input_buf.i4_topfield_first)); 1273 ps_master_ctxt->as_frm_prms[i4_me_frm_id].i4_temporal_layer_id = i4_temporal_layer_id; 1274 { 1275 S32 pic_type = ps_enc_lap_inp->s_lap_out.i4_pic_type; 1276 1277 /*********************************************************************/ 1278 /* For I Pic, we do not call update fn at ctb level, instead we do */ 1279 /* one shot update for entire picture. */ 1280 /*********************************************************************/ 1281 if((pic_type == IV_I_FRAME) || (pic_type == IV_II_FRAME) || (pic_type == IV_IDR_FRAME)) 1282 { 1283 ps_master_ctxt->as_frm_prms[i4_me_frm_id].is_i_pic = 1; 1284 ps_master_ctxt->as_frm_prms[i4_me_frm_id].bidir_enabled = 0; 1285 } 1286 1287 else if((pic_type == IV_P_FRAME) || (pic_type == IV_PP_FRAME)) 1288 { 1289 ps_master_ctxt->as_frm_prms[i4_me_frm_id].bidir_enabled = 0; 1290 } 1291 else if((pic_type == IV_B_FRAME) || (pic_type == IV_BB_FRAME)) 1292 { 1293 ps_master_ctxt->as_frm_prms[i4_me_frm_id].bidir_enabled = 1; 1294 } 1295 else 1296 { 1297 /* not sure whether we need to handle mixed frames like IP, */ 1298 /* they should ideally come as single field. */ 1299 /* TODO : resolve thsi ambiguity */ 1300 ASSERT(0); 1301 } 1302 } 1303 /************************************************************************/ 1304 /* Lambda calculations moved outside ME and to one place, so as to have */ 1305 /* consistent lambda across ME, IPE, CL RDOPT etc */ 1306 /************************************************************************/ 1307 1308 { 1309 double d_q_factor; 1310 1311 d_q_factor = pow(2.0, (i4_frm_qp / 6.)) * 5.0 / 8.0; 1312 ps_master_ctxt->as_frm_prms[i4_me_frm_id].qstep = (WORD32)(d_q_factor + .5); 1313 ps_master_ctxt->as_frm_prms[i4_me_frm_id].i4_frame_qp = i4_frm_qp; 1314 1315 /* Qstep multiplied by 256, to work at higher precision: 1316 5/6 is the rounding factor. Multiplied by 2 for the Had vs DCT 1317 cost variation */ 1318 ps_master_ctxt->as_frm_prms[i4_me_frm_id].qstep_ls8 = 1319 (WORD32)((((d_q_factor * 256) * 5) / 3) + .5); 1320 } 1321 1322 /* Frame level init of all threads of ME */ 1323 { 1324 WORD32 num_thrds; 1325 1326 /* initialise the parameters for all the threads */ 1327 for(num_thrds = 0; num_thrds < ps_master_ctxt->i4_num_proc_thrds; num_thrds++) 1328 { 1329 me_frm_ctxt_t *ps_tmp_frm_ctxt; 1330 1331 ps_thrd_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds]; 1332 1333 ps_tmp_frm_ctxt = ps_thrd_ctxt->aps_me_frm_prms[i4_me_frm_id]; 1334 1335 hme_process_frm_init( 1336 (void *)ps_thrd_ctxt, 1337 ps_tmp_frm_ctxt->ps_hme_ref_map, 1338 ps_tmp_frm_ctxt->ps_hme_frm_prms, 1339 i4_me_frm_id, 1340 ps_master_ctxt->i4_num_me_frm_pllel); 1341 1342 ps_tmp_frm_ctxt->s_frm_lambda_ctxt = *ps_frm_lamda; 1343 ps_tmp_frm_ctxt->pv_dep_mngr_encloop_dep_me = pv_dep_mngr_encloop_dep_me; 1344 } 1345 } 1346 1347 ps_master_ctxt->as_frm_prms[i4_me_frm_id].i4_cl_sad_lambda_qf = 1348 ps_frm_lamda->i4_cl_sad_lambda_qf; 1349 ps_master_ctxt->as_frm_prms[i4_me_frm_id].i4_cl_satd_lambda_qf = 1350 ps_frm_lamda->i4_cl_satd_lambda_qf; 1351 ps_master_ctxt->as_frm_prms[i4_me_frm_id].i4_ol_sad_lambda_qf = 1352 ps_frm_lamda->i4_ol_sad_lambda_qf; 1353 ps_master_ctxt->as_frm_prms[i4_me_frm_id].i4_ol_satd_lambda_qf = 1354 ps_frm_lamda->i4_ol_satd_lambda_qf; 1355 ps_master_ctxt->as_frm_prms[i4_me_frm_id].lambda_q_shift = LAMBDA_Q_SHIFT; 1356 1357 ps_master_ctxt->as_frm_prms[i4_me_frm_id].u1_is_cu_qp_delta_enabled = 1358 i1_cu_qp_delta_enabled_flag; 1359 1360 /*************************************************************************/ 1361 /* If num ref is 0, that means that it has to be coded as I. Do nothing */ 1362 /* However mv bank update needs to happen with "intra" mv. */ 1363 /*************************************************************************/ 1364 if(ps_master_ctxt->as_ref_map[i4_me_frm_id].i4_num_ref == 0 || 1365 ps_master_ctxt->as_frm_prms[i4_me_frm_id].is_i_pic) 1366 { 1367 for(i = 0; i < 1; i++) 1368 { 1369 layer_ctxt_t *ps_layer_ctxt = ps_ctxt->ps_curr_descr->aps_layers[i]; 1370 BLK_SIZE_T e_blk_size; 1371 S32 use_4x4; 1372 1373 /* The mv bank is filled with "intra" mv */ 1374 use_4x4 = hme_get_mv_blk_size( 1375 ps_thrd0_ctxt->s_init_prms.use_4x4, i, ps_ctxt->num_layers, ps_ctxt->u1_encode[i]); 1376 e_blk_size = use_4x4 ? BLK_4x4 : BLK_8x8; 1377 hme_init_mv_bank(ps_layer_ctxt, e_blk_size, 2, 1, ps_ctxt->u1_encode[i]); 1378 hme_fill_mvbank_intra(ps_layer_ctxt); 1379 1380 /* Clear out the global mvs */ 1381 memset( 1382 ps_layer_ctxt->s_global_mv, 1383 0, 1384 sizeof(hme_mv_t) * ps_ctxt->max_num_ref * NUM_GMV_LOBES); 1385 } 1386 1387 return; 1388 } 1389 1390 /*************************************************************************/ 1391 /* Encode layer frame init */ 1392 /*************************************************************************/ 1393 { 1394 refine_prms_t s_refine_prms; 1395 layer_ctxt_t *ps_curr_layer; 1396 S16 i2_max; 1397 S32 layer_id; 1398 1399 layer_id = 0; 1400 i2_max = ps_ctxt->ps_curr_descr->aps_layers[layer_id]->i2_max_mv_x; 1401 i2_max = MAX(i2_max, ps_ctxt->ps_curr_descr->aps_layers[layer_id]->i2_max_mv_y); 1402 1403 ps_curr_layer = ps_ctxt->ps_curr_descr->aps_layers[layer_id]; 1404 1405 { 1406 hme_set_refine_prms( 1407 &s_refine_prms, 1408 ps_ctxt->u1_encode[layer_id], 1409 ps_master_ctxt->as_ref_map[i4_me_frm_id].i4_num_ref, 1410 layer_id, 1411 ps_ctxt->num_layers, 1412 ps_ctxt->num_layers_explicit_search, 1413 ps_thrd0_ctxt->s_init_prms.use_4x4, 1414 &ps_master_ctxt->as_frm_prms[i4_me_frm_id], 1415 NULL, 1416 &ps_thrd0_ctxt->s_init_prms 1417 .s_me_coding_tools); /* during frm init Intra cost Pointer is not required */ 1418 1419 hme_refine_frm_init(ps_curr_layer, &s_refine_prms, ps_coarse_layer); 1420 } 1421 } 1422 } 1423 1424 /*! 1425 ****************************************************************************** 1426 * \if Function name : ihevce_l0_me_frame_end \endif 1427 * 1428 * \brief 1429 * End of frame update function performs 1430 * - Dynamic Search Range collation 1431 * 1432 * \param[in] pv_ctxt : pointer to ME module 1433 * 1434 * \return 1435 * None 1436 * 1437 * \author 1438 * Ittiam 1439 * 1440 ***************************************************************************** 1441 */ 1442 1443 void ihevce_l0_me_frame_end( 1444 void *pv_me_ctxt, WORD32 i4_idx_dvsr_p, WORD32 i4_display_num, WORD32 me_frm_id) 1445 { 1446 WORD32 i4_num_ref = 0, num_ref, num_thrds, cur_poc, frm_num; 1447 1448 me_master_ctxt_t *ps_master_ctxt = (me_master_ctxt_t *)pv_me_ctxt; 1449 me_ctxt_t *ps_thrd0_ctxt; 1450 me_frm_ctxt_t *ps_frm_ctxt; 1451 WORD32 prev_me_frm_id; 1452 1453 ps_thrd0_ctxt = ps_master_ctxt->aps_me_ctxt[0]; 1454 ps_frm_ctxt = ps_thrd0_ctxt->aps_me_frm_prms[me_frm_id]; 1455 1456 /* Deriving the previous poc from previous frames context */ 1457 if(me_frm_id == 0) 1458 prev_me_frm_id = (MAX_NUM_ME_PARALLEL - 1); 1459 else 1460 prev_me_frm_id = me_frm_id - 1; 1461 1462 /* Getting the max num references value */ 1463 for(num_thrds = 0; num_thrds < ps_master_ctxt->i4_num_proc_thrds; num_thrds++) 1464 { 1465 i4_num_ref = 1466 MAX(i4_num_ref, 1467 ps_master_ctxt->aps_me_ctxt[num_thrds] 1468 ->aps_me_frm_prms[me_frm_id] 1469 ->as_l0_dyn_range_prms[i4_idx_dvsr_p] 1470 .i4_num_act_ref_in_l0); 1471 } 1472 1473 /* No processing is required if current pic is I pic */ 1474 if(1 == ps_master_ctxt->as_frm_prms[me_frm_id].is_i_pic) 1475 { 1476 return; 1477 } 1478 1479 /* If a B/b pic, then the previous frame ctxts dyn search prms should be copied ito the latest ctxt */ 1480 if(1 == ps_frm_ctxt->s_frm_prms.bidir_enabled) 1481 { 1482 return; 1483 } 1484 1485 /* Only for P pic. For P, both are 0, I&B has them mut. exclusive */ 1486 ASSERT(ps_frm_ctxt->s_frm_prms.is_i_pic == ps_frm_ctxt->s_frm_prms.bidir_enabled); 1487 1488 /* use thrd 0 ctxt to collate the Dynamic Search Range across all threads */ 1489 for(num_ref = 0; num_ref < i4_num_ref; num_ref++) 1490 { 1491 dyn_range_prms_t *ps_dyn_range_prms_thrd0; 1492 1493 ps_dyn_range_prms_thrd0 = 1494 &ps_frm_ctxt->as_l0_dyn_range_prms[i4_idx_dvsr_p].as_dyn_range_prms[num_ref]; 1495 1496 /* run a loop over all the other threads to update the dynamical search range */ 1497 for(num_thrds = 1; num_thrds < ps_master_ctxt->i4_num_proc_thrds; num_thrds++) 1498 { 1499 me_frm_ctxt_t *ps_me_tmp_frm_ctxt; 1500 1501 dyn_range_prms_t *ps_dyn_range_prms; 1502 1503 ps_me_tmp_frm_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds]->aps_me_frm_prms[me_frm_id]; 1504 1505 /* get current thrd dynamical search range param. pointer */ 1506 ps_dyn_range_prms = 1507 &ps_me_tmp_frm_ctxt->as_l0_dyn_range_prms[i4_idx_dvsr_p].as_dyn_range_prms[num_ref]; 1508 1509 /* TODO : This calls can be optimized further. No need for min in 1st call and max in 2nd call */ 1510 hme_update_dynamic_search_params( 1511 ps_dyn_range_prms_thrd0, ps_dyn_range_prms->i2_dyn_max_y); 1512 1513 hme_update_dynamic_search_params( 1514 ps_dyn_range_prms_thrd0, ps_dyn_range_prms->i2_dyn_min_y); 1515 } 1516 } 1517 1518 /*************************************************************************/ 1519 /* Get the MAX/MIN per POC distance based on the all the ref. pics */ 1520 /*************************************************************************/ 1521 cur_poc = ps_frm_ctxt->i4_curr_poc; 1522 ps_frm_ctxt->as_l0_dyn_range_prms[i4_idx_dvsr_p].i2_dyn_max_y_per_poc = 0; 1523 ps_frm_ctxt->as_l0_dyn_range_prms[i4_idx_dvsr_p].i2_dyn_min_y_per_poc = 0; 1524 /*populate display num*/ 1525 ps_frm_ctxt->as_l0_dyn_range_prms[i4_idx_dvsr_p].i4_display_num = i4_display_num; 1526 1527 for(num_ref = 0; num_ref < i4_num_ref; num_ref++) 1528 { 1529 WORD16 i2_mv_per_poc; 1530 WORD32 ref_poc, poc_diff; 1531 dyn_range_prms_t *ps_dyn_range_prms_thrd0; 1532 ps_dyn_range_prms_thrd0 = 1533 &ps_frm_ctxt->as_l0_dyn_range_prms[i4_idx_dvsr_p].as_dyn_range_prms[num_ref]; 1534 1535 ref_poc = ps_dyn_range_prms_thrd0->i4_poc; 1536 /* Should be cleaned up for ME llsm */ 1537 poc_diff = (cur_poc - ref_poc); 1538 poc_diff = MAX(1, poc_diff); 1539 1540 /* cur. ref. pic. max y per POC */ 1541 i2_mv_per_poc = (ps_dyn_range_prms_thrd0->i2_dyn_max_y + (poc_diff - 1)) / poc_diff; 1542 /* update the max y per POC */ 1543 ps_frm_ctxt->as_l0_dyn_range_prms[i4_idx_dvsr_p].i2_dyn_max_y_per_poc = MAX( 1544 ps_frm_ctxt->as_l0_dyn_range_prms[i4_idx_dvsr_p].i2_dyn_max_y_per_poc, i2_mv_per_poc); 1545 1546 /* cur. ref. pic. min y per POC */ 1547 i2_mv_per_poc = (ps_dyn_range_prms_thrd0->i2_dyn_min_y - (poc_diff - 1)) / poc_diff; 1548 /* update the min y per POC */ 1549 ps_frm_ctxt->as_l0_dyn_range_prms[i4_idx_dvsr_p].i2_dyn_min_y_per_poc = MIN( 1550 ps_frm_ctxt->as_l0_dyn_range_prms[i4_idx_dvsr_p].i2_dyn_min_y_per_poc, i2_mv_per_poc); 1551 } 1552 1553 /*************************************************************************/ 1554 /* Populate the results to all thread ctxt */ 1555 /*************************************************************************/ 1556 for(num_thrds = 1; num_thrds < ps_master_ctxt->i4_num_proc_thrds; num_thrds++) 1557 { 1558 me_frm_ctxt_t *ps_me_tmp_frm_ctxt; 1559 1560 ps_me_tmp_frm_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds]->aps_me_frm_prms[me_frm_id]; 1561 1562 ps_me_tmp_frm_ctxt->as_l0_dyn_range_prms[i4_idx_dvsr_p].i2_dyn_max_y_per_poc = 1563 ps_frm_ctxt->as_l0_dyn_range_prms[i4_idx_dvsr_p].i2_dyn_max_y_per_poc; 1564 1565 ps_me_tmp_frm_ctxt->as_l0_dyn_range_prms[i4_idx_dvsr_p].i2_dyn_min_y_per_poc = 1566 ps_frm_ctxt->as_l0_dyn_range_prms[i4_idx_dvsr_p].i2_dyn_min_y_per_poc; 1567 1568 ps_me_tmp_frm_ctxt->as_l0_dyn_range_prms[i4_idx_dvsr_p].i4_display_num = 1569 ps_frm_ctxt->as_l0_dyn_range_prms[i4_idx_dvsr_p].i4_display_num; 1570 } 1571 1572 /* Copy the dynamic search paramteres into the other Frame cotexts in parallel */ 1573 for(num_thrds = 0; num_thrds < ps_master_ctxt->i4_num_proc_thrds; num_thrds++) 1574 { 1575 l0_dyn_range_prms_t *ps_dyn_range_prms_thrd0; 1576 1577 ps_frm_ctxt = ps_thrd0_ctxt->aps_me_frm_prms[me_frm_id]; 1578 1579 i4_num_ref = ps_frm_ctxt->as_l0_dyn_range_prms[i4_idx_dvsr_p].i4_num_act_ref_in_l0; 1580 1581 ps_dyn_range_prms_thrd0 = &ps_frm_ctxt->as_l0_dyn_range_prms[i4_idx_dvsr_p]; 1582 1583 for(frm_num = 0; frm_num < MAX_NUM_ME_PARALLEL; frm_num++) 1584 { 1585 if(me_frm_id != frm_num) 1586 { 1587 me_frm_ctxt_t *ps_me_tmp_frm_ctxt; 1588 1589 l0_dyn_range_prms_t *ps_dyn_range_prms; 1590 1591 ps_me_tmp_frm_ctxt = 1592 ps_master_ctxt->aps_me_ctxt[num_thrds]->aps_me_frm_prms[frm_num]; 1593 1594 /* get current thrd dynamical search range param. pointer */ 1595 ps_dyn_range_prms = &ps_me_tmp_frm_ctxt->as_l0_dyn_range_prms[i4_idx_dvsr_p]; 1596 1597 memcpy(ps_dyn_range_prms, ps_dyn_range_prms_thrd0, sizeof(l0_dyn_range_prms_t)); 1598 } 1599 } 1600 } 1601 } 1602