• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
ihevcd_get_mv_ctb(mv_ctxt_t * ps_mv_ctxt,UWORD32 * pu4_ctb_top_pu_idx,UWORD32 * pu4_ctb_left_pu_idx,UWORD32 * pu4_ctb_top_left_pu_idx)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          UWORD32 cur_ctb_ht_in_min_pu = MIN(((ps_sps->i2_pic_height_in_luma_samples
513                      - (ps_mv_ctxt->i4_ctb_y << ps_sps->i1_log2_ctb_size)) / MIN_PU_SIZE), ctb_size_in_min_pu);
514          UWORD32 cur_ctb_wd_in_min_pu = MIN(((ps_sps->i2_pic_width_in_luma_samples
515                      - (ps_mv_ctxt->i4_ctb_x << ps_sps->i1_log2_ctb_size)) / MIN_PU_SIZE), ctb_size_in_min_pu);
516  
517          index_pic_map = 0 * ctb_size_in_min_pu + 0;
518          index_nbr_map = (0 + 1) * nbr_pu_idx_strd + (0 + 1);
519  
520          for(ctb_row = 0; ctb_row < cur_ctb_ht_in_min_pu; ctb_row++)
521          {
522              for(ctb_col = 0; ctb_col < cur_ctb_wd_in_min_pu; ctb_col++)
523              {
524                  pu1_pic_pu_map_ctb[index_pic_map + ctb_col] = pu4_nbr_pu_idx[index_nbr_map + ctb_col]
525                                  - first_pu_of_ctb;
526              }
527              index_pic_map += ctb_size_in_min_pu;
528              index_nbr_map += nbr_pu_idx_strd;
529          }
530      }
531      return num_pu_per_ctb;
532  }
533