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_mv_pred.c
     22  *
     23  * @brief
     24  *  Contains functions for motion vector prediction
     25  *
     26  * @author
     27  *  Ittiam
     28  *
     29  * @par List of Functions:
     30  * - ihevcd_scale_mv()
     31  * - ihevcd_mv_pred()
     32  *
     33  * @remarks
     34  *  None
     35  *
     36  *******************************************************************************
     37  */
     38 /*****************************************************************************/
     39 /* File Includes                                                             */
     40 /*****************************************************************************/
     41 
     42 #include <stdio.h>
     43 #include <stddef.h>
     44 #include <stdlib.h>
     45 #include <string.h>
     46 
     47 #include "ihevc_typedefs.h"
     48 #include "iv.h"
     49 #include "ivd.h"
     50 #include "ihevcd_cxa.h"
     51 #include "ithread.h"
     52 
     53 #include "ihevc_defs.h"
     54 #include "ihevc_debug.h"
     55 #include "ihevc_structs.h"
     56 #include "ihevc_macros.h"
     57 #include "ihevc_platform_macros.h"
     58 #include "ihevc_cabac_tables.h"
     59 #include "ihevc_disp_mgr.h"
     60 #include "ihevc_buf_mgr.h"
     61 #include "ihevc_dpb_mgr.h"
     62 
     63 #include "ihevcd_defs.h"
     64 #include "ihevcd_function_selector.h"
     65 #include "ihevcd_structs.h"
     66 #include "ihevcd_error.h"
     67 #include "ihevcd_nal.h"
     68 #include "ihevcd_bitstream.h"
     69 #include "ihevcd_fmt_conv.h"
     70 #include "ihevcd_job_queue.h"
     71 #include "ihevcd_debug.h"
     72 #include "ihevcd_mv_merge.h"
     73 
     74 /**
     75  *******************************************************************************
     76  *
     77  * @brief Function scaling motion vector
     78  *
     79  *
     80  * @par Description:
     81  *   Scales mv based on difference between current POC and current
     82  *   reference POC and neighbour reference poc
     83  *
     84  * @param[inout] mv
     85  *   motion vector to be scaled
     86  *
     87  * @param[in] cur_ref_poc
     88  *   Current PU refernce pic poc
     89  *
     90  * @param[in] nbr_ref_poc
     91  *   Neighbor PU reference pic poc
     92  *
     93  * @param[in] cur_poc
     94  *   Picture order count of current pic
     95  *
     96  * @returns
     97  *  None
     98  *
     99  * @remarks
    100  *
    101  *******************************************************************************
    102  */
    103 void ihevcd_scale_mv(mv_t *ps_mv,
    104                      WORD32 cur_ref_poc,
    105                      WORD32 nbr_ref_poc,
    106                      WORD32 cur_poc)
    107 {
    108     WORD32 td, tb, tx;
    109     WORD32 dist_scale_factor;
    110     WORD32 mvx, mvy;
    111 
    112     td = CLIP_S8(cur_poc - nbr_ref_poc);
    113     tb = CLIP_S8(cur_poc - cur_ref_poc);
    114 
    115     if(0 != td)
    116     {
    117         tx = (16384 + (abs(td) >> 1)) / td;
    118 
    119         dist_scale_factor = (tb * tx + 32) >> 6;
    120         dist_scale_factor = CLIP3(dist_scale_factor, -4096, 4095);
    121 
    122         mvx = ps_mv->i2_mvx;
    123         mvy = ps_mv->i2_mvy;
    124 
    125         mvx = SIGN(dist_scale_factor * mvx)
    126                         * ((abs(dist_scale_factor * mvx) + 127) >> 8);
    127         mvy = SIGN(dist_scale_factor * mvy)
    128                         * ((abs(dist_scale_factor * mvy) + 127) >> 8);
    129 
    130         ps_mv->i2_mvx = CLIP_S16(mvx);
    131         ps_mv->i2_mvy = CLIP_S16(mvy);
    132     }
    133 }
    134 
    135 /**
    136  *******************************************************************************
    137  *
    138  * @brief Function scaling temporal motion vector
    139  *
    140  *
    141  * @par Description:
    142  *   Scales mv based on difference between current POC and current
    143  *   reference POC and neighbour reference poc
    144  *
    145  * @param[inout] mv
    146  *   motion vector to be scaled
    147  *
    148  * @param[in] cur_ref_poc
    149  *   Current PU refernce pic poc
    150  *
    151  * @param[in] nbr_ref_poc
    152  *   Neighbor PU reference pic poc
    153  *
    154  * @param[in] cur_poc
    155  *   Picture order count of current pic
    156  *
    157  * @returns
    158  *  None
    159  *
    160  * @remarks
    161  *
    162  *******************************************************************************
    163  */
    164 void ihevcd_scale_collocated_mv(mv_t *ps_mv,
    165                                 WORD32 cur_ref_poc,
    166                                 WORD32 col_ref_poc,
    167                                 WORD32 col_poc,
    168                                 WORD32 cur_poc)
    169 {
    170     WORD32 td, tb, tx;
    171     WORD32 dist_scale_factor;
    172     WORD32 mvx, mvy;
    173 
    174     td = CLIP_S8(col_poc - col_ref_poc);
    175     tb = CLIP_S8(cur_poc - cur_ref_poc);
    176 
    177     tx = (16384 + (abs(td) >> 1)) / td;
    178 
    179     dist_scale_factor = (tb * tx + 32) >> 6;
    180     dist_scale_factor = CLIP3(dist_scale_factor, -4096, 4095);
    181 
    182     mvx = ps_mv->i2_mvx;
    183     mvy = ps_mv->i2_mvy;
    184 
    185     mvx = SIGN(dist_scale_factor * mvx)
    186                     * ((abs(dist_scale_factor * mvx) + 127) >> 8);
    187     mvy = SIGN(dist_scale_factor * mvy)
    188                     * ((abs(dist_scale_factor * mvy) + 127) >> 8);
    189 
    190     ps_mv->i2_mvx = CLIP_S16(mvx);
    191     ps_mv->i2_mvy = CLIP_S16(mvy);
    192 }
    193 
    194 #define CHECK_NBR_MV_ST(pi4_avail_flag, cur_ref_poc, u1_nbr_pred_flag, nbr_ref_poc,         \
    195                         ps_mv, ps_nbr_mv )                                                  \
    196 {                                                                                           \
    197     if((u1_nbr_pred_flag) && (cur_ref_poc == nbr_ref_poc))                                  \
    198     {                                                                                       \
    199         *pi4_avail_flag = 1;                                                                \
    200         *ps_mv = *ps_nbr_mv;                                                                \
    201         break ;                                                                             \
    202     }                                                                                       \
    203 }
    204 #define CHECK_NBR_MV_LT(pi4_avail_flag, u1_cur_ref_lt, cur_poc, cur_ref_poc,                 \
    205                       u1_nbr_pred_flag, u1_nbr_ref_lt, nbr_ref_poc,                          \
    206                       ps_mv, ps_nbr_mv )                                                     \
    207 {                                                                                            \
    208     WORD32 cur_lt, nbr_lt;                                                                   \
    209     cur_lt = (LONG_TERM_REF == (u1_cur_ref_lt));                                             \
    210     nbr_lt = (LONG_TERM_REF == (u1_nbr_ref_lt));                                             \
    211     if((u1_nbr_pred_flag) && (cur_lt == nbr_lt))                                             \
    212     {                                                                                        \
    213         *pi4_avail_flag = 1;                                                                 \
    214         *ps_mv = *ps_nbr_mv;                                                                 \
    215         if(SHORT_TERM_REF == u1_nbr_ref_lt)                                                  \
    216         {                                                                                    \
    217             ihevcd_scale_mv(ps_mv, cur_ref_poc, nbr_ref_poc,                                 \
    218                                                 cur_poc);                                    \
    219         }                                                                                    \
    220         break ;                                                                              \
    221     }                                                                                        \
    222 }
    223 
    224 
    225 void GET_MV_NBR_ST(ref_list_t **ps_ref_pic_list, WORD32 *pi4_avail_flag, pic_buf_t *ps_cur_pic_buf_lx, pu_t **aps_nbr_pu, mv_t *ps_mv, WORD32 num_nbrs, WORD32 lx)
    226 {
    227     WORD32 i, nbr_pred_lx;
    228     pic_buf_t *ps_nbr_pic_buf_lx;
    229     /* Short Term */
    230     /* L0 */
    231     if(0 == lx)
    232     {
    233         for(i = 0; i < num_nbrs; i++)
    234         {
    235             nbr_pred_lx = (PRED_L1 != aps_nbr_pu[i]->b2_pred_mode);
    236             ps_nbr_pic_buf_lx = (pic_buf_t *)((ps_ref_pic_list[0][aps_nbr_pu[i]->mv.i1_l0_ref_idx].pv_pic_buf));
    237             CHECK_NBR_MV_ST(pi4_avail_flag, ps_cur_pic_buf_lx->i4_abs_poc, nbr_pred_lx,
    238                             ps_nbr_pic_buf_lx->i4_abs_poc, ps_mv, &aps_nbr_pu[i]->mv.s_l0_mv);
    239             nbr_pred_lx = (PRED_L0 != aps_nbr_pu[i]->b2_pred_mode);
    240 
    241             nbr_pred_lx = (PRED_L0 != aps_nbr_pu[i]->b2_pred_mode);
    242             ps_nbr_pic_buf_lx = (pic_buf_t *)((ps_ref_pic_list[1][aps_nbr_pu[i]->mv.i1_l1_ref_idx].pv_pic_buf));
    243             CHECK_NBR_MV_ST(pi4_avail_flag, ps_cur_pic_buf_lx->i4_abs_poc, nbr_pred_lx,
    244                             ps_nbr_pic_buf_lx->i4_abs_poc, ps_mv, &aps_nbr_pu[i]->mv.s_l1_mv);
    245         }
    246     }
    247     /* L1 */
    248     else
    249     {
    250         for(i = 0; i < num_nbrs; i++)
    251         {
    252             nbr_pred_lx = (PRED_L0 != aps_nbr_pu[i]->b2_pred_mode);
    253             ps_nbr_pic_buf_lx = (pic_buf_t *)((ps_ref_pic_list[1][aps_nbr_pu[i]->mv.i1_l1_ref_idx].pv_pic_buf));
    254             CHECK_NBR_MV_ST(pi4_avail_flag, ps_cur_pic_buf_lx->i4_abs_poc, nbr_pred_lx,
    255                             ps_nbr_pic_buf_lx->i4_abs_poc, ps_mv, &aps_nbr_pu[i]->mv.s_l1_mv);
    256 
    257             nbr_pred_lx = (PRED_L1 != aps_nbr_pu[i]->b2_pred_mode);
    258             ps_nbr_pic_buf_lx = (pic_buf_t *)((ps_ref_pic_list[0][aps_nbr_pu[i]->mv.i1_l0_ref_idx].pv_pic_buf));
    259             CHECK_NBR_MV_ST(pi4_avail_flag, ps_cur_pic_buf_lx->i4_abs_poc, nbr_pred_lx,
    260                             ps_nbr_pic_buf_lx->i4_abs_poc, ps_mv, &aps_nbr_pu[i]->mv.s_l0_mv);
    261         }
    262     }
    263 }
    264 
    265 void GET_MV_NBR_LT(ref_list_t **ps_ref_pic_list, slice_header_t *ps_slice_hdr, WORD32 *pi4_avail_flag, pic_buf_t *ps_cur_pic_buf_lx, pu_t **aps_nbr_pu, mv_t *ps_mv, WORD32 num_nbrs, WORD32 lx)
    266 {
    267     WORD32 i, nbr_pred_lx;
    268     pic_buf_t *ps_nbr_pic_buf_lx;
    269     /* Long Term*/
    270     /* L0 */
    271     if(0 == lx)
    272     {
    273         for(i = 0; i < num_nbrs; i++)
    274         {
    275             nbr_pred_lx = (PRED_L1 != aps_nbr_pu[i]->b2_pred_mode);
    276             ps_nbr_pic_buf_lx = (pic_buf_t *)((ps_ref_pic_list[0][aps_nbr_pu[i]->mv.i1_l0_ref_idx].pv_pic_buf));
    277             CHECK_NBR_MV_LT(pi4_avail_flag, ps_cur_pic_buf_lx->u1_used_as_ref, ps_slice_hdr->i4_abs_pic_order_cnt, ps_cur_pic_buf_lx->i4_abs_poc,
    278                             nbr_pred_lx,
    279                             ps_nbr_pic_buf_lx->u1_used_as_ref, ps_nbr_pic_buf_lx->i4_abs_poc,
    280                             ps_mv, &aps_nbr_pu[i]->mv.s_l0_mv);
    281 
    282             nbr_pred_lx = (PRED_L0 != aps_nbr_pu[i]->b2_pred_mode);
    283             ps_nbr_pic_buf_lx = (pic_buf_t *)((ps_ref_pic_list[1][aps_nbr_pu[i]->mv.i1_l1_ref_idx].pv_pic_buf));
    284             CHECK_NBR_MV_LT(pi4_avail_flag, ps_cur_pic_buf_lx->u1_used_as_ref, ps_slice_hdr->i4_abs_pic_order_cnt, ps_cur_pic_buf_lx->i4_abs_poc,
    285                             nbr_pred_lx,
    286                             ps_nbr_pic_buf_lx->u1_used_as_ref, ps_nbr_pic_buf_lx->i4_abs_poc,
    287                             ps_mv, &aps_nbr_pu[i]->mv.s_l1_mv);
    288         }
    289     }
    290     /* L1 */
    291     else
    292     {
    293         for(i = 0; i < num_nbrs; i++)
    294         {
    295             nbr_pred_lx = (PRED_L0 != aps_nbr_pu[i]->b2_pred_mode);
    296             ps_nbr_pic_buf_lx = (pic_buf_t *)((ps_ref_pic_list[1][aps_nbr_pu[i]->mv.i1_l1_ref_idx].pv_pic_buf));
    297             CHECK_NBR_MV_LT(pi4_avail_flag, ps_cur_pic_buf_lx->u1_used_as_ref, ps_slice_hdr->i4_abs_pic_order_cnt, ps_cur_pic_buf_lx->i4_abs_poc,
    298                             nbr_pred_lx,
    299                             ps_nbr_pic_buf_lx->u1_used_as_ref, ps_nbr_pic_buf_lx->i4_abs_poc,
    300                             ps_mv, &aps_nbr_pu[i]->mv.s_l1_mv);
    301 
    302             nbr_pred_lx = (PRED_L1 != aps_nbr_pu[i]->b2_pred_mode);
    303             ps_nbr_pic_buf_lx = (pic_buf_t *)((ps_ref_pic_list[0][aps_nbr_pu[i]->mv.i1_l0_ref_idx].pv_pic_buf));
    304             CHECK_NBR_MV_LT(pi4_avail_flag, ps_cur_pic_buf_lx->u1_used_as_ref, ps_slice_hdr->i4_abs_pic_order_cnt, ps_cur_pic_buf_lx->i4_abs_poc,
    305                             nbr_pred_lx,
    306                             ps_nbr_pic_buf_lx->u1_used_as_ref, ps_nbr_pic_buf_lx->i4_abs_poc,
    307                             ps_mv, &aps_nbr_pu[i]->mv.s_l0_mv);
    308         }
    309     }
    310 }
    311 /**
    312  *******************************************************************************
    313  *
    314  * @brief
    315  * This function performs Motion Vector prediction and return a list of mv
    316  *
    317  * @par Description:
    318  *  MV predictor list is computed using neighbor mvs and colocated mv
    319  *
    320  * @param[in] ps_ctxt
    321  * pointer to mv predictor context
    322  *
    323  * @param[in] ps_top_nbr_4x4
    324  * pointer to top 4x4 nbr structure
    325  *
    326  * @param[in] ps_left_nbr_4x4
    327  * pointer to left 4x4 nbr structure
    328  *
    329  * @param[in] ps_top_left_nbr_4x4
    330  * pointer to top left 4x4 nbr structure
    331  *
    332  * @param[in] left_nbr_4x4_strd
    333  * left nbr buffer stride in terms of 4x4 units
    334  *
    335  * @param[in] ps_avail_flags
    336  * Neighbor availability flags container
    337  *
    338  * @param[in] ps_col_mv
    339  * Colocated MV pointer
    340  *
    341  * @param[in] ps_pu
    342  * Current Partition PU strucrture pointer
    343  *
    344  * @param[inout] ps_pred_mv
    345  * pointer to store predicted MV list
    346  *
    347  * @returns
    348  * None
    349  * @remarks
    350  *
    351  *
    352  *******************************************************************************
    353  */
    354 void ihevcd_mv_pred(mv_ctxt_t *ps_mv_ctxt,
    355                     UWORD32 *pu4_top_pu_idx,
    356                     UWORD32 *pu4_left_pu_idx,
    357                     UWORD32 *pu4_top_left_pu_idx,
    358                     WORD32 left_nbr_4x4_strd,
    359                     pu_t *ps_pu,
    360                     WORD32 lb_avail,
    361                     WORD32 l_avail,
    362                     WORD32 tr_avail,
    363                     WORD32 t_avail,
    364                     WORD32 tl_avail,
    365                     pu_mv_t *ps_pred_mv)
    366 {
    367     slice_header_t *ps_slice_hdr;
    368     ref_list_t *ps_ref_pic_list[2];
    369     pu_t *ps_pic_pu;
    370     WORD32 max_l0_mvp_cand, max_l1_mvp_cand;
    371     WORD32 l0_done_flag, l1_done_flag;
    372     WORD32 num_l0_mvp_cand, num_l1_mvp_cand;
    373     WORD32 is_scaled_flag_list /* Indicates whether A0 or A1 is available */;
    374     WORD32 avail_a_flag[2];
    375     mv_t as_mv_a[2];
    376     WORD32 part_pos_x;
    377     WORD32 part_pos_y;
    378     WORD32 part_wd;
    379     WORD32 part_ht;
    380     pic_buf_t *ps_cur_pic_buf_l0, *ps_cur_pic_buf_l1;
    381     WORD32 nbr_avail[3]; /*[A0/A1] */ /* [B0/B1/B2] */
    382     pu_t *aps_nbr_pu[3];  /*[A0/A1] */ /* [B0/B1/B2] */
    383     WORD32 num_nbrs = 0;
    384 
    385     /*******************************************/
    386     /* Neighbor location: Graphical indication */
    387     /*                                         */
    388     /*          B2 _____________B1 B0          */
    389     /*            |               |            */
    390     /*            |               |            */
    391     /*            |               |            */
    392     /*            |      PU     ht|            */
    393     /*            |               |            */
    394     /*            |               |            */
    395     /*          A1|______wd_______|            */
    396     /*          A0                             */
    397     /*                                         */
    398     /*******************************************/
    399 
    400     ps_slice_hdr = ps_mv_ctxt->ps_slice_hdr;
    401     ps_pic_pu = ps_mv_ctxt->ps_pic_pu;
    402     max_l0_mvp_cand = ps_pu->b1_l0_mvp_idx + 1;
    403     max_l1_mvp_cand = ps_pu->b1_l1_mvp_idx + 1;
    404     num_l0_mvp_cand = 0;
    405     num_l1_mvp_cand = 0;
    406 
    407     /* Initializing reference list */
    408     ps_ref_pic_list[0] = ps_slice_hdr->as_ref_pic_list0;
    409     ps_ref_pic_list[1] = ps_slice_hdr->as_ref_pic_list1;
    410     if(PSLICE == ps_slice_hdr->i1_slice_type)
    411         ps_ref_pic_list[1] = ps_slice_hdr->as_ref_pic_list0;
    412 
    413     ps_cur_pic_buf_l0 = (pic_buf_t *)((ps_ref_pic_list[0][ps_pu->mv.i1_l0_ref_idx].pv_pic_buf));
    414     ps_cur_pic_buf_l1 = (pic_buf_t *)((ps_ref_pic_list[1][ps_pu->mv.i1_l1_ref_idx].pv_pic_buf));
    415 
    416     is_scaled_flag_list = 0;
    417 
    418     part_pos_x = ps_pu->b4_pos_x << 2;
    419     part_pos_y = ps_pu->b4_pos_y << 2;
    420     part_wd = (ps_pu->b4_wd + 1) << 2;
    421     part_ht = (ps_pu->b4_ht + 1) << 2;
    422 
    423     /************************************************************/
    424     /* Calculating of motion vector A from neighbors A0 and A1  */
    425     /************************************************************/
    426     {
    427         nbr_avail[0] = 0;
    428         nbr_avail[1] = 0;
    429 
    430         /* Pointers to A0 and A1 */
    431         {
    432             WORD32 y_a0, y_a1;
    433             WORD32 pu_idx_a0, pu_idx_a1;
    434 
    435             /* TODO: y_a0, y_a1 is coded assuming left nbr pointer starts at PU */
    436             y_a0 = (part_ht >> 2);
    437             y_a1 = ((part_ht - 1) >> 2);
    438 
    439             pu_idx_a0 = *(pu4_left_pu_idx + (y_a0 * left_nbr_4x4_strd));
    440             pu_idx_a1 = *(pu4_left_pu_idx + (y_a1 * left_nbr_4x4_strd));
    441 
    442             if(lb_avail && (!ps_pic_pu[pu_idx_a0].b1_intra_flag))
    443             {
    444                 aps_nbr_pu[num_nbrs] = &ps_pic_pu[pu_idx_a0];
    445                 num_nbrs++;
    446                 nbr_avail[0] = 1;
    447             }
    448             if(l_avail && (!ps_pic_pu[pu_idx_a1].b1_intra_flag))
    449             {
    450                 aps_nbr_pu[num_nbrs] = &ps_pic_pu[pu_idx_a1];
    451                 num_nbrs++;
    452                 nbr_avail[1] = 1;
    453             }
    454         }
    455         /* Setting is scaled flag based on availability of A0 and A1 */
    456         if((nbr_avail[0] == 1) || (nbr_avail[1]))
    457         {
    458             is_scaled_flag_list = 1;
    459         }
    460 
    461         avail_a_flag[0] = 0;
    462         avail_a_flag[1] = 0;
    463 
    464         /* L0 */
    465         GET_MV_NBR_ST(ps_ref_pic_list, &avail_a_flag[0], ps_cur_pic_buf_l0, aps_nbr_pu, &as_mv_a[0], num_nbrs, 0);
    466         if(0 == avail_a_flag[0])
    467         {
    468             GET_MV_NBR_LT(ps_ref_pic_list, ps_slice_hdr, &avail_a_flag[0], ps_cur_pic_buf_l0, aps_nbr_pu, &as_mv_a[0], num_nbrs, 0);
    469         }
    470 
    471         /* L1 */
    472         if(PRED_L0 != ps_pu->b2_pred_mode)
    473         {
    474             GET_MV_NBR_ST(ps_ref_pic_list, &avail_a_flag[1], ps_cur_pic_buf_l1, aps_nbr_pu, &as_mv_a[1], num_nbrs, 1);
    475             if(0 == avail_a_flag[1])
    476             {
    477                 GET_MV_NBR_LT(ps_ref_pic_list, ps_slice_hdr, &avail_a_flag[1], ps_cur_pic_buf_l1, aps_nbr_pu, &as_mv_a[1], num_nbrs, 1);
    478             }
    479         }
    480 
    481         l0_done_flag = (PRED_L1 == ps_pu->b2_pred_mode);
    482         l1_done_flag = (PRED_L0 == ps_pu->b2_pred_mode);
    483 
    484         if(avail_a_flag[0])
    485         {
    486             num_l0_mvp_cand++;
    487             if(max_l0_mvp_cand == num_l0_mvp_cand)
    488             {
    489                 ps_pred_mv->s_l0_mv = as_mv_a[0];
    490                 l0_done_flag = 1;
    491             }
    492         }
    493         if(avail_a_flag[1])
    494         {
    495             num_l1_mvp_cand++;
    496             if(max_l1_mvp_cand == num_l1_mvp_cand)
    497             {
    498                 ps_pred_mv->s_l1_mv = as_mv_a[1];
    499                 l1_done_flag = 1;
    500             }
    501         }
    502         if(l0_done_flag && l1_done_flag)
    503             return;
    504     }
    505 
    506     /************************************************************/
    507     /* Calculating of motion vector B from neighbors B0 and B1  */
    508     /************************************************************/
    509     {
    510         WORD32 avail_b_flag[2];
    511         mv_t as_mv_b[2];
    512 
    513         /* Pointers to B0, B1 and B2 */
    514         {
    515             WORD32 x_b0, x_b1, x_b2;
    516             WORD32 pu_idx_b0, pu_idx_b1, pu_idx_b2;
    517 
    518             /* Relative co-ordiante of Xp,Yp w.r.t CTB start will work */
    519             /* as long as minCTB = 16                                  */
    520             x_b0 = (part_pos_x + part_wd);
    521             x_b1 = (part_pos_x + part_wd - 1);
    522             x_b2 = (part_pos_x - 1);
    523             /* Getting offset back to given pointer */
    524             x_b0 = x_b0 - part_pos_x;
    525             x_b1 = x_b1 - part_pos_x;
    526             x_b2 = x_b2 - part_pos_x;
    527 
    528             /* Below derivation are based on top pointer */
    529             /* is pointing first pixel of PU             */
    530             pu_idx_b0 = *(pu4_top_pu_idx + (x_b0 >> 2));
    531             pu_idx_b0 = pu_idx_b0 * tr_avail;
    532             pu_idx_b1 = *(pu4_top_pu_idx + (x_b1 >> 2));
    533             pu_idx_b1 = pu_idx_b1 * t_avail;
    534             /* At CTB boundary, use top-left passed in */
    535             if(part_pos_y)
    536             {
    537                 pu_idx_b2 = *pu4_top_left_pu_idx;
    538             }
    539             else
    540             {
    541                 /* Not at CTB boundary, use top and  */
    542                 /* add correction to go to top-left */
    543                 pu_idx_b2 = *((pu4_top_pu_idx)+(x_b2 >> 2));
    544             }
    545             pu_idx_b2 = pu_idx_b2 * tl_avail;
    546 
    547             num_nbrs = 0;
    548             nbr_avail[0] = 0;
    549             nbr_avail[1] = 0;
    550             nbr_avail[2] = 0;
    551 
    552             if(tr_avail && (!ps_pic_pu[pu_idx_b0].b1_intra_flag))
    553             {
    554                 aps_nbr_pu[num_nbrs] = &ps_pic_pu[pu_idx_b0];
    555                 num_nbrs++;
    556                 nbr_avail[0] = 1;
    557             }
    558             if(t_avail && (!ps_pic_pu[pu_idx_b1].b1_intra_flag))
    559             {
    560                 aps_nbr_pu[num_nbrs] = &ps_pic_pu[pu_idx_b1];
    561                 num_nbrs++;
    562                 nbr_avail[1] = 1;
    563             }
    564             if(tl_avail && (!ps_pic_pu[pu_idx_b2].b1_intra_flag))
    565             {
    566                 aps_nbr_pu[num_nbrs] = &ps_pic_pu[pu_idx_b2];
    567                 num_nbrs++;
    568                 nbr_avail[2] = 1;
    569             }
    570         }
    571 
    572         /* L0 */
    573         avail_b_flag[0] = 0;
    574         avail_b_flag[1] = 0;
    575 
    576         GET_MV_NBR_ST(ps_ref_pic_list, &avail_b_flag[0], ps_cur_pic_buf_l0, aps_nbr_pu, &as_mv_b[0], num_nbrs, 0);
    577 
    578         /* L1 */
    579         if(PRED_L0 != ps_pu->b2_pred_mode)
    580         {
    581             /* B0 Short Term */
    582             GET_MV_NBR_ST(ps_ref_pic_list, &avail_b_flag[1], ps_cur_pic_buf_l1, aps_nbr_pu, &as_mv_b[1], num_nbrs, 1);
    583         }
    584 
    585         if(avail_b_flag[0])
    586         {
    587             if(((0 == num_l0_mvp_cand)
    588                             || (as_mv_a[0].i2_mvx != as_mv_b[0].i2_mvx)
    589                             || (as_mv_a[0].i2_mvy != as_mv_b[0].i2_mvy)))
    590             {
    591                 num_l0_mvp_cand++;
    592                 if(max_l0_mvp_cand == num_l0_mvp_cand)
    593                 {
    594                     ps_pred_mv->s_l0_mv = as_mv_b[0];
    595                     l0_done_flag = 1;
    596                 }
    597             }
    598         }
    599         if(avail_b_flag[1])
    600         {
    601             if(((0 == num_l1_mvp_cand)
    602                             || (as_mv_a[1].i2_mvx != as_mv_b[1].i2_mvx)
    603                             || (as_mv_a[1].i2_mvy != as_mv_b[1].i2_mvy)))
    604             {
    605                 num_l1_mvp_cand++;
    606                 if(max_l1_mvp_cand == num_l1_mvp_cand)
    607                 {
    608                     ps_pred_mv->s_l1_mv = as_mv_b[1];
    609                     l1_done_flag = 1;
    610                 }
    611             }
    612         }
    613         if(l0_done_flag && l1_done_flag)
    614             return;
    615 
    616         if((is_scaled_flag_list == 0) && (avail_b_flag[0] == 1))
    617         {
    618             avail_a_flag[0] = 1;
    619             as_mv_a[0] = as_mv_b[0];
    620         }
    621         if((is_scaled_flag_list == 0) && (avail_b_flag[1] == 1))
    622         {
    623             avail_a_flag[1] = 1;
    624             as_mv_a[1] = as_mv_b[1];
    625         }
    626 
    627         if(0 == is_scaled_flag_list)
    628         {
    629             avail_b_flag[0] = avail_b_flag[1] = 0;
    630 
    631             GET_MV_NBR_LT(ps_ref_pic_list, ps_slice_hdr, &avail_b_flag[0], ps_cur_pic_buf_l0, aps_nbr_pu, &as_mv_b[0], num_nbrs, 0);
    632 
    633             if(PRED_L0 != ps_pu->b2_pred_mode)
    634             {
    635                 GET_MV_NBR_LT(ps_ref_pic_list, ps_slice_hdr, &avail_b_flag[1], ps_cur_pic_buf_l1, aps_nbr_pu, &as_mv_b[1], num_nbrs, 1);
    636             }
    637 
    638             if(avail_b_flag[0])
    639             {
    640                 if(((0 == num_l0_mvp_cand)
    641                                 || (as_mv_a[0].i2_mvx != as_mv_b[0].i2_mvx)
    642                                 || (as_mv_a[0].i2_mvy != as_mv_b[0].i2_mvy)))
    643                 {
    644                     num_l0_mvp_cand++;
    645                     if(max_l0_mvp_cand == num_l0_mvp_cand)
    646                     {
    647                         ps_pred_mv->s_l0_mv = as_mv_b[0];
    648                         l0_done_flag = 1;
    649                     }
    650                 }
    651             }
    652             if(avail_b_flag[1])
    653             {
    654                 if(((0 == num_l1_mvp_cand)
    655                                 || (as_mv_a[1].i2_mvx != as_mv_b[1].i2_mvx)
    656                                 || (as_mv_a[1].i2_mvy != as_mv_b[1].i2_mvy)))
    657                 {
    658                     num_l1_mvp_cand++;
    659                     if(max_l1_mvp_cand == num_l1_mvp_cand)
    660                     {
    661                         ps_pred_mv->s_l1_mv = as_mv_b[1];
    662                         l1_done_flag = 1;
    663                     }
    664                 }
    665             }
    666             if(l0_done_flag && l1_done_flag)
    667                 return;
    668         }
    669         /***********************************************************/
    670         /*          Collocated MV prediction                       */
    671         /***********************************************************/
    672         if((2 != num_l0_mvp_cand) || (2 != num_l1_mvp_cand))
    673         {
    674             mv_t as_mv_col[2], s_mv_col_l0, s_mv_col_l1;
    675             WORD32 avail_col_flag[2] = { 0 };
    676             WORD32 x_col, y_col, avail_col_l0, avail_col_l1;
    677 //            ihevcd_collocated_mvp((mv_ctxt_t *)ps_mv_ctxt,ps_pu,part_pos_x,part_pos_y,part_wd,part_ht,as_mv_col,avail_col_flag,1);
    678             x_col = part_pos_x + part_wd;
    679             y_col = part_pos_y + part_ht;
    680             ihevcd_collocated_mvp(ps_mv_ctxt, ps_pu, as_mv_col, avail_col_flag, 1, x_col, y_col);
    681 
    682             avail_col_l0 = avail_col_flag[0];
    683             avail_col_l1 = avail_col_flag[1];
    684             if(avail_col_l0 || avail_col_l1)
    685             {
    686                 s_mv_col_l0 = as_mv_col[0];
    687                 s_mv_col_l1 = as_mv_col[1];
    688             }
    689 
    690             if(avail_col_l0 == 0 || avail_col_l1 == 0)
    691             {
    692                 /* Checking Collocated MV availability at Center of PU */
    693                 x_col = part_pos_x + (part_wd >> 1);
    694                 y_col = part_pos_y + (part_ht >> 1);
    695                 ihevcd_collocated_mvp(ps_mv_ctxt, ps_pu, as_mv_col, avail_col_flag, 1, x_col, y_col);
    696 
    697                 if(avail_col_l0 == 0)
    698                 {
    699                     s_mv_col_l0 = as_mv_col[0];
    700                 }
    701                 if(avail_col_l1 == 0)
    702                 {
    703                     s_mv_col_l1 = as_mv_col[1];
    704                 }
    705 
    706                 avail_col_l0 |= avail_col_flag[0];
    707                 avail_col_l1 |= avail_col_flag[1];
    708             }
    709 
    710             /* Checking if mvp index matches collocated mv */
    711             if(avail_col_l0)
    712             {
    713                 if(2 != num_l0_mvp_cand)
    714                 {
    715                     num_l0_mvp_cand++;
    716                     if(max_l0_mvp_cand == num_l0_mvp_cand)
    717                     {
    718                         ps_pred_mv->s_l0_mv = s_mv_col_l0;
    719                         l0_done_flag = 1;
    720                     }
    721                 }
    722             }
    723             if(avail_col_l1)
    724             {
    725                 if(2 != num_l1_mvp_cand)
    726                 {
    727                     num_l1_mvp_cand++;
    728                     if(max_l1_mvp_cand == num_l1_mvp_cand)
    729                     {
    730                         ps_pred_mv->s_l1_mv = s_mv_col_l1;
    731                         l1_done_flag = 1;
    732                     }
    733                 }
    734             }
    735             if(l0_done_flag && l1_done_flag)
    736                 return;
    737         }
    738 
    739         if(0 == l0_done_flag)
    740         {
    741             ps_pred_mv->s_l0_mv.i2_mvx = 0;
    742             ps_pred_mv->s_l0_mv.i2_mvy = 0;
    743         }
    744         if(0 == l1_done_flag)
    745         {
    746             ps_pred_mv->s_l1_mv.i2_mvx = 0;
    747             ps_pred_mv->s_l1_mv.i2_mvy = 0;
    748         }
    749     }
    750 }
    751