1 /******************************************************************************
2  *
3  * Copyright (C) 2018 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************
18  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19 */
20 /**
21  *******************************************************************************
22  * @file
23  *  ihevcd_mv_pred_merge.c
24  *
25  * @brief
26  *  Contains functions for motion vector merge candidates derivation
27  *
28  * @author
29  *  Ittiam
30  *
31  * @par List of Functions:
32  * - ihevce_compare_pu_mv_t()
33  * - ihevce_mv_pred_merge()
34  *
35  * @remarks
36  *  None
37  *
38  *******************************************************************************
39  */
40 /*****************************************************************************/
41 /* File Includes                                                             */
42 /*****************************************************************************/
43 /* System include files */
44 #include <stdio.h>
45 #include <string.h>
46 #include <stdlib.h>
47 #include <assert.h>
48 #include <stdarg.h>
49 #include <math.h>
50 
51 /* User include files */
52 #include "ihevc_typedefs.h"
53 #include "itt_video_api.h"
54 #include "ihevce_api.h"
55 
56 #include "rc_cntrl_param.h"
57 #include "rc_frame_info_collector.h"
58 #include "rc_look_ahead_params.h"
59 
60 #include "ihevc_defs.h"
61 #include "ihevc_macros.h"
62 #include "ihevc_debug.h"
63 #include "ihevc_structs.h"
64 #include "ihevc_platform_macros.h"
65 #include "ihevc_deblk.h"
66 #include "ihevc_itrans_recon.h"
67 #include "ihevc_chroma_itrans_recon.h"
68 #include "ihevc_chroma_intra_pred.h"
69 #include "ihevc_intra_pred.h"
70 #include "ihevc_inter_pred.h"
71 #include "ihevc_mem_fns.h"
72 #include "ihevc_padding.h"
73 #include "ihevc_weighted_pred.h"
74 #include "ihevc_sao.h"
75 #include "ihevc_resi_trans.h"
76 #include "ihevc_quant_iquant_ssd.h"
77 #include "ihevc_cabac_tables.h"
78 #include "ihevc_common_tables.h"
79 
80 #include "ihevce_defs.h"
81 #include "ihevce_hle_interface.h"
82 #include "ihevce_lap_enc_structs.h"
83 #include "ihevce_multi_thrd_structs.h"
84 #include "ihevce_me_common_defs.h"
85 #include "ihevce_had_satd.h"
86 #include "ihevce_error_codes.h"
87 #include "ihevce_bitstream.h"
88 #include "ihevce_cabac.h"
89 #include "ihevce_rdoq_macros.h"
90 #include "ihevce_function_selector.h"
91 #include "ihevce_enc_structs.h"
92 #include "ihevce_entropy_structs.h"
93 #include "ihevce_cmn_utils_instr_set_router.h"
94 #include "ihevce_enc_loop_structs.h"
95 #include "hme_datatype.h"
96 #include "hme_interface.h"
97 #include "hme_common_defs.h"
98 #include "hme_defs.h"
99 #include "ihevce_mv_pred.h"
100 #include "ihevce_mv_pred_merge.h"
101 #include "ihevce_common_utils.h"
102 
103 /*****************************************************************************/
104 /* Function Definitions                                                      */
105 /*****************************************************************************/
106 
107 /**
108  *******************************************************************************
109  *
110  * @brief Function scaling temporal motion vector
111  *
112  *
113  * @par Description:
114  *   Scales mv based on difference between current POC and current
115  *   reference POC and neighbour reference poc
116  *
117  * @param[inout] mv
118  *   motion vector to be scaled
119  *
120  * @param[in] cur_ref_poc
121  *   Current PU refernce pic poc
122  *
123  * @param[in] nbr_ref_poc
124  *   Neighbor PU reference pic poc
125  *
126  * @param[in] cur_poc
127  *   Picture order count of current pic
128  *
129  * @returns
130  *  None
131  *
132  * @remarks
133  *
134  *******************************************************************************
135  */
ihevce_scale_collocated_mv(mv_t * ps_mv,WORD32 cur_ref_poc,WORD32 col_ref_poc,WORD32 col_poc,WORD32 cur_poc)136 void ihevce_scale_collocated_mv(
137     mv_t *ps_mv, WORD32 cur_ref_poc, WORD32 col_ref_poc, WORD32 col_poc, WORD32 cur_poc)
138 {
139     WORD32 td, tb, tx;
140     WORD32 dist_scale_factor;
141     WORD32 mvx, mvy;
142 
143     td = CLIP_S8(col_poc - col_ref_poc);
144     tb = CLIP_S8(cur_poc - cur_ref_poc);
145 
146     tx = (16384 + (abs(td) >> 1)) / td;
147 
148     dist_scale_factor = (tb * tx + 32) >> 6;
149     dist_scale_factor = CLIP3(dist_scale_factor, -4096, 4095);
150 
151     mvx = ps_mv->i2_mvx;
152     mvy = ps_mv->i2_mvy;
153 
154     mvx = SIGN(dist_scale_factor * mvx) * ((abs(dist_scale_factor * mvx) + 127) >> 8);
155     mvy = SIGN(dist_scale_factor * mvy) * ((abs(dist_scale_factor * mvy) + 127) >> 8);
156 
157     ps_mv->i2_mvx = CLIP_S16(mvx);
158     ps_mv->i2_mvy = CLIP_S16(mvy);
159 
160 } /* End of ihevce_scale_collocated_mv */
161 
ihevce_collocated_mvp(mv_pred_ctxt_t * ps_mv_ctxt,pu_t * ps_pu,mv_t * ps_mv_col,WORD32 * pu4_avail_col_flag,WORD32 use_pu_ref_idx,WORD32 x_col,WORD32 y_col)162 void ihevce_collocated_mvp(
163     mv_pred_ctxt_t *ps_mv_ctxt,
164     pu_t *ps_pu,
165     mv_t *ps_mv_col,
166     WORD32 *pu4_avail_col_flag,
167     WORD32 use_pu_ref_idx,
168     WORD32 x_col,
169     WORD32 y_col)
170 {
171     sps_t *ps_sps = ps_mv_ctxt->ps_sps;
172     slice_header_t *ps_slice_hdr = ps_mv_ctxt->ps_slice_hdr;
173     recon_pic_buf_t *ps_col_ref_buf;
174     WORD32 xp_col, yp_col;  //In pixel unit
175     WORD32 col_ctb_x, col_ctb_y;  //In CTB unit
176     mv_t as_mv_col[2];
177     WORD32 log2_ctb_size;
178     WORD32 ctb_size;
179     WORD32 avail_col;
180     WORD32 col_ctb_idx, pu_cnt;
181     WORD32 au4_list_col[2];
182     WORD32 num_minpu_in_ctb;
183     UWORD8 *pu1_pic_pu_map_ctb;
184     pu_col_mv_t *ps_col_mv;
185     WORD32 part_pos_y;
186 
187     part_pos_y = ps_pu->b4_pos_y << 2;
188 
189     log2_ctb_size = ps_sps->i1_log2_ctb_size;
190     ctb_size = (1 << log2_ctb_size);
191 
192     avail_col = 1;
193 
194     /* Initializing reference list */
195     if((ps_slice_hdr->i1_slice_type == BSLICE) && (ps_slice_hdr->i1_collocated_from_l0_flag == 0))
196     {
197         /* L1 */
198         ps_col_ref_buf = ps_mv_ctxt->ps_ref_list[1][ps_slice_hdr->i1_collocated_ref_idx];
199     }
200     else
201     {
202         /* L0 */
203         ps_col_ref_buf = ps_mv_ctxt->ps_ref_list[0][ps_slice_hdr->i1_collocated_ref_idx];
204     }
205     num_minpu_in_ctb = (ctb_size / MIN_PU_SIZE) * (ctb_size / MIN_PU_SIZE);
206 
207     if(((part_pos_y >> log2_ctb_size) == (y_col >> log2_ctb_size)) &&
208        (((x_col + (ps_mv_ctxt->i4_ctb_x << log2_ctb_size)) < ps_sps->i2_pic_width_in_luma_samples) ||
209         ps_mv_ctxt->ai4_tile_xtra_ctb[2]) &&
210        ((((y_col + (ps_mv_ctxt->i4_ctb_y << log2_ctb_size)) <
211           ps_sps->i2_pic_height_in_luma_samples) ||
212          ps_mv_ctxt->ai4_tile_xtra_ctb[3])))
213     {
214         xp_col = ((x_col >> 4) << 4);
215         yp_col = ((y_col >> 4) << 4);
216         col_ctb_x = ps_mv_ctxt->i4_ctb_x + (xp_col >> log2_ctb_size);
217         col_ctb_y = ps_mv_ctxt->i4_ctb_y + (yp_col >> log2_ctb_size);
218 
219         /* pu1_frm_pu_map has (i2_pic_wd_in_ctb + 1) CTBs for stride */
220         col_ctb_idx = col_ctb_x + (col_ctb_y) * (ps_sps->i2_pic_wd_in_ctb + 1);
221 
222         if(xp_col == ctb_size)
223             xp_col = 0;
224 
225         pu1_pic_pu_map_ctb = ps_col_ref_buf->pu1_frm_pu_map + col_ctb_idx * num_minpu_in_ctb;
226 
227         pu_cnt = pu1_pic_pu_map_ctb[(yp_col >> 2) * (ctb_size / MIN_PU_SIZE) + (xp_col >> 2)];
228 
229         /* ps_frm_col_mv has (i2_pic_wd_in_ctb + 1) CTBs for stride */
230         ps_col_mv = ps_col_ref_buf->ps_frm_col_mv +
231                     (col_ctb_y * (ps_sps->i2_pic_wd_in_ctb + 1) + col_ctb_x) * num_minpu_in_ctb +
232                     pu_cnt;
233     }
234     else
235         avail_col = 0;
236 
237     if((avail_col == 0) || (ps_col_mv->b1_intra_flag == 1) ||
238        (ps_slice_hdr->i1_slice_temporal_mvp_enable_flag == 0))
239     {
240         pu4_avail_col_flag[0] = 0;
241         pu4_avail_col_flag[1] = 0;
242         ps_mv_col[0].i2_mvx = 0;
243         ps_mv_col[0].i2_mvy = 0;
244         ps_mv_col[1].i2_mvx = 0;
245         ps_mv_col[1].i2_mvy = 0;
246     }
247     else
248     {
249         WORD32 au4_ref_idx_col[2];
250         WORD32 pred_flag_l0, pred_flag_l1;
251         pred_flag_l0 = (ps_col_mv->b2_pred_mode != PRED_L1);
252         pred_flag_l1 = (ps_col_mv->b2_pred_mode != PRED_L0);
253 
254         if(pred_flag_l0 == 0)
255         {
256             as_mv_col[0] = ps_col_mv->s_l1_mv;
257             au4_ref_idx_col[0] = ps_col_mv->i1_l1_ref_idx;
258             au4_list_col[0] = 1; /* L1 */
259 
260             as_mv_col[1] = ps_col_mv->s_l1_mv;
261             au4_ref_idx_col[1] = ps_col_mv->i1_l1_ref_idx;
262             au4_list_col[1] = 1; /* L1 */
263         }
264         else
265         {
266             if(pred_flag_l1 == 0)
267             {
268                 as_mv_col[0] = ps_col_mv->s_l0_mv;
269                 au4_ref_idx_col[0] = ps_col_mv->i1_l0_ref_idx;
270                 au4_list_col[0] = 0; /* L1 */
271 
272                 as_mv_col[1] = ps_col_mv->s_l0_mv;
273                 au4_ref_idx_col[1] = ps_col_mv->i1_l0_ref_idx;
274                 au4_list_col[1] = 0; /* L1 */
275             }
276             else
277             {
278                 if(1 == ps_slice_hdr->i1_low_delay_flag)
279                 {
280                     as_mv_col[0] = ps_col_mv->s_l0_mv;
281                     au4_ref_idx_col[0] = ps_col_mv->i1_l0_ref_idx;
282                     au4_list_col[0] = 0; /* L0 */
283 
284                     as_mv_col[1] = ps_col_mv->s_l1_mv;
285                     au4_ref_idx_col[1] = ps_col_mv->i1_l1_ref_idx;
286                     au4_list_col[1] = 1; /* L1 */
287                 }
288                 else
289                 {
290                     if(0 == ps_slice_hdr->i1_collocated_from_l0_flag)
291                     {
292                         as_mv_col[0] = ps_col_mv->s_l0_mv;
293                         au4_ref_idx_col[0] = ps_col_mv->i1_l0_ref_idx;
294 
295                         as_mv_col[1] = ps_col_mv->s_l0_mv;
296                         au4_ref_idx_col[1] = ps_col_mv->i1_l0_ref_idx;
297                     }
298                     else
299                     {
300                         as_mv_col[0] = ps_col_mv->s_l1_mv;
301                         au4_ref_idx_col[0] = ps_col_mv->i1_l1_ref_idx;
302 
303                         as_mv_col[1] = ps_col_mv->s_l1_mv;
304                         au4_ref_idx_col[1] = ps_col_mv->i1_l1_ref_idx;
305                     }
306 
307                     au4_list_col[0] =
308                         ps_slice_hdr->i1_collocated_from_l0_flag; /* L"collocated_from_l0_flag" */
309                     au4_list_col[1] =
310                         ps_slice_hdr->i1_collocated_from_l0_flag; /* L"collocated_from_l0_flag" */
311                 }
312             }
313         }
314         avail_col = 1;
315         {
316             WORD32 cur_poc, col_poc, col_ref_poc_l0, cur_ref_poc;
317             WORD32 col_ref_poc_l0_lt, cur_ref_poc_lt;
318             WORD32 ref_idx_l0, ref_idx_l1;
319 
320             if(use_pu_ref_idx)
321             {
322                 ref_idx_l0 = ps_pu->mv.i1_l0_ref_idx;
323                 ref_idx_l1 = ps_pu->mv.i1_l1_ref_idx;
324             }
325             else
326             {
327                 ref_idx_l0 = 0;
328                 ref_idx_l1 = 0;
329             }
330 
331             col_poc = ps_col_ref_buf->i4_poc;
332             cur_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
333 
334             if(-1 != ref_idx_l0)
335             {
336                 if(au4_list_col[0] == 0)
337                 {
338                     col_ref_poc_l0 = ps_col_ref_buf->ai4_col_l0_poc[au4_ref_idx_col[0]];
339                     col_ref_poc_l0_lt = 0; /* Encoder has only short term references */
340                 }
341                 else
342                 {
343                     col_ref_poc_l0 = ps_col_ref_buf->ai4_col_l1_poc[au4_ref_idx_col[0]];
344                     col_ref_poc_l0_lt = 0;
345                 }
346                 /* L0 collocated mv */
347                 cur_ref_poc = ps_mv_ctxt->ps_ref_list[0][ref_idx_l0]->i4_poc;
348                 cur_ref_poc_lt = 0;
349 
350                 {
351                     pu4_avail_col_flag[0] = 1;
352 
353                     /*if(cur_ref_poc_lt || ((col_poc - col_ref_poc_l0) == (cur_poc - cur_ref_poc)))*/
354                     if((col_poc - col_ref_poc_l0) == (cur_poc - cur_ref_poc))
355                     {
356                         ps_mv_col[0] = as_mv_col[0];
357                     }
358                     else
359                     {
360                         ps_mv_col[0] = as_mv_col[0];
361                         if(col_ref_poc_l0 != col_poc)
362                         {
363                             ihevce_scale_collocated_mv(
364                                 (mv_t *)(&ps_mv_col[0]),
365                                 cur_ref_poc,
366                                 col_ref_poc_l0,
367                                 col_poc,
368                                 cur_poc);
369                         }
370                     }
371                 }
372             }
373             else
374             {
375                 pu4_avail_col_flag[0] = 0;
376                 ps_mv_col[0].i2_mvx = 0;
377                 ps_mv_col[0].i2_mvy = 0;
378             }
379             if((BSLICE == ps_slice_hdr->i1_slice_type) && (-1 != ref_idx_l1))
380             {
381                 WORD32 col_ref_poc_l1_lt, col_ref_poc_l1;
382 
383                 if(au4_list_col[1] == 0)
384                 {
385                     col_ref_poc_l1 = ps_col_ref_buf->ai4_col_l0_poc[au4_ref_idx_col[0]];
386                     col_ref_poc_l1_lt = 0;
387                 }
388                 else
389                 {
390                     col_ref_poc_l1 = ps_col_ref_buf->ai4_col_l1_poc[au4_ref_idx_col[0]];
391                     col_ref_poc_l1_lt = 0;
392                 }
393 
394                 /* L1 collocated mv */
395                 cur_ref_poc = ps_mv_ctxt->ps_ref_list[1][ref_idx_l1]->i4_poc;
396                 cur_ref_poc_lt = 0;
397 
398                 {
399                     pu4_avail_col_flag[1] = 1;
400 
401                     /*if(cur_ref_poc_lt || ((col_poc - col_ref_poc_l1) == (cur_poc - cur_ref_poc)))*/
402                     if((col_poc - col_ref_poc_l1) == (cur_poc - cur_ref_poc))
403                     {
404                         ps_mv_col[1] = as_mv_col[1];
405                     }
406                     else
407                     {
408                         ps_mv_col[1] = as_mv_col[1];
409                         if(col_ref_poc_l1 != col_poc)
410                         {
411                             ihevce_scale_collocated_mv(
412                                 (mv_t *)&ps_mv_col[1],
413                                 cur_ref_poc,
414                                 col_ref_poc_l1,
415                                 col_poc,
416                                 cur_poc);
417                         }
418                     }
419                 }
420             } /* End of if BSLICE */
421             else
422             {
423                 pu4_avail_col_flag[1] = 0;
424             }
425         }
426 
427     } /* End of collocated MV calculation */
428 
429 } /* End of ihevce_collocated_mvp */
430 
431 /**
432  *******************************************************************************
433  *
434  * @brief Compare Motion vectors function
435  *
436  *
437  * @par Description:
438  *   Checks if MVs and Reference idx are excatly matching.
439  *
440  * @param[inout] ps_1
441  *   motion vector 1 to be compared
442  *
443  * @param[in] ps_2
444  *   motion vector 2 to be compared
445  *
446  * @returns
447  *  0 : if not matching 1 : if matching
448  *
449  * @remarks
450  *
451  *******************************************************************************
452  */
453 
454 /**
455  *******************************************************************************
456  *
457  * @brief
458  * This function performs Motion Vector Merge candidates derivation
459  *
460  * @par Description:
461  *  MV merge list is computed using neighbor mvs and colocated mv
462  *
463  * @param[in] ps_ctxt
464  * pointer to mv predictor context
465  *
466  * @param[in] ps_top_nbr_4x4
467  * pointer to top 4x4 nbr structure
468  *
469  * @param[in] ps_left_nbr_4x4
470  * pointer to left 4x4 nbr structure
471  *
472  * @param[in] ps_top_left_nbr_4x4
473  * pointer to top left 4x4 nbr structure
474  *
475  * @param[in] left_nbr_4x4_strd
476  * left nbr buffer stride in terms of 4x4 units
477  *
478  * @param[in] ps_avail_flags
479  * Neighbor availability flags container
480  *
481  * @param[in] ps_col_mv
482  * Colocated MV pointer
483  *
484  * @param[in] ps_pu
485  * Current Partition PU strucrture pointer
486  *
487  * @param[in] part_mode
488  * Partition mode @sa PART_SIZE_E
489  *
490  * @param[in] part_idx
491  * Partition idx of current partition inside CU
492  *
493  * @param[in] single_mcl_flag
494  * Single MCL flag based on 8x8 CU and Parallel merge value
495  *
496  * @param[out] ps_merge_cand_list
497  * pointer to store MV merge candidates list
498  *
499  * @returns
500  * Number of merge candidates
501  * @remarks
502  *
503  *
504  *******************************************************************************
505  */
ihevce_mv_pred_merge(mv_pred_ctxt_t * ps_ctxt,nbr_4x4_t * ps_top_nbr_4x4,nbr_4x4_t * ps_left_nbr_4x4,nbr_4x4_t * ps_top_left_nbr_4x4,WORD32 left_nbr_4x4_strd,nbr_avail_flags_t * ps_avail_flags,pu_mv_t * ps_col_mv,pu_t * ps_pu,PART_SIZE_E part_mode,WORD32 part_idx,WORD32 single_mcl_flag,merge_cand_list_t * ps_merge_cand_list,UWORD8 * pu1_is_top_used)506 WORD32 ihevce_mv_pred_merge(
507     mv_pred_ctxt_t *ps_ctxt,
508     nbr_4x4_t *ps_top_nbr_4x4,
509     nbr_4x4_t *ps_left_nbr_4x4,
510     nbr_4x4_t *ps_top_left_nbr_4x4,
511     WORD32 left_nbr_4x4_strd,
512     nbr_avail_flags_t *ps_avail_flags,
513     pu_mv_t *ps_col_mv,
514     pu_t *ps_pu,
515     PART_SIZE_E part_mode,
516     WORD32 part_idx,
517     WORD32 single_mcl_flag,
518     merge_cand_list_t *ps_merge_cand_list,
519     UWORD8 *pu1_is_top_used)
520 {
521     /******************************************************/
522     /*      Spatial Merge Candidates                      */
523     /******************************************************/
524     WORD32 part_pos_x;
525     WORD32 part_pos_y;
526     WORD32 part_wd;
527     WORD32 part_ht;
528     WORD32 slice_type;
529     WORD32 num_ref_idx_l0_active;
530     WORD32 num_ref_idx_l1_active;
531     WORD32 num_merge_cand;
532     WORD32 log2_parallel_merge_level_minus2;
533     WORD32 n;
534     WORD8 i1_spatial_avail_flag_n[MAX_NUM_MV_NBR]; /*[A0/A1/B0/B1/B2]*/
535     WORD32 nbr_x[MAX_NUM_MV_NBR], nbr_y[MAX_NUM_MV_NBR];
536     UWORD8 u1_nbr_avail[MAX_NUM_MV_NBR];
537     WORD32 merge_shift;
538     nbr_4x4_t *ps_nbr_mv[MAX_NUM_MV_NBR];
539 
540     /*******************************************/
541     /* Neighbor location: Graphical indication */
542     /*                                         */
543     /*          B2 _____________B1 B0          */
544     /*            |               |            */
545     /*            |               |            */
546     /*            |               |            */
547     /*            |      PU     ht|            */
548     /*            |               |            */
549     /*            |               |            */
550     /*          A1|______wd_______|            */
551     /*          A0                             */
552     /*                                         */
553     /*******************************************/
554 
555     part_pos_x = ps_pu->b4_pos_x << 2;
556     part_pos_y = ps_pu->b4_pos_y << 2;
557     part_ht = (ps_pu->b4_ht + 1) << 2;
558     part_wd = (ps_pu->b4_wd + 1) << 2;
559 
560     slice_type = ps_ctxt->ps_slice_hdr->i1_slice_type;
561     num_ref_idx_l0_active = ps_ctxt->ps_slice_hdr->i1_num_ref_idx_l0_active;
562     num_ref_idx_l1_active = ps_ctxt->ps_slice_hdr->i1_num_ref_idx_l1_active;
563     log2_parallel_merge_level_minus2 = ps_ctxt->i4_log2_parallel_merge_level_minus2;
564 
565     /* Assigning co-ordinates to neighbors */
566     nbr_x[NBR_A0] = part_pos_x - 1;
567     nbr_y[NBR_A0] = part_pos_y + part_ht; /* A0 */
568 
569     nbr_x[NBR_A1] = part_pos_x - 1;
570     nbr_y[NBR_A1] = part_pos_y + part_ht - 1; /* A1 */
571 
572     nbr_x[NBR_B0] = part_pos_x + part_wd;
573     nbr_y[NBR_B0] = part_pos_y - 1; /* B0 */
574 
575     nbr_x[NBR_B1] = part_pos_x + part_wd - 1;
576     nbr_y[NBR_B1] = part_pos_y - 1; /* B1 */
577 
578     nbr_x[NBR_B2] = part_pos_x - 1;
579     nbr_y[NBR_B2] = part_pos_y - 1; /* B2 */
580 
581     /* Assigning mv's */
582     ps_nbr_mv[NBR_A0] = ps_left_nbr_4x4 + ((nbr_y[NBR_A0] - part_pos_y) >> 2) * left_nbr_4x4_strd;
583     ps_nbr_mv[NBR_A1] = ps_left_nbr_4x4 + ((nbr_y[NBR_A1] - part_pos_y) >> 2) * left_nbr_4x4_strd;
584     ps_nbr_mv[NBR_B0] = ps_top_nbr_4x4 + ((nbr_x[NBR_B0] - part_pos_x) >> 2);
585     ps_nbr_mv[NBR_B1] = ps_top_nbr_4x4 + ((nbr_x[NBR_B1] - part_pos_x) >> 2);
586 
587     if(part_pos_y == 0) /* AT vertical CTB boundary */
588         ps_nbr_mv[NBR_B2] = ps_top_nbr_4x4 + ((nbr_x[NBR_B2] - part_pos_x) >> 2);
589     else
590         ps_nbr_mv[NBR_B2] = ps_top_left_nbr_4x4;
591 
592     /* Assigning nbr availability */
593     u1_nbr_avail[NBR_A0] = ps_avail_flags->u1_bot_lt_avail &&
594                            (!ps_nbr_mv[NBR_A0]->b1_intra_flag); /* A0 */
595     u1_nbr_avail[NBR_A1] = ps_avail_flags->u1_left_avail &&
596                            (!ps_nbr_mv[NBR_A1]->b1_intra_flag); /* A1 */
597     u1_nbr_avail[NBR_B0] = ps_avail_flags->u1_top_rt_avail &&
598                            (!ps_nbr_mv[NBR_B0]->b1_intra_flag); /* B0 */
599     u1_nbr_avail[NBR_B1] = ps_avail_flags->u1_top_avail &&
600                            (!ps_nbr_mv[NBR_B1]->b1_intra_flag); /* B1 */
601     u1_nbr_avail[NBR_B2] = ps_avail_flags->u1_top_lt_avail &&
602                            (!ps_nbr_mv[NBR_B2]->b1_intra_flag); /* B2 */
603 
604     merge_shift = log2_parallel_merge_level_minus2 + 2;
605 
606     /* Availability check */
607     /* A1 */
608     {
609         WORD32 avail_flag;
610         avail_flag = 1;
611         n = NBR_A1;
612 
613         /* if at same merge level */
614         if((part_pos_x >> merge_shift) == (nbr_x[n] >> merge_shift) &&
615            ((part_pos_y >> merge_shift) == (nbr_y[n] >> merge_shift)))
616         {
617             u1_nbr_avail[n] = 0;
618         }
619 
620         /* SPEC JCTVC-K1003_v9 version has a different way using not available       */
621         /* candidates compared to software. for non square part and seconf part case */
622         /* ideally nothing from the 1st partition should be used as per spec but     */
623         /* HM 8.2 dev verison does not adhere to this. currenlty code fllows HM      */
624 
625         /* if single MCL is 0 , second part of 2 part in CU */
626         if((single_mcl_flag == 0) && (part_idx == 1) &&
627            ((part_mode == PART_Nx2N) || (part_mode == PART_nLx2N) || (part_mode == PART_nRx2N)))
628         {
629             u1_nbr_avail[n] = 0;
630         }
631 
632         if(u1_nbr_avail[n] == 0)
633         {
634             avail_flag = 0;
635         }
636         i1_spatial_avail_flag_n[n] = avail_flag;
637     }
638     /* B1 */
639     {
640         WORD32 avail_flag;
641         avail_flag = 1;
642         n = NBR_B1;
643 
644         /* if at same merge level */
645         if((part_pos_x >> merge_shift) == (nbr_x[n] >> merge_shift) &&
646            ((part_pos_y >> merge_shift) == (nbr_y[n] >> merge_shift)))
647         {
648             u1_nbr_avail[n] = 0;
649         }
650 
651         /* if single MCL is 0 , second part of 2 part in CU */
652         if((single_mcl_flag == 0) && (part_idx == 1) &&
653            ((part_mode == PART_2NxN) || (part_mode == PART_2NxnU) || (part_mode == PART_2NxnD)))
654         {
655             u1_nbr_avail[n] = 0;
656         }
657 
658         if(u1_nbr_avail[n] == 0)
659         {
660             avail_flag = 0;
661         }
662 
663         if((avail_flag == 1) && (u1_nbr_avail[NBR_A1] == 1))
664         {
665             /* TODO: Assumption: mvs and ref indicies in both l0 and l1*/
666             /* should match for non availability                       */
667             WORD32 i4_pred_1, i4_pred_2;
668             i4_pred_1 =
669                 (ps_nbr_mv[NBR_A1]->b1_pred_l0_flag | (ps_nbr_mv[NBR_A1]->b1_pred_l1_flag << 1)) -
670                 1;
671             i4_pred_2 = (ps_nbr_mv[n]->b1_pred_l0_flag | (ps_nbr_mv[n]->b1_pred_l1_flag << 1)) - 1;
672             if(ihevce_compare_pu_mv_t(
673                    &ps_nbr_mv[NBR_A1]->mv, &ps_nbr_mv[n]->mv, i4_pred_1, i4_pred_2))
674             {
675                 avail_flag = 0;
676             }
677         }
678         i1_spatial_avail_flag_n[n] = avail_flag;
679     }
680 
681     /* B0 */
682     {
683         WORD32 avail_flag;
684         avail_flag = 1;
685         n = NBR_B0;
686 
687         /* if at same merge level */
688         if((part_pos_x >> merge_shift) == (nbr_x[n] >> merge_shift) &&
689            ((part_pos_y >> merge_shift) == (nbr_y[n] >> merge_shift)))
690         {
691             u1_nbr_avail[n] = 0;
692         }
693 
694         if(u1_nbr_avail[n] == 0)
695         {
696             avail_flag = 0;
697         }
698 
699         if((avail_flag == 1) && (u1_nbr_avail[NBR_B1] == 1))
700         {
701             WORD32 i4_pred_1, i4_pred_2;
702             i4_pred_1 =
703                 (ps_nbr_mv[NBR_B1]->b1_pred_l0_flag | (ps_nbr_mv[NBR_B1]->b1_pred_l1_flag << 1)) -
704                 1;
705             i4_pred_2 = (ps_nbr_mv[n]->b1_pred_l0_flag | (ps_nbr_mv[n]->b1_pred_l1_flag << 1)) - 1;
706             if(ihevce_compare_pu_mv_t(
707                    &ps_nbr_mv[NBR_B1]->mv, &ps_nbr_mv[n]->mv, i4_pred_1, i4_pred_2))
708             {
709                 avail_flag = 0;
710             }
711         }
712         i1_spatial_avail_flag_n[n] = avail_flag;
713     }
714 
715     /* A0 */
716     {
717         WORD32 avail_flag;
718         avail_flag = 1;
719         n = NBR_A0;
720 
721         /* if at same merge level */
722         if((part_pos_x >> merge_shift) == (nbr_x[n] >> merge_shift) &&
723            ((part_pos_y >> merge_shift) == (nbr_y[n] >> merge_shift)))
724         {
725             u1_nbr_avail[n] = 0;
726         }
727 
728         if(u1_nbr_avail[n] == 0)
729         {
730             avail_flag = 0;
731         }
732 
733         if((avail_flag == 1) && (u1_nbr_avail[NBR_A1] == 1))
734         {
735             WORD32 i4_pred_1, i4_pred_2;
736             i4_pred_1 =
737                 (ps_nbr_mv[NBR_A1]->b1_pred_l0_flag | (ps_nbr_mv[NBR_A1]->b1_pred_l1_flag << 1)) -
738                 1;
739             i4_pred_2 = (ps_nbr_mv[n]->b1_pred_l0_flag | (ps_nbr_mv[n]->b1_pred_l1_flag << 1)) - 1;
740             if(ihevce_compare_pu_mv_t(
741                    &ps_nbr_mv[NBR_A1]->mv, &ps_nbr_mv[n]->mv, i4_pred_1, i4_pred_2))
742             {
743                 avail_flag = 0;
744             }
745         }
746         i1_spatial_avail_flag_n[n] = avail_flag;
747     }
748     /* B2 */
749     {
750         WORD32 avail_flag;
751         avail_flag = 1;
752         n = NBR_B2;
753 
754         /* if at same merge level */
755         if((part_pos_x >> merge_shift) == (nbr_x[n] >> merge_shift) &&
756            ((part_pos_y >> merge_shift) == (nbr_y[n] >> merge_shift)))
757         {
758             u1_nbr_avail[n] = 0;
759         }
760 
761         if(u1_nbr_avail[n] == 0)
762         {
763             avail_flag = 0;
764         }
765 
766         if((i1_spatial_avail_flag_n[NBR_A0] + i1_spatial_avail_flag_n[NBR_A1] +
767             i1_spatial_avail_flag_n[NBR_B0] + i1_spatial_avail_flag_n[NBR_B1]) == 4)
768         {
769             avail_flag = 0;
770         }
771 
772         if(avail_flag == 1)
773         {
774             if(u1_nbr_avail[NBR_A1] == 1)
775             {
776                 WORD32 i4_pred_1, i4_pred_2;
777                 i4_pred_1 = (ps_nbr_mv[NBR_A1]->b1_pred_l0_flag |
778                              (ps_nbr_mv[NBR_A1]->b1_pred_l1_flag << 1)) -
779                             1;
780                 i4_pred_2 =
781                     (ps_nbr_mv[n]->b1_pred_l0_flag | (ps_nbr_mv[n]->b1_pred_l1_flag << 1)) - 1;
782                 if(ihevce_compare_pu_mv_t(
783                        &ps_nbr_mv[NBR_A1]->mv, &ps_nbr_mv[n]->mv, i4_pred_1, i4_pred_2))
784                 {
785                     avail_flag = 0;
786                 }
787             }
788             if(u1_nbr_avail[NBR_B1] == 1)
789             {
790                 WORD32 i4_pred_1, i4_pred_2;
791                 i4_pred_1 = (ps_nbr_mv[NBR_B1]->b1_pred_l0_flag |
792                              (ps_nbr_mv[NBR_B1]->b1_pred_l1_flag << 1)) -
793                             1;
794                 i4_pred_2 =
795                     (ps_nbr_mv[n]->b1_pred_l0_flag | (ps_nbr_mv[n]->b1_pred_l1_flag << 1)) - 1;
796                 if(ihevce_compare_pu_mv_t(
797                        &ps_nbr_mv[NBR_B1]->mv, &ps_nbr_mv[n]->mv, i4_pred_1, i4_pred_2))
798                 {
799                     avail_flag = 0;
800                 }
801             }
802         }
803         i1_spatial_avail_flag_n[n] = avail_flag;
804     }
805 
806     /******************************************************/
807     /*          Merge Candidates List                     */
808     /******************************************************/
809     /* Preparing MV merge candidate list */
810     {
811         WORD32 merge_list_priority[MAX_NUM_MERGE_CAND] = { NBR_A1, NBR_B1, NBR_B0, NBR_A0, NBR_B2 };
812 
813         num_merge_cand = 0;
814         for(n = 0; n < MAX_NUM_MERGE_CAND; n++)
815         {
816             WORD32 merge_idx;
817             merge_idx = merge_list_priority[n];
818             if(i1_spatial_avail_flag_n[merge_idx] == 1)
819             {
820                 ps_merge_cand_list[num_merge_cand].mv = ps_nbr_mv[merge_idx]->mv;
821                 ps_merge_cand_list[num_merge_cand].u1_pred_flag_l0 =
822                     (UWORD8)ps_nbr_mv[merge_idx]->b1_pred_l0_flag;
823                 ps_merge_cand_list[num_merge_cand].u1_pred_flag_l1 =
824                     (UWORD8)ps_nbr_mv[merge_idx]->b1_pred_l1_flag;
825 
826                 switch(merge_list_priority[n])
827                 {
828                 case NBR_A1:
829                 case NBR_A0:
830                 {
831                     pu1_is_top_used[num_merge_cand] = 0;
832 
833                     break;
834                 }
835                 default:
836                 {
837                     pu1_is_top_used[num_merge_cand] = 1;
838 
839                     break;
840                 }
841                 }
842 
843                 num_merge_cand++;
844             }
845         }
846 
847         /******************************************************/
848         /*           Temporal Merge Candidates                */
849         /******************************************************/
850         if(num_merge_cand < MAX_NUM_MERGE_CAND)
851         {
852             mv_t as_mv_col[2];
853             WORD32 avail_col_flag[2] = { 0 }, x_col, y_col;
854             WORD32 avail_col_l0, avail_col_l1;
855 
856             /* Checking Collocated MV availability at Bottom right of PU*/
857             x_col = part_pos_x + part_wd;
858             y_col = part_pos_y + part_ht;
859             ihevce_collocated_mvp(ps_ctxt, ps_pu, as_mv_col, avail_col_flag, 0, x_col, y_col);
860 
861             avail_col_l0 = avail_col_flag[0];
862             avail_col_l1 = avail_col_flag[1];
863 
864             if(avail_col_l0 || avail_col_l1)
865             {
866                 ps_merge_cand_list[num_merge_cand].mv.s_l0_mv = as_mv_col[0];
867                 ps_merge_cand_list[num_merge_cand].mv.s_l1_mv = as_mv_col[1];
868             }
869 
870             if(avail_col_l0 == 0 || avail_col_l1 == 0)
871             {
872                 /* Checking Collocated MV availability at Center of PU */
873                 x_col = part_pos_x + (part_wd >> 1);
874                 y_col = part_pos_y + (part_ht >> 1);
875                 ihevce_collocated_mvp(ps_ctxt, ps_pu, as_mv_col, avail_col_flag, 0, x_col, y_col);
876 
877                 if(avail_col_l0 == 0)
878                 {
879                     ps_merge_cand_list[num_merge_cand].mv.s_l0_mv = as_mv_col[0];
880                 }
881                 if(avail_col_l1 == 0)
882                 {
883                     ps_merge_cand_list[num_merge_cand].mv.s_l1_mv = as_mv_col[1];
884                 }
885 
886                 avail_col_l0 |= avail_col_flag[0];
887                 avail_col_l1 |= avail_col_flag[1];
888             }
889 
890             ps_merge_cand_list[num_merge_cand].mv.i1_l0_ref_idx = 0;
891             ps_merge_cand_list[num_merge_cand].mv.i1_l1_ref_idx = 0;
892             ps_merge_cand_list[num_merge_cand].u1_pred_flag_l0 = avail_col_l0 ? 1 : 0;
893             ps_merge_cand_list[num_merge_cand].u1_pred_flag_l1 = avail_col_l1 ? 1 : 0;
894 
895             if(avail_col_l0 || avail_col_l1)
896             {
897                 pu1_is_top_used[num_merge_cand] = 0;
898                 num_merge_cand++;
899             }
900         }
901 
902         /******************************************************/
903         /*      Bi pred merge candidates                      */
904         /******************************************************/
905         if(slice_type == BSLICE)
906         {
907             if((num_merge_cand > 1) && (num_merge_cand < MAX_NUM_MERGE_CAND))
908             {
909                 WORD32 priority_list0[12] = { 0, 1, 0, 2, 1, 2, 0, 3, 1, 3, 2, 3 };
910                 WORD32 priority_list1[12] = { 1, 0, 2, 0, 2, 1, 3, 0, 3, 1, 3, 2 };
911                 WORD32 l0_cand, l1_cand;
912                 WORD32 bi_pred_idx = 0;
913                 WORD32 total_bi_pred_cand = num_merge_cand * (num_merge_cand - 1);
914 
915                 while(bi_pred_idx < total_bi_pred_cand)
916                 {
917                     l0_cand = priority_list0[bi_pred_idx];
918                     l1_cand = priority_list1[bi_pred_idx];
919 
920                     if((ps_merge_cand_list[l0_cand].u1_pred_flag_l0 == 1) &&
921                        (ps_merge_cand_list[l1_cand].u1_pred_flag_l1 == 1))
922                     {
923                         WORD8 i1_l0_ref_idx, i1_l1_ref_idx;
924                         WORD32 l0_poc, l1_poc;
925                         mv_t s_l0_mv, s_l1_mv;
926 
927                         i1_l0_ref_idx = ps_merge_cand_list[l0_cand].mv.i1_l0_ref_idx;
928                         i1_l1_ref_idx = ps_merge_cand_list[l1_cand].mv.i1_l1_ref_idx;
929                         l0_poc = ps_ctxt->ps_ref_list[0][i1_l0_ref_idx]->i4_poc;
930                         l1_poc = ps_ctxt->ps_ref_list[1][i1_l1_ref_idx]->i4_poc;
931                         s_l0_mv = ps_merge_cand_list[l0_cand].mv.s_l0_mv;
932                         s_l1_mv = ps_merge_cand_list[l1_cand].mv.s_l1_mv;
933 
934                         if((l0_poc != l1_poc) || (s_l0_mv.i2_mvx != s_l1_mv.i2_mvx) ||
935                            (s_l0_mv.i2_mvy != s_l1_mv.i2_mvy))
936                         {
937                             ps_merge_cand_list[num_merge_cand].mv.s_l0_mv = s_l0_mv;
938                             ps_merge_cand_list[num_merge_cand].mv.s_l1_mv = s_l1_mv;
939                             ps_merge_cand_list[num_merge_cand].mv.i1_l0_ref_idx = i1_l0_ref_idx;
940                             ps_merge_cand_list[num_merge_cand].mv.i1_l1_ref_idx = i1_l1_ref_idx;
941                             ps_merge_cand_list[num_merge_cand].u1_pred_flag_l0 = 1;
942                             ps_merge_cand_list[num_merge_cand].u1_pred_flag_l1 = 1;
943 
944                             if(pu1_is_top_used[l0_cand] || pu1_is_top_used[l1_cand])
945                             {
946                                 pu1_is_top_used[num_merge_cand] = 1;
947                             }
948                             else
949                             {
950                                 pu1_is_top_used[num_merge_cand] = 0;
951                             }
952 
953                             num_merge_cand++;
954                         }
955                     }
956 
957                     bi_pred_idx++;
958 
959                     if((bi_pred_idx == total_bi_pred_cand) ||
960                        (num_merge_cand == MAX_NUM_MERGE_CAND))
961                     {
962                         break;
963                     }
964                 }
965             }
966         } /* End of Bipred merge candidates */
967 
968         /******************************************************/
969         /*      Zero merge candidates                         */
970         /******************************************************/
971         if(num_merge_cand < MAX_NUM_MERGE_CAND)
972         {
973             WORD32 num_ref_idx;
974             WORD32 zero_idx;
975 
976             zero_idx = 0;
977 
978             if(slice_type == PSLICE)
979                 num_ref_idx = num_ref_idx_l0_active;
980             else
981                 /* Slice type B */
982                 num_ref_idx = MIN(num_ref_idx_l0_active, num_ref_idx_l1_active);
983 
984             while(num_merge_cand < MAX_NUM_MERGE_CAND)
985             {
986                 if(slice_type == PSLICE)
987                 {
988                     ps_merge_cand_list[num_merge_cand].mv.i1_l0_ref_idx = zero_idx;
989                     ps_merge_cand_list[num_merge_cand].mv.i1_l1_ref_idx = -1;
990                     ps_merge_cand_list[num_merge_cand].u1_pred_flag_l0 = 1;
991                     ps_merge_cand_list[num_merge_cand].u1_pred_flag_l1 = 0;
992                 }
993                 else /* Slice type B */
994                 {
995                     ps_merge_cand_list[num_merge_cand].mv.i1_l0_ref_idx = zero_idx;
996                     ps_merge_cand_list[num_merge_cand].mv.i1_l1_ref_idx = zero_idx;
997                     ps_merge_cand_list[num_merge_cand].u1_pred_flag_l0 = 1;
998                     ps_merge_cand_list[num_merge_cand].u1_pred_flag_l1 = 1;
999                 }
1000 
1001                 ps_merge_cand_list[num_merge_cand].mv.s_l0_mv.i2_mvx = 0;
1002                 ps_merge_cand_list[num_merge_cand].mv.s_l0_mv.i2_mvy = 0;
1003                 ps_merge_cand_list[num_merge_cand].mv.s_l1_mv.i2_mvx = 0;
1004                 ps_merge_cand_list[num_merge_cand].mv.s_l1_mv.i2_mvy = 0;
1005 
1006                 pu1_is_top_used[num_merge_cand] = 0;
1007 
1008                 num_merge_cand++;
1009                 zero_idx++;
1010 
1011                 /* if all the reference pics have been added as candidates      */
1012                 /* the the loop shoudl break since it would add same cand again */
1013                 if(zero_idx == num_ref_idx)
1014                 {
1015                     break;
1016                 }
1017             }
1018         } /* End of zero merge candidates */
1019 
1020     } /* End of merge candidate list population */
1021 
1022     return (num_merge_cand);
1023 }
1024