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  */
ihevcd_scale_mv(mv_t * ps_mv,WORD32 cur_ref_poc,WORD32 nbr_ref_poc,WORD32 cur_poc)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  */
ihevcd_scale_collocated_mv(mv_t * ps_mv,WORD32 cur_ref_poc,WORD32 col_ref_poc,WORD32 col_poc,WORD32 cur_poc)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 
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)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 
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)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  */
ihevcd_mv_pred(mv_ctxt_t * ps_mv_ctxt,UWORD32 * pu4_top_pu_idx,UWORD32 * pu4_left_pu_idx,UWORD32 * pu4_top_left_pu_idx,WORD32 left_nbr_4x4_strd,pu_t * ps_pu,WORD32 lb_avail,WORD32 l_avail,WORD32 tr_avail,WORD32 t_avail,WORD32 tl_avail,pu_mv_t * ps_pred_mv)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