Home | History | Annotate | Download | only in encoder
      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