Home | History | Annotate | Download | only in decoder
      1 /******************************************************************************
      2 *
      3 * Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore
      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 /**
     19  *******************************************************************************
     20  * @file
     21  *  ihevcd_get_mv.c
     22  *
     23  * @brief
     24  *  Contains functions to compute motion vectors
     25  *
     26  * @author
     27  *  Ittiam
     28  *
     29  * @par List of Functions:
     30  * - ihevcd_get_mv_ctb()
     31  *
     32  * @remarks
     33  *  None
     34  *
     35  *******************************************************************************
     36  */
     37 /*****************************************************************************/
     38 /* File Includes                                                             */
     39 /*****************************************************************************/
     40 
     41 #include <stdio.h>
     42 #include <stddef.h>
     43 #include <stdlib.h>
     44 #include <string.h>
     45 
     46 #include "ihevc_typedefs.h"
     47 #include "iv.h"
     48 #include "ivd.h"
     49 #include "ihevcd_cxa.h"
     50 #include "ithread.h"
     51 
     52 #include "ihevc_defs.h"
     53 #include "ihevc_debug.h"
     54 #include "ihevc_structs.h"
     55 #include "ihevc_macros.h"
     56 #include "ihevc_platform_macros.h"
     57 #include "ihevc_cabac_tables.h"
     58 #include "ihevc_disp_mgr.h"
     59 #include "ihevc_buf_mgr.h"
     60 #include "ihevc_dpb_mgr.h"
     61 
     62 #include "ihevcd_defs.h"
     63 #include "ihevcd_function_selector.h"
     64 #include "ihevcd_structs.h"
     65 #include "ihevcd_error.h"
     66 #include "ihevcd_nal.h"
     67 #include "ihevcd_bitstream.h"
     68 #include "ihevcd_fmt_conv.h"
     69 #include "ihevcd_job_queue.h"
     70 #include "ihevcd_debug.h"
     71 #include "ihevcd_mv_merge.h"
     72 #include "ihevcd_mv_pred.h"
     73 #include "ihevcd_profile.h"
     74 /**
     75  *******************************************************************************
     76  *
     77  * @brief
     78  * This function computes and stores MV's of all the PU's in CTB
     79  *
     80  * @par Description:
     81  * MV's of a PU will be stored in PU structure. MV computation can be merge or mv pred
     82  *
     83  * @param[in] ps_proc
     84  * processor context
     85  *
     86  * @param[in] pi4_ctb_top_pu_idx
     87  * Pointer to ctb top PU indices
     88  *
     89  * @param[in] pi4_ctb_left_pu_idx
     90  * Pointer to ctb left PU indices
     91  *
     92  * @param[in] pi4_ctb_top_left_pu_idx
     93  * Pointer to ctb top left PU indices
     94  *
     95  * @returns
     96  * number of PU's per ctb
     97  *
     98  * @remarks
     99  *
    100  *
    101  *******************************************************************************
    102  */
    103 
    104 WORD32 ihevcd_get_mv_ctb(mv_ctxt_t *ps_mv_ctxt,
    105                          UWORD32 *pu4_ctb_top_pu_idx,
    106                          UWORD32 *pu4_ctb_left_pu_idx,
    107                          UWORD32 *pu4_ctb_top_left_pu_idx)
    108 {
    109 
    110     WORD32 i;
    111     sps_t *ps_sps;
    112     pps_t *ps_pps;
    113     pu_t *ps_pu;
    114     tile_t *ps_tile;
    115     UWORD8 *pu1_pic_pu_map_ctb;
    116     WORD32 num_minpu_in_ctb;
    117     WORD32 ctb_start_pu_idx;
    118     UWORD32 *pu4_top_pu_idx, *pu4_left_pu_idx, *pu4_top_left_pu_idx;
    119     WORD32 pu_x_in_4x4, pu_y_in_4x4;
    120     WORD32 pu_x_in_4x4_single_mcl, pu_y_in_4x4_single_mcl;
    121     pu_mv_t s_pred_mv;
    122     WORD32 ctb_size, ctb_size_in_min_pu;
    123     WORD32 num_pu_per_ctb, pu_wd, pu_ht, pu_cnt;
    124     WORD32  pu_wd_single_mcl, pu_ht_single_mcl;
    125     UWORD32 au4_nbr_avail[MAX_CTB_SIZE / MIN_PU_SIZE
    126                     + 2 /* Top nbr + bot nbr */];
    127     UWORD32 *pu4_nbr_pu_idx/* (Left + ctb_size + right ) * (top + ctb_size + bottom) */;
    128     WORD32 top_avail_bits;
    129     UWORD8 u1_lb_avail, u1_l_avail, u1_t_avail, u1_tr_avail, u1_tl_avail;
    130     WORD32 nbr_pu_idx_strd;
    131     WORD32 cb_size;
    132     WORD32 single_mcl_flag;
    133 
    134     PROFILE_DISABLE_MV_PREDICTION();
    135     ps_sps = ps_mv_ctxt->ps_sps;
    136     ps_pps = ps_mv_ctxt->ps_pps;
    137     ps_pu = ps_mv_ctxt->ps_pu;
    138     ps_tile = ps_mv_ctxt->ps_tile;
    139 
    140     pu4_nbr_pu_idx = ps_mv_ctxt->pu4_pic_pu_idx_map;
    141 
    142     ctb_size = (1 << ps_sps->i1_log2_ctb_size);
    143 
    144     ctb_size_in_min_pu = (ctb_size / MIN_PU_SIZE);
    145 
    146     num_minpu_in_ctb = ctb_size_in_min_pu * ctb_size_in_min_pu;
    147     pu1_pic_pu_map_ctb = ps_mv_ctxt->pu1_pic_pu_map + (ps_mv_ctxt->i4_ctb_x + ps_mv_ctxt->i4_ctb_y * ps_sps->i2_pic_wd_in_ctb) * num_minpu_in_ctb;
    148 
    149     num_pu_per_ctb = ps_mv_ctxt->i4_ctb_pu_cnt;
    150     ctb_start_pu_idx = ps_mv_ctxt->i4_ctb_start_pu_idx;
    151     nbr_pu_idx_strd = MAX_CTB_SIZE / MIN_PU_SIZE + 2;
    152 
    153     {
    154         /* Updating the initial availability map */
    155         WORD32 i;
    156         UWORD32 u4_left_ctb_avail, u4_top_lt_ctb_avail, u4_top_rt_ctb_avail,
    157                         u4_top_ctb_avail;
    158 
    159         u4_left_ctb_avail = ps_mv_ctxt->u1_left_ctb_avail;
    160         u4_top_lt_ctb_avail = ps_mv_ctxt->u1_top_lt_ctb_avail;
    161         u4_top_ctb_avail = ps_mv_ctxt->u1_top_ctb_avail;
    162         u4_top_rt_ctb_avail = ps_mv_ctxt->u1_top_rt_ctb_avail;
    163 
    164         /* Initializing the availability array */
    165         memset(au4_nbr_avail, 0,
    166                (MAX_CTB_SIZE / MIN_PU_SIZE + 2) * sizeof(UWORD32));
    167         /* Initializing the availability array with CTB level availability flags */
    168         {
    169             WORD32 rows_remaining = ps_sps->i2_pic_height_in_luma_samples
    170                             - (ps_mv_ctxt->i4_ctb_y << ps_sps->i1_log2_ctb_size);
    171             WORD32 ctb_size_left = MIN(ctb_size, rows_remaining);
    172             for(i = 0; i < ctb_size_left / MIN_PU_SIZE; i++)
    173             {
    174                 au4_nbr_avail[i + 1] = (u4_left_ctb_avail << 31);
    175             }
    176         }
    177         au4_nbr_avail[0] |= ((u4_top_rt_ctb_avail << 31)
    178                         >> (1 + ctb_size_in_min_pu)); /* 1+ctb_size/4 position bit pos from msb */
    179 
    180         au4_nbr_avail[0] |= (u4_top_lt_ctb_avail << 31);
    181         {
    182             WORD32 cols_remaining = ps_sps->i2_pic_width_in_luma_samples
    183                             - (ps_mv_ctxt->i4_ctb_x << ps_sps->i1_log2_ctb_size);
    184             WORD32 ctb_size_top = MIN(ctb_size, cols_remaining);
    185             WORD32 shift = (31 - (ctb_size / MIN_TU_SIZE));
    186 
    187             /* ctb_size_top gives number of valid pixels remaining in the current row */
    188             /* Since we need pattern of 1's starting from the MSB, an additional shift */
    189             /* is needed */
    190             shift += ((ctb_size - ctb_size_top) / MIN_TU_SIZE);
    191 
    192             top_avail_bits = ((1 << (ctb_size_top / MIN_PU_SIZE)) - 1) << shift;
    193         }
    194 
    195         au4_nbr_avail[0] |= ((u4_top_ctb_avail == 1) ? top_avail_bits : 0x0);
    196         /* Starting from msb 2nd bit to (1+ctb_size/4) bit, set 1 if top avail,or 0 */
    197 
    198     }
    199 
    200     {
    201         /* In case of a  tile boundary, left and top arrays must change*/
    202         /*Left*/
    203         /* If start of tile row*/
    204         if(((ps_tile->u1_pos_x) == (ps_mv_ctxt->i4_ctb_x)) && (ps_mv_ctxt->i4_ctb_x != 0))
    205         {
    206             WORD32 index_pic_map;
    207             WORD32 ctb_pu_idx;
    208             UWORD8 *pu1_pic_pu_map;
    209 
    210             /* Goto the left ctb which belongs to another tile */
    211             index_pic_map = ((ps_mv_ctxt->i4_ctb_x - 1) + ps_mv_ctxt->i4_ctb_y * ps_sps->i2_pic_wd_in_ctb);
    212             ctb_pu_idx = ps_mv_ctxt->pu4_pic_pu_idx[index_pic_map];
    213             index_pic_map *= num_minpu_in_ctb;
    214 
    215             /*Replicate the PUs of the last column of the left ctb*/
    216             pu1_pic_pu_map = ps_mv_ctxt->pu1_pic_pu_map + index_pic_map + ctb_size_in_min_pu - 1;
    217             for(i = 0; i < ctb_size_in_min_pu; i++)
    218             {
    219                 /* Left neighbors change*/
    220                 pu4_ctb_left_pu_idx[i] = ctb_pu_idx + (WORD32)*pu1_pic_pu_map;
    221                 pu1_pic_pu_map = pu1_pic_pu_map + ctb_size_in_min_pu;
    222             }
    223 
    224 
    225             index_pic_map = ((ps_mv_ctxt->i4_ctb_x - 1) + (ps_mv_ctxt->i4_ctb_y - 1) * ps_sps->i2_pic_wd_in_ctb);
    226             ctb_pu_idx = ps_mv_ctxt->pu4_pic_pu_idx[index_pic_map];
    227             index_pic_map *= num_minpu_in_ctb;
    228             index_pic_map += (num_minpu_in_ctb - 1);
    229             pu4_ctb_top_left_pu_idx[0] = ctb_pu_idx + pu1_pic_pu_map[index_pic_map];
    230         }
    231         /*Top*/
    232         /* If start of tile column*/
    233         if(((ps_tile->u1_pos_y) == (ps_mv_ctxt->i4_ctb_y)) && (ps_mv_ctxt->i4_ctb_y != 0))
    234         {
    235             WORD32 index_pic_map;
    236             WORD32 ctb_pu_idx;
    237             UWORD8 *pu1_pic_pu_map;
    238 
    239             /* Goto the top ctb which belongs to another tile */
    240             index_pic_map =  (ps_mv_ctxt->i4_ctb_x) + ((ps_mv_ctxt->i4_ctb_y - 1) * ps_sps->i2_pic_wd_in_ctb);
    241             ctb_pu_idx = ps_mv_ctxt->pu4_pic_pu_idx[index_pic_map];
    242             index_pic_map *= num_minpu_in_ctb;
    243 
    244             /*Replicate the PUs of the last row of the top ctb*/
    245             pu1_pic_pu_map = ps_mv_ctxt->pu1_pic_pu_map + index_pic_map + (ctb_size_in_min_pu * (ctb_size_in_min_pu - 1));
    246             for(i = 0; i < ctb_size_in_min_pu; i++)
    247             {
    248                 /* Top neighbors change*/
    249                 pu4_ctb_top_pu_idx[i] = ctb_pu_idx + (WORD32)*pu1_pic_pu_map;
    250                 pu1_pic_pu_map++;
    251             }
    252         }
    253 
    254         /* Updating the initial neighbor pu idx map */
    255         /* Initializing the availability array with CTB level availability flags */
    256         /* 16x16 array for holding pu info of the ctb, wrt the frame pu count*/
    257         for(i = 0; i < ctb_size_in_min_pu; i++)
    258         {
    259             /* Left */
    260             pu4_nbr_pu_idx[(i + 1) * nbr_pu_idx_strd] = pu4_ctb_left_pu_idx[i];
    261             /* Top */
    262             pu4_nbr_pu_idx[i + 1] = pu4_ctb_top_pu_idx[i];
    263         }
    264         /* Top right */
    265         pu4_nbr_pu_idx[1 + ctb_size_in_min_pu] = pu4_ctb_top_pu_idx[ctb_size_in_min_pu];
    266 
    267         /* Top left */
    268         pu4_nbr_pu_idx[0] = pu4_ctb_top_left_pu_idx[0];
    269 
    270     }
    271 
    272     /* CTB level MV pred */
    273     for(pu_cnt = 0; pu_cnt < num_pu_per_ctb; pu_cnt++, ps_pu++)
    274     {
    275         pu_ht = (ps_pu->b4_ht + 1) << 2;
    276         pu_wd = (ps_pu->b4_wd + 1) << 2;
    277 
    278         pu_ht_single_mcl = pu_ht;
    279         pu_wd_single_mcl = pu_wd;
    280 
    281         pu_x_in_4x4 = ps_pu->b4_pos_x;
    282         pu_y_in_4x4 = ps_pu->b4_pos_y;
    283 
    284         pu_x_in_4x4_single_mcl = pu_x_in_4x4;
    285         pu_y_in_4x4_single_mcl = pu_y_in_4x4;
    286 
    287         /*******************************************/
    288         /* Neighbor location: Graphical indication */
    289         /*                                         */
    290         /*          B2 _____________B1 B0          */
    291         /*            |               |            */
    292         /*            |               |            */
    293         /*            |               |            */
    294         /*            |      PU     ht|            */
    295         /*            |               |            */
    296         /*            |               |            */
    297         /*          A1|______wd_______|            */
    298         /*          A0                             */
    299         /*                                         */
    300         /*******************************************/
    301         /* Below code is for merge mode, where if single_mcl_flag == 1,
    302          * all the prediction units of the current coding unit share a
    303          * single merge candidate list, which is identical to the
    304          * merge candidate list of the 2Nx2N prediction unit.
    305          */
    306         single_mcl_flag = 0;
    307         if(1 == ps_pu->b1_merge_flag)
    308         {
    309             cb_size = MAX(pu_wd_single_mcl, pu_ht_single_mcl);
    310             cb_size = MAX(cb_size,
    311                           (1 << ps_sps->i1_log2_min_coding_block_size));
    312             if((ps_pps->i1_log2_parallel_merge_level > 2) && cb_size == 8 && (pu_wd_single_mcl != pu_ht_single_mcl))
    313             {
    314                 single_mcl_flag = 1;
    315                 if((PART_Nx2N == ps_pu->b3_part_mode) && (1 == ps_pu->b2_part_idx))
    316                 {
    317                     pu_x_in_4x4_single_mcl = pu_x_in_4x4_single_mcl - 1;
    318                 }
    319                 else if((PART_2NxN == ps_pu->b3_part_mode) && (1 == ps_pu->b2_part_idx))
    320                 {
    321                     pu_y_in_4x4_single_mcl = pu_y_in_4x4_single_mcl - 1;
    322                 }
    323                 pu_ht_single_mcl = 8;
    324                 pu_wd_single_mcl = 8;
    325             }
    326         }
    327         pu4_top_pu_idx = &pu4_nbr_pu_idx[(1 + pu_x_in_4x4_single_mcl)
    328                         + (1 + pu_y_in_4x4_single_mcl - 1) * nbr_pu_idx_strd];
    329         pu4_top_left_pu_idx = pu4_top_pu_idx - 1;
    330         pu4_left_pu_idx = pu4_top_pu_idx - 1 + nbr_pu_idx_strd;
    331 
    332         /* Get neibhbor availability */
    333         {
    334             u1_lb_avail = (au4_nbr_avail[1 + pu_y_in_4x4_single_mcl + pu_ht_single_mcl / MIN_PU_SIZE]
    335                             >> (31 - (1 + pu_x_in_4x4_single_mcl - 1))) & 1;
    336             u1_l_avail = (au4_nbr_avail[1 + pu_y_in_4x4_single_mcl]
    337                             >> (31 - (1 + pu_x_in_4x4_single_mcl - 1))) & 1;
    338             u1_t_avail = (au4_nbr_avail[1 + pu_y_in_4x4_single_mcl - 1]
    339                             >> (31 - (1 + pu_x_in_4x4_single_mcl))) & 1;
    340             u1_tr_avail = (au4_nbr_avail[1 + pu_y_in_4x4_single_mcl - 1]
    341                             >> (31 - (1 + pu_x_in_4x4_single_mcl + pu_wd_single_mcl / MIN_PU_SIZE)))
    342                             & 1;
    343             u1_tl_avail = (au4_nbr_avail[1 + pu_y_in_4x4_single_mcl - 1]
    344                             >> (31 - (1 + pu_x_in_4x4_single_mcl - 1))) & 1;
    345         }
    346         if(ps_pu->b1_intra_flag == 0)
    347         {
    348             if(ps_pu->b1_merge_flag == 0)
    349             {
    350                 WORD32 pred_flag_l0, pred_flag_l1;
    351                 WORD32 tmp_x, tmp_y, mvd_x, mvd_y, mvp_x, mvp_y;
    352                 WORD32 two_pow_16, two_pow_15;
    353 
    354                 ihevcd_mv_pred(ps_mv_ctxt, pu4_top_pu_idx, pu4_left_pu_idx,
    355                                pu4_top_left_pu_idx, nbr_pu_idx_strd,
    356                                ps_pu, u1_lb_avail, u1_l_avail,
    357                                u1_tr_avail, u1_t_avail, u1_tl_avail,
    358                                &s_pred_mv);
    359 
    360                 pred_flag_l0 = (ps_pu->b2_pred_mode != PRED_L1);
    361                 pred_flag_l1 = (ps_pu->b2_pred_mode != PRED_L0);
    362 
    363                 two_pow_16 = (1 << 16);
    364                 two_pow_15 = (1 << 15);
    365 
    366                 /* L0 MV */
    367                 if(pred_flag_l0)
    368                 {
    369                     mvp_x = s_pred_mv.s_l0_mv.i2_mvx;
    370                     mvp_y = s_pred_mv.s_l0_mv.i2_mvy;
    371                     mvd_x = ps_pu->mv.s_l0_mv.i2_mvx;
    372                     mvd_y = ps_pu->mv.s_l0_mv.i2_mvy;
    373 
    374                     tmp_x = (mvp_x + mvd_x + two_pow_16) & (two_pow_16 - 1);
    375                     tmp_x = tmp_x >= two_pow_15 ?
    376                                     (tmp_x - two_pow_16) : tmp_x;
    377                     ps_pu->mv.s_l0_mv.i2_mvx = tmp_x;
    378                     tmp_y = (mvp_y + mvd_y + two_pow_16) & (two_pow_16 - 1);
    379                     tmp_y = tmp_y >= two_pow_15 ?
    380                                     (tmp_y - two_pow_16) : tmp_y;
    381                     ps_pu->mv.s_l0_mv.i2_mvy = tmp_y;
    382                 }
    383                 /* L1 MV */
    384                 if(pred_flag_l1)
    385                 {
    386                     mvp_x = s_pred_mv.s_l1_mv.i2_mvx;
    387                     mvp_y = s_pred_mv.s_l1_mv.i2_mvy;
    388                     mvd_x = ps_pu->mv.s_l1_mv.i2_mvx;
    389                     mvd_y = ps_pu->mv.s_l1_mv.i2_mvy;
    390 
    391                     tmp_x = (mvp_x + mvd_x + two_pow_16) & (two_pow_16 - 1);
    392                     tmp_x = tmp_x >= two_pow_15 ?
    393                                     (tmp_x - two_pow_16) : tmp_x;
    394                     ps_pu->mv.s_l1_mv.i2_mvx = tmp_x;
    395                     tmp_y = (mvp_y + mvd_y + two_pow_16) & (two_pow_16 - 1);
    396                     tmp_y = tmp_y >= two_pow_15 ?
    397                                     (tmp_y - two_pow_16) : tmp_y;
    398                     ps_pu->mv.s_l1_mv.i2_mvy = tmp_y;
    399                 }
    400             }
    401             else
    402             {
    403                 WORD32 part_mode;
    404                 WORD32 part_idx;
    405                 part_mode = ps_pu->b3_part_mode;
    406                 //TODO: Get part_idx
    407                 part_idx = ps_pu->b2_part_idx;
    408 
    409                 ihevcd_mv_merge(ps_mv_ctxt, pu4_top_pu_idx, pu4_left_pu_idx,
    410                                 nbr_pu_idx_strd, ps_pu, part_mode,
    411                                 part_idx, pu_wd_single_mcl, pu_ht_single_mcl,
    412                                 pu_x_in_4x4_single_mcl << 2, pu_y_in_4x4_single_mcl << 2,
    413                                 single_mcl_flag, u1_lb_avail, u1_l_avail, u1_tr_avail,
    414                                 u1_t_avail, u1_tl_avail);
    415 
    416                 if(PRED_BI == ps_pu->b2_pred_mode)
    417                 {
    418                     if(((ps_pu->b3_part_mode == PART_2NxN) && (pu_wd == 8))
    419                                     || ((ps_pu->b3_part_mode == PART_Nx2N)
    420                                                     && (pu_ht == 8)))
    421                     {
    422                         ps_pu->b2_pred_mode = PRED_L0;
    423                     }
    424                 }
    425             }
    426         }
    427 
    428         {
    429             slice_header_t *ps_slice_hdr;
    430             pic_buf_t *ps_pic_buf_l0, *ps_pic_buf_l1;
    431             ps_slice_hdr = ps_mv_ctxt->ps_slice_hdr;
    432             ps_pic_buf_l0 = (pic_buf_t *)((ps_slice_hdr->as_ref_pic_list0[ps_pu->mv.i1_l0_ref_idx].pv_pic_buf));
    433             ps_pic_buf_l1 = (pic_buf_t *)((ps_slice_hdr->as_ref_pic_list1[ps_pu->mv.i1_l1_ref_idx].pv_pic_buf));
    434             ps_pu->mv.i1_l0_ref_pic_buf_id = ps_pic_buf_l0->u1_buf_id;
    435             if(BSLICE == ps_slice_hdr->i1_slice_type)
    436             {
    437                 ps_pu->mv.i1_l1_ref_pic_buf_id = ps_pic_buf_l1->u1_buf_id;
    438             }
    439         }
    440 
    441         /* Neighbor availability inside CTB */
    442         /* 1bit per 4x4. Indicates whether that 4x4 block has been reconstructed(avialable) */
    443         /* Used for neighbor availability in intra pred */
    444         {
    445             WORD32 trans_in_min_tu;
    446             UWORD32 cur_tu_in_bits;
    447             UWORD32 cur_tu_avail_flag;
    448 
    449             trans_in_min_tu = pu_wd / MIN_PU_SIZE;
    450             cur_tu_in_bits = (1 << trans_in_min_tu) - 1;
    451             cur_tu_in_bits = cur_tu_in_bits << (32 - trans_in_min_tu);
    452 
    453             cur_tu_avail_flag = cur_tu_in_bits >> (pu_x_in_4x4 + 1);
    454 
    455             for(i = 0; i < pu_ht / MIN_PU_SIZE; i++)
    456                 au4_nbr_avail[1 + pu_y_in_4x4 + i] |= cur_tu_avail_flag;
    457         }
    458 
    459         /* Neighbor PU idx update inside CTB */
    460         /* 1byte per 4x4. Indicates the PU idx that 4x4 block belongs to */
    461 
    462         {
    463             WORD32 row, col;
    464             UWORD32 cur_pu_idx;
    465             WORD32 offset;
    466             cur_pu_idx = ctb_start_pu_idx + pu_cnt;
    467 
    468             offset = (1 + pu_x_in_4x4 + 0) + (1 + pu_y_in_4x4 + 0) * nbr_pu_idx_strd;
    469 
    470             for(row = 0; row < pu_ht / MIN_PU_SIZE; row++)
    471             {
    472                 for(col = 0; col < pu_wd / MIN_PU_SIZE; col++)
    473                 {
    474                     pu4_nbr_pu_idx[offset + col] = cur_pu_idx;
    475                 }
    476                 offset += nbr_pu_idx_strd;
    477             }
    478         }
    479 
    480     }
    481 
    482     /* Updating Top and Left pointers */
    483     {
    484         WORD32 offset_top, offset_left;
    485 
    486         offset_left = ctb_size_in_min_pu + (0 + 1) * nbr_pu_idx_strd;
    487         offset_top = ctb_size_in_min_pu * nbr_pu_idx_strd + 0 + 1;
    488 
    489         /* Top Left */
    490         /* saving top left before updating top ptr, as updating top ptr will overwrite the top left for the next ctb */
    491         pu4_ctb_top_left_pu_idx[0] = pu4_ctb_top_pu_idx[ctb_size_in_min_pu - 1];
    492 
    493         for(i = 0; i < ctb_size_in_min_pu; i++)
    494         {
    495             /* Left */
    496             /* Last column of au4_nbr_pu_idx */
    497             pu4_ctb_left_pu_idx[i] = pu4_nbr_pu_idx[offset_left];
    498             /* Top */
    499             /* Last row of au4_nbr_pu_idx */
    500             pu4_ctb_top_pu_idx[i] = pu4_nbr_pu_idx[offset_top];
    501 
    502             offset_left += nbr_pu_idx_strd;
    503             offset_top += 1;
    504         }
    505     }
    506 
    507     /* Updating the CTB level PU idx (Used for collocated MV pred)*/
    508     {
    509         WORD32 ctb_row, ctb_col, index_pic_map, index_nbr_map;
    510         WORD32 first_pu_of_ctb;
    511         first_pu_of_ctb = pu4_nbr_pu_idx[1 + nbr_pu_idx_strd];
    512 
    513         index_pic_map = 0 * ctb_size_in_min_pu + 0;
    514         index_nbr_map = (0 + 1) * nbr_pu_idx_strd + (0 + 1);
    515 
    516         for(ctb_row = 0; ctb_row < ctb_size_in_min_pu; ctb_row++)
    517         {
    518             for(ctb_col = 0; ctb_col < ctb_size_in_min_pu; ctb_col++)
    519             {
    520                 pu1_pic_pu_map_ctb[index_pic_map + ctb_col] = pu4_nbr_pu_idx[index_nbr_map + ctb_col]
    521                                 - first_pu_of_ctb;
    522             }
    523             index_pic_map += ctb_size_in_min_pu;
    524             index_nbr_map += nbr_pu_idx_strd;
    525         }
    526     }
    527     return num_pu_per_ctb;
    528 }
    529