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_merge.c
22  *
23  * @brief
24  *  Contains functions for motion vector merge candidates derivation
25  *
26  * @author
27  *  Ittiam
28  *
29  * @par List of Functions:
30  * - ihevcd_compare_pu_mv_t()
31  * - ihevcd_mv_pred_merge()
32  *
33  * @remarks
34  *  None
35  *
36  *******************************************************************************
37  */
38 /*****************************************************************************/
39 /* File Includes                                                             */
40 /*****************************************************************************/
41 #include <stdio.h>
42 #include <stddef.h>
43 #include <stdlib.h>
44 #include <string.h>
45 
46 #include "ihevc_typedefs.h"
47 #include "iv.h"
48 #include "ivd.h"
49 #include "ihevcd_cxa.h"
50 #include "ithread.h"
51 
52 #include "ihevc_defs.h"
53 #include "ihevc_debug.h"
54 #include "ihevc_structs.h"
55 #include "ihevc_macros.h"
56 #include "ihevc_platform_macros.h"
57 #include "ihevc_cabac_tables.h"
58 #include "ihevc_disp_mgr.h"
59 #include "ihevc_buf_mgr.h"
60 #include "ihevc_dpb_mgr.h"
61 
62 #include "ihevcd_defs.h"
63 #include "ihevcd_function_selector.h"
64 #include "ihevcd_structs.h"
65 #include "ihevcd_error.h"
66 #include "ihevcd_nal.h"
67 #include "ihevcd_bitstream.h"
68 #include "ihevcd_fmt_conv.h"
69 #include "ihevcd_job_queue.h"
70 #include "ihevcd_debug.h"
71 #include "ihevcd_mv_merge.h"
72 /**
73  *******************************************************************************
74  *
75  * @brief Compare Motion vectors function
76  *
77  *
78  * @par Description:
79  *   Checks if MVs and Reference idx are excatly matching.
80  *
81  * @param[inout] ps_1
82  *   motion vector 1 to be compared
83  *
84  * @param[in] ps_2
85  *   motion vector 2 to be compared
86  *
87  * @returns
88  *  0 : if not matching 1 : if matching
89  *
90  * @remarks
91  *
92  *******************************************************************************
93  */
ihevcd_compare_pu_t(pu_t * ps_pu_1,pu_t * ps_pu_2)94 WORD32 ihevcd_compare_pu_t(pu_t *ps_pu_1, pu_t *ps_pu_2)
95 {
96     WORD32 l0_match = 0, l1_match = 0;
97     pu_mv_t *ps_mv_1, *ps_mv_2;
98     WORD32 pred_mode_1, pred_mode_2;
99 
100     ps_mv_1 = &ps_pu_1->mv;
101     ps_mv_2 = &ps_pu_2->mv;
102 
103     pred_mode_1 = ps_pu_1->b2_pred_mode;
104     pred_mode_2 = ps_pu_2->b2_pred_mode;
105 
106     if(pred_mode_1 == pred_mode_2)
107     {
108         if(pred_mode_1 != PRED_L1)
109         {
110             if(ps_mv_1->i1_l0_ref_idx == ps_mv_2->i1_l0_ref_idx)
111             {
112                 if(0 == memcmp(&ps_mv_1->s_l0_mv, &ps_mv_2->s_l0_mv, sizeof(mv_t)))
113                 {
114                     l0_match = 1;
115                 }
116             }
117         }
118         if(pred_mode_1 != PRED_L0)
119         {
120             if(ps_mv_1->i1_l1_ref_idx == ps_mv_2->i1_l1_ref_idx)
121             {
122                 if(0 == memcmp(&ps_mv_1->s_l1_mv, &ps_mv_2->s_l1_mv, sizeof(mv_t)))
123                 {
124                     l1_match = 1;
125                 }
126             }
127         }
128         if(pred_mode_1 == PRED_BI)
129             return (l1_match && l0_match);
130         else if(pred_mode_1 == PRED_L0)
131             return l0_match;
132         else
133             return l1_match;
134     }
135 
136     return 0;
137 }
138 
ihevcd_collocated_mvp(mv_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)139 void ihevcd_collocated_mvp(mv_ctxt_t *ps_mv_ctxt,
140                            pu_t *ps_pu,
141                            mv_t *ps_mv_col,
142                            WORD32 *pu4_avail_col_flag,
143                            WORD32 use_pu_ref_idx,
144                            WORD32 x_col,
145                            WORD32 y_col)
146 {
147     sps_t *ps_sps = ps_mv_ctxt->ps_sps;
148     slice_header_t *ps_slice_hdr = ps_mv_ctxt->ps_slice_hdr;
149     ref_list_t *ps_ref_list[2];
150     mv_buf_t *ps_mv_buf_col;
151     WORD32 xp_col, yp_col;
152     WORD32 col_ctb_x, col_ctb_y;
153     mv_t as_mv_col[2];
154     WORD32 log2_ctb_size;
155     WORD32 ctb_size;
156     WORD32 avail_col;
157     WORD32 col_ctb_idx, pu_cnt;
158     WORD32 au4_list_col[2];
159     WORD32 num_minpu_in_ctb;
160     UWORD8 *pu1_pic_pu_map_ctb;
161     pu_t *ps_col_pu;
162     WORD32 part_pos_y;
163 
164 
165     part_pos_y = ps_pu->b4_pos_y << 2;
166 
167     log2_ctb_size = ps_sps->i1_log2_ctb_size;
168     ctb_size = (1 << log2_ctb_size);
169 
170     avail_col = 1;
171 
172     /* Initializing reference list */
173     ps_ref_list[0] = ps_slice_hdr->as_ref_pic_list0;
174     ps_ref_list[1] = ps_slice_hdr->as_ref_pic_list1;
175     if(PSLICE == ps_slice_hdr->i1_slice_type)
176         ps_ref_list[1] = ps_slice_hdr->as_ref_pic_list0;
177 
178     if((ps_slice_hdr->i1_slice_type == BSLICE) && (ps_slice_hdr->i1_collocated_from_l0_flag == 0))
179     {
180         /* L1 */
181         ps_mv_buf_col = (mv_buf_t *)ps_ref_list[1][ps_slice_hdr->i1_collocated_ref_idx].pv_mv_buf;
182 
183     }
184     else
185     {
186         /* L0 */
187         ps_mv_buf_col = (mv_buf_t *)ps_ref_list[0][ps_slice_hdr->i1_collocated_ref_idx].pv_mv_buf;
188 
189     }
190     num_minpu_in_ctb = (ctb_size / MIN_PU_SIZE) * (ctb_size / MIN_PU_SIZE);
191 
192     if(((part_pos_y >> log2_ctb_size) == (y_col >> log2_ctb_size))
193                     && ((x_col + (ps_mv_ctxt->i4_ctb_x << log2_ctb_size)) < ps_sps->i2_pic_width_in_luma_samples)
194                     && (((y_col + (ps_mv_ctxt->i4_ctb_y << log2_ctb_size))
195                                     < ps_sps->i2_pic_height_in_luma_samples)))
196     {
197         xp_col = ((x_col >> 4) << 4);
198         yp_col = ((y_col >> 4) << 4);
199         col_ctb_x = ps_mv_ctxt->i4_ctb_x + (xp_col >> log2_ctb_size);
200         col_ctb_y = ps_mv_ctxt->i4_ctb_y + (yp_col >> log2_ctb_size);
201         col_ctb_idx = col_ctb_x + (col_ctb_y)*(ps_sps->i2_pic_wd_in_ctb);
202         pu_cnt = ps_mv_buf_col->pu4_pic_pu_idx[col_ctb_idx];
203         pu1_pic_pu_map_ctb = ps_mv_buf_col->pu1_pic_pu_map
204                         + col_ctb_idx * num_minpu_in_ctb;
205         if(xp_col == ctb_size)
206             xp_col = 0;
207         pu_cnt += pu1_pic_pu_map_ctb[(yp_col >> 2)
208                         * (ctb_size / MIN_PU_SIZE) + (xp_col >> 2)];
209         ps_col_pu = &ps_mv_buf_col->ps_pic_pu[pu_cnt];
210     }
211     else
212         avail_col = 0;
213 
214     if((avail_col == 0) || (ps_col_pu->b1_intra_flag == 1)
215                     || (ps_slice_hdr->i1_slice_temporal_mvp_enable_flag == 0))
216     {
217         pu4_avail_col_flag[0] = 0;
218         pu4_avail_col_flag[1] = 0;
219         ps_mv_col[0].i2_mvx = 0;
220         ps_mv_col[0].i2_mvy = 0;
221         ps_mv_col[1].i2_mvx = 0;
222         ps_mv_col[1].i2_mvy = 0;
223     }
224     else
225     {
226         WORD32 au4_ref_idx_col[2];
227         WORD32 pred_flag_l0, pred_flag_l1;
228         pred_flag_l0 = (ps_col_pu->b2_pred_mode != PRED_L1);
229         pred_flag_l1 = (ps_col_pu->b2_pred_mode != PRED_L0);
230 
231         if(pred_flag_l0 == 0)
232         {
233             as_mv_col[0] = ps_col_pu->mv.s_l1_mv;
234             au4_ref_idx_col[0] = ps_col_pu->mv.i1_l1_ref_idx;
235             au4_list_col[0] = 1; /* L1 */
236 
237             as_mv_col[1] = ps_col_pu->mv.s_l1_mv;
238             au4_ref_idx_col[1] = ps_col_pu->mv.i1_l1_ref_idx;
239             au4_list_col[1] = 1; /* L1 */
240         }
241         else
242         {
243             if(pred_flag_l1 == 0)
244             {
245                 as_mv_col[0] = ps_col_pu->mv.s_l0_mv;
246                 au4_ref_idx_col[0] = ps_col_pu->mv.i1_l0_ref_idx;
247                 au4_list_col[0] = 0; /* L1 */
248 
249                 as_mv_col[1] = ps_col_pu->mv.s_l0_mv;
250                 au4_ref_idx_col[1] = ps_col_pu->mv.i1_l0_ref_idx;
251                 au4_list_col[1] = 0; /* L1 */
252             }
253             else
254             {
255                 if(1 == ps_slice_hdr->i1_low_delay_flag)
256                 {
257                     as_mv_col[0] = ps_col_pu->mv.s_l0_mv;
258                     au4_ref_idx_col[0] = ps_col_pu->mv.i1_l0_ref_idx;
259                     au4_list_col[0] = 0; /* L0 */
260 
261                     as_mv_col[1] = ps_col_pu->mv.s_l1_mv;
262                     au4_ref_idx_col[1] = ps_col_pu->mv.i1_l1_ref_idx;
263                     au4_list_col[1] = 1; /* L1 */
264                 }
265                 else
266                 {
267                     if(0 == ps_slice_hdr->i1_collocated_from_l0_flag)
268                     {
269                         as_mv_col[0] = ps_col_pu->mv.s_l0_mv;
270                         au4_ref_idx_col[0] = ps_col_pu->mv.i1_l0_ref_idx;
271 
272                         as_mv_col[1] = ps_col_pu->mv.s_l0_mv;
273                         au4_ref_idx_col[1] = ps_col_pu->mv.i1_l0_ref_idx;
274                     }
275                     else
276                     {
277                         as_mv_col[0] = ps_col_pu->mv.s_l1_mv;
278                         au4_ref_idx_col[0] = ps_col_pu->mv.i1_l1_ref_idx;
279 
280                         as_mv_col[1] = ps_col_pu->mv.s_l1_mv;
281                         au4_ref_idx_col[1] = ps_col_pu->mv.i1_l1_ref_idx;
282                     }
283 
284                     au4_list_col[0] = ps_slice_hdr->i1_collocated_from_l0_flag; /* L"collocated_from_l0_flag" */
285                     au4_list_col[1] = ps_slice_hdr->i1_collocated_from_l0_flag; /* L"collocated_from_l0_flag" */
286                 }
287             }
288         }
289         avail_col = 1;
290         {
291             WORD32 cur_poc, col_poc, col_ref_poc_l0, cur_ref_poc;
292             WORD32 col_ref_poc_l0_lt, cur_ref_poc_lt;
293             WORD32 ref_idx_l0, ref_idx_l1;
294             WORD32 slice_idx;
295             pic_buf_t *ps_pic_buf;
296 
297             if(use_pu_ref_idx)
298             {
299                 ref_idx_l0 = ps_pu->mv.i1_l0_ref_idx;
300                 ref_idx_l1 = ps_pu->mv.i1_l1_ref_idx;
301             }
302             else
303             {
304                 ref_idx_l0 = 0;
305                 ref_idx_l1 = 0;
306             }
307 
308             col_poc = ps_mv_buf_col->i4_abs_poc;
309             cur_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
310 
311             slice_idx = *(ps_mv_buf_col->pu1_pic_slice_map + col_ctb_x + col_ctb_y * ps_sps->i2_pic_wd_in_ctb);
312 
313             if(au4_list_col[0] == 0)
314             {
315                 col_ref_poc_l0 =
316                                 ps_mv_buf_col->ai4_l0_collocated_poc[slice_idx][au4_ref_idx_col[0]];
317                 col_ref_poc_l0_lt =
318                                 (ps_mv_buf_col->ai1_l0_collocated_poc_lt[slice_idx][au4_ref_idx_col[0]] == LONG_TERM_REF);
319             }
320             else
321             {
322                 col_ref_poc_l0 =
323                                 ps_mv_buf_col->ai4_l1_collocated_poc[slice_idx][au4_ref_idx_col[0]];
324                 col_ref_poc_l0_lt =
325                                 (ps_mv_buf_col->ai1_l1_collocated_poc_lt[slice_idx][au4_ref_idx_col[0]] == LONG_TERM_REF);
326             }
327             /* L0 collocated mv */
328             ps_pic_buf = (pic_buf_t *)((ps_ref_list[0][ref_idx_l0].pv_pic_buf));
329             cur_ref_poc = ps_pic_buf->i4_abs_poc;
330             cur_ref_poc_lt = (ps_pic_buf->u1_used_as_ref == LONG_TERM_REF);
331 
332             if(cur_ref_poc_lt == col_ref_poc_l0_lt)
333             {
334                 pu4_avail_col_flag[0] = 1;
335 
336                 if(cur_ref_poc_lt || ((col_poc - col_ref_poc_l0) == (cur_poc - cur_ref_poc)))
337                 {
338                     ps_mv_col[0] = as_mv_col[0];
339                 }
340                 else
341                 {
342                     ps_mv_col[0] = as_mv_col[0];
343                     if(col_ref_poc_l0 != col_poc)
344                         ihevcd_scale_collocated_mv((mv_t *)(&ps_mv_col[0]), cur_ref_poc,
345                                                    col_ref_poc_l0, col_poc, cur_poc);
346                 }
347             }
348             else
349             {
350                 pu4_avail_col_flag[0] = 0;
351                 ps_mv_col[0].i2_mvx = 0;
352                 ps_mv_col[0].i2_mvy = 0;
353             }
354             if((BSLICE == ps_slice_hdr->i1_slice_type))
355             {
356                 WORD32 col_ref_poc_l1_lt, col_ref_poc_l1;
357 
358                 if(au4_list_col[1] == 0)
359                 {
360                     col_ref_poc_l1 =
361                                     ps_mv_buf_col->ai4_l0_collocated_poc[slice_idx][au4_ref_idx_col[1]];
362                     col_ref_poc_l1_lt =
363                                     (ps_mv_buf_col->ai1_l0_collocated_poc_lt[slice_idx][au4_ref_idx_col[1]] == LONG_TERM_REF);
364                 }
365                 else
366                 {
367                     col_ref_poc_l1 =
368                                     ps_mv_buf_col->ai4_l1_collocated_poc[slice_idx][au4_ref_idx_col[1]];
369                     col_ref_poc_l1_lt =
370                                     (ps_mv_buf_col->ai1_l1_collocated_poc_lt[slice_idx][au4_ref_idx_col[1]] == LONG_TERM_REF);
371                 }
372 
373                 /* L1 collocated mv */
374                 ps_pic_buf = (pic_buf_t *)((ps_ref_list[1][ref_idx_l1].pv_pic_buf));
375                 cur_ref_poc = ps_pic_buf->i4_abs_poc;
376                 cur_ref_poc_lt = (ps_pic_buf->u1_used_as_ref == LONG_TERM_REF);
377 
378                 if(cur_ref_poc_lt == col_ref_poc_l1_lt)
379                 {
380                     pu4_avail_col_flag[1] = 1;
381 
382                     if(cur_ref_poc_lt || ((col_poc - col_ref_poc_l1) == (cur_poc - cur_ref_poc)))
383                     {
384                         ps_mv_col[1] = as_mv_col[1];
385                     }
386                     else
387                     {
388                         ps_mv_col[1] = as_mv_col[1];
389                         if(col_ref_poc_l1 != col_poc)
390                             ihevcd_scale_collocated_mv((mv_t *)&ps_mv_col[1], cur_ref_poc,
391                                                        col_ref_poc_l1, col_poc, cur_poc);
392                     }
393                 }
394                 else
395                 {
396                     pu4_avail_col_flag[1] = 0;
397                     ps_mv_col[1].i2_mvx = 0;
398                     ps_mv_col[1].i2_mvy = 0;
399                 }
400             }
401             else
402             {
403                 pu4_avail_col_flag[1] = 0;
404             }
405         }
406     }
407 }
408 
409 
410 /**
411  *******************************************************************************
412  *
413  * @brief
414  * This function performs Motion Vector Merge candidates derivation
415  *
416  * @par Description:
417  *  MV merge list is computed using neighbor mvs and colocated mv
418  *
419  * @param[in] ps_ctxt
420  * pointer to mv predictor context
421  *
422  * @param[in] ps_top_nbr_4x4
423  * pointer to top 4x4 nbr structure
424  *
425  * @param[in] ps_left_nbr_4x4
426  * pointer to left 4x4 nbr structure
427  *
428  * @param[in] ps_top_left_nbr_4x4
429  * pointer to top left 4x4 nbr structure
430  *
431  * @param[in] left_nbr_4x4_strd
432  * left nbr buffer stride in terms of 4x4 units
433  *
434  * @param[in] ps_avail_flags
435  * Neighbor availability flags container
436  *
437  * @param[in] ps_col_mv
438  * Colocated MV pointer
439  *
440  * @param[in] ps_pu
441  * Current Partition PU strucrture pointer
442  *
443  * @param[in] part_mode
444  * Partition mode @sa PART_SIZE_E
445  *
446  * @param[in] part_idx
447  * Partition idx of current partition inside CU
448  *
449  * @param[in] single_mcl_flag
450  * Single MCL flag based on 8x8 CU and Parallel merge value
451  *
452  * @param[out] ps_merge_cand_list
453  * pointer to store MV merge candidates list
454  *
455  * @returns
456  * None
457  * @remarks
458  *
459  *
460  *******************************************************************************
461  */
ihevcd_mv_merge(mv_ctxt_t * ps_mv_ctxt,UWORD32 * pu4_top_pu_idx,UWORD32 * pu4_left_pu_idx,WORD32 left_nbr_4x4_strd,pu_t * ps_pu,WORD32 part_mode,WORD32 part_idx,WORD32 part_wd,WORD32 part_ht,WORD32 part_pos_x,WORD32 part_pos_y,WORD32 single_mcl_flag,WORD32 lb_avail,WORD32 l_avail,WORD32 tr_avail,WORD32 t_avail,WORD32 tl_avail)462 void ihevcd_mv_merge(mv_ctxt_t *ps_mv_ctxt,
463                      UWORD32 *pu4_top_pu_idx,
464                      UWORD32 *pu4_left_pu_idx,
465                      WORD32 left_nbr_4x4_strd,
466                      pu_t *ps_pu,
467                      WORD32 part_mode,
468                      WORD32 part_idx,
469                      WORD32 part_wd,
470                      WORD32 part_ht,
471                      WORD32 part_pos_x,
472                      WORD32 part_pos_y,
473                      WORD32 single_mcl_flag,
474                      WORD32 lb_avail,
475                      WORD32 l_avail,
476                      WORD32 tr_avail,
477                      WORD32 t_avail,
478                      WORD32 tl_avail)
479 {
480     /******************************************************/
481     /*      Spatial Merge Candidates                      */
482     /******************************************************/
483     slice_header_t *ps_slice_hdr;
484     pu_t as_pu_merge_list[MAX_NUM_MERGE_CAND];
485     pps_t *ps_pps;
486     ref_list_t *ps_ref_list[2];
487     WORD32 sum_avail_a0_a1_b0_b1 = 0; /*Sum of availability of A0, A1, B0, B1*/
488     WORD32 nbr_x, nbr_y;
489     WORD32 nbr_avail[MAX_NUM_MV_NBR];
490     WORD32 merge_shift;
491     WORD32 nbr_pu_idx;
492     pu_t *ps_nbr_pu[MAX_NUM_MV_NBR];
493     WORD32 max_num_merge_cand;
494     WORD32 candidate_cnt;
495     WORD32 pos_x_merge_shift, pos_y_merge_shift;
496 
497     ps_slice_hdr = ps_mv_ctxt->ps_slice_hdr;
498     ps_pps = ps_mv_ctxt->ps_pps;
499     /* Initializing reference list */
500     ps_ref_list[0] = ps_slice_hdr->as_ref_pic_list0;
501     ps_ref_list[1] = ps_slice_hdr->as_ref_pic_list1;
502     if(PSLICE == ps_slice_hdr->i1_slice_type)
503         ps_ref_list[1] = ps_slice_hdr->as_ref_pic_list0;
504 
505     candidate_cnt = 0;
506     /*******************************************/
507     /* Neighbor location: Graphical indication */
508     /*                                         */
509     /*          B2 _____________B1 B0          */
510     /*            |               |            */
511     /*            |               |            */
512     /*            |               |            */
513     /*            |      PU     ht|            */
514     /*            |               |            */
515     /*            |               |            */
516     /*          A1|______wd_______|            */
517     /*          A0                             */
518     /*                                         */
519     /*******************************************/
520 
521     merge_shift = ps_pps->i1_log2_parallel_merge_level;
522 
523     /* Availability check */
524     /* A1 */
525     nbr_x = part_pos_x - 1;
526     nbr_y = part_pos_y + part_ht - 1; /* A1 */
527 
528     nbr_pu_idx = *(pu4_left_pu_idx + ((nbr_y - part_pos_y) >> 2) * left_nbr_4x4_strd);
529     ps_nbr_pu[NBR_A1] = ps_mv_ctxt->ps_pic_pu + nbr_pu_idx;
530 
531     nbr_avail[NBR_A1] = l_avail
532                     && (!ps_nbr_pu[NBR_A1]->b1_intra_flag); /* A1 */
533 
534     pos_x_merge_shift = (part_pos_x >> merge_shift);
535     pos_y_merge_shift = (part_pos_y >> merge_shift);
536     max_num_merge_cand = ps_pu->b3_merge_idx + 1;
537 
538     {
539         if(nbr_avail[NBR_A1])
540         {
541             /* if at same merge level */
542             if(pos_x_merge_shift == (nbr_x >> merge_shift) &&
543                (pos_y_merge_shift == (nbr_y >> merge_shift)))
544             {
545                 nbr_avail[NBR_A1] = 0;
546             }
547 
548             /* SPEC JCTVC-K1003_v9 version has a different way using not available       */
549             /* candidates compared to software. for non square part and seconf part case */
550             /* ideally nothing from the 1st partition should be used as per spec but     */
551             /* HM 8.2 dev verison does not adhere to this. currenlty code fllows HM      */
552 
553             /* if single MCL is 0 , second part of 2 part in CU */
554             else if((single_mcl_flag == 0) && (part_idx == 1) &&
555                             ((part_mode == PART_Nx2N) || (part_mode == PART_nLx2N) ||
556                                             (part_mode == PART_nRx2N)))
557             {
558                 nbr_avail[NBR_A1] = 0;
559             }
560             sum_avail_a0_a1_b0_b1 += nbr_avail[NBR_A1];
561             if(nbr_avail[NBR_A1])
562             {
563                 as_pu_merge_list[candidate_cnt] = *ps_nbr_pu[NBR_A1];
564                 candidate_cnt++;
565                 if(candidate_cnt == max_num_merge_cand)
566                 {
567                     ps_pu[0].mv = as_pu_merge_list[candidate_cnt - 1].mv;
568                     ps_pu[0].b2_pred_mode = as_pu_merge_list[candidate_cnt - 1].b2_pred_mode;
569                     return;
570                 }
571             }
572         }
573     }
574 
575     /* B1 */
576     nbr_x = part_pos_x + part_wd - 1;
577     nbr_y = part_pos_y - 1;
578 
579     nbr_pu_idx = *(pu4_top_pu_idx + ((nbr_x - part_pos_x) >> 2));
580     ps_nbr_pu[NBR_B1] = ps_mv_ctxt->ps_pic_pu + nbr_pu_idx;
581 
582     nbr_avail[NBR_B1] = t_avail
583                     && (!ps_nbr_pu[NBR_B1]->b1_intra_flag); /* B1 */
584 
585     {
586         WORD32 avail_flag;
587         avail_flag = nbr_avail[NBR_B1];
588 
589         if(nbr_avail[NBR_B1])
590         {
591             /* if at same merge level */
592             if(pos_x_merge_shift == (nbr_x >> merge_shift) &&
593                (pos_y_merge_shift == (nbr_y >> merge_shift)))
594             {
595                 nbr_avail[NBR_B1] = 0;
596                 avail_flag = 0;
597             }
598 
599             /* if single MCL is 0 , second part of 2 part in CU */
600             else if((single_mcl_flag == 0) && (part_idx == 1) &&
601                             ((part_mode == PART_2NxN) || (part_mode == PART_2NxnU) ||
602                                             (part_mode == PART_2NxnD)))
603             {
604                 nbr_avail[NBR_B1] = 0;
605                 avail_flag = 0;
606             }
607 
608             else if(nbr_avail[NBR_A1])
609             {
610                 avail_flag = !ihevcd_compare_pu_t(ps_nbr_pu[NBR_A1], ps_nbr_pu[NBR_B1]);
611             }
612 
613             sum_avail_a0_a1_b0_b1 += avail_flag;
614             if(avail_flag)
615             {
616                 as_pu_merge_list[candidate_cnt] = *ps_nbr_pu[NBR_B1];
617                 candidate_cnt++;
618                 if(candidate_cnt == max_num_merge_cand)
619                 {
620                     ps_pu[0].mv = as_pu_merge_list[candidate_cnt - 1].mv;
621                     ps_pu[0].b2_pred_mode = as_pu_merge_list[candidate_cnt - 1].b2_pred_mode;
622                     return;
623                 }
624             }
625         }
626     }
627     /* B0 */
628     nbr_x = part_pos_x + part_wd;
629     nbr_y = part_pos_y - 1;
630 
631     nbr_pu_idx = *(pu4_top_pu_idx + ((nbr_x - part_pos_x) >> 2));
632     ps_nbr_pu[NBR_B0] = ps_mv_ctxt->ps_pic_pu + nbr_pu_idx;
633 
634     nbr_avail[NBR_B0] = tr_avail
635                     && (!ps_nbr_pu[NBR_B0]->b1_intra_flag); /* B0 */
636 
637     {
638         WORD32 avail_flag;
639         avail_flag = nbr_avail[NBR_B0];
640 
641         /* if at same merge level */
642         if(nbr_avail[NBR_B0])
643         {
644             if(pos_x_merge_shift == (nbr_x >> merge_shift) &&
645                (pos_y_merge_shift == (nbr_y >> merge_shift)))
646             {
647                 nbr_avail[NBR_B0] = 0;
648                 avail_flag = 0;
649             }
650             else if(nbr_avail[NBR_B1])
651             {
652                 avail_flag = !ihevcd_compare_pu_t(ps_nbr_pu[NBR_B1], ps_nbr_pu[NBR_B0]);
653             }
654 
655             sum_avail_a0_a1_b0_b1 += avail_flag;
656             if(avail_flag)
657             {
658                 as_pu_merge_list[candidate_cnt] = *ps_nbr_pu[NBR_B0];
659                 candidate_cnt++;
660                 if(candidate_cnt == max_num_merge_cand)
661                 {
662                     ps_pu[0].mv = as_pu_merge_list[candidate_cnt - 1].mv;
663                     ps_pu[0].b2_pred_mode = as_pu_merge_list[candidate_cnt - 1].b2_pred_mode;
664                     return;
665                 }
666             }
667         }
668     }
669     /* A0 */
670     nbr_x = part_pos_x - 1;
671     nbr_y = part_pos_y + part_ht; /* A0 */
672 
673     nbr_pu_idx = *(pu4_left_pu_idx + ((nbr_y - part_pos_y) >> 2) * left_nbr_4x4_strd);
674     ps_nbr_pu[NBR_A0] = ps_mv_ctxt->ps_pic_pu + nbr_pu_idx;
675 
676     nbr_avail[NBR_A0] = lb_avail
677                     && (!ps_nbr_pu[NBR_A0]->b1_intra_flag); /* A0 */
678     {
679         WORD32 avail_flag;
680         avail_flag = nbr_avail[NBR_A0];
681 
682         if(nbr_avail[NBR_A0])
683         {
684             /* if at same merge level */
685             if(pos_x_merge_shift == (nbr_x >> merge_shift) &&
686                             (pos_y_merge_shift == (nbr_y >> merge_shift)))
687             {
688                 nbr_avail[NBR_A0] = 0;
689                 avail_flag = 0;
690             }
691             else if(nbr_avail[NBR_A1])
692             {
693                 avail_flag = !ihevcd_compare_pu_t(ps_nbr_pu[NBR_A1], ps_nbr_pu[NBR_A0]);
694             }
695 
696             sum_avail_a0_a1_b0_b1 += avail_flag;
697             if(avail_flag)
698             {
699                 as_pu_merge_list[candidate_cnt] = *ps_nbr_pu[NBR_A0];
700                 candidate_cnt++;
701                 if(candidate_cnt == max_num_merge_cand)
702                 {
703                     ps_pu[0].mv = as_pu_merge_list[candidate_cnt - 1].mv;
704                     ps_pu[0].b2_pred_mode = as_pu_merge_list[candidate_cnt - 1].b2_pred_mode;
705                     return;
706                 }
707             }
708         }
709     }
710     /* B2 */
711 
712     nbr_x = part_pos_x - 1;
713     nbr_y = part_pos_y - 1; /* B2 */
714 
715     nbr_pu_idx = *(pu4_top_pu_idx + ((nbr_x - part_pos_x) >> 2));
716     ps_nbr_pu[NBR_B2] = ps_mv_ctxt->ps_pic_pu + nbr_pu_idx;
717 
718     nbr_avail[NBR_B2] = tl_avail
719                     && (!ps_nbr_pu[NBR_B2]->b1_intra_flag); /* B2 */
720 
721     {
722         WORD32 avail_flag;
723         avail_flag = nbr_avail[NBR_B2];
724 
725         if(nbr_avail[NBR_B2])
726         {
727             /* if at same merge level */
728             if(pos_x_merge_shift == (nbr_x >> merge_shift) &&
729                             (pos_y_merge_shift == (nbr_y >> merge_shift)))
730             {
731                 nbr_avail[NBR_B2] = 0;
732                 avail_flag = 0;
733             }
734             else if(4 == sum_avail_a0_a1_b0_b1)
735             {
736                 avail_flag = 0;
737             }
738 
739             else
740             {
741                 if(nbr_avail[NBR_A1])
742                 {
743                     avail_flag = !ihevcd_compare_pu_t(ps_nbr_pu[NBR_A1], ps_nbr_pu[NBR_B2]);
744                 }
745 
746                 if(avail_flag && nbr_avail[NBR_B1])
747                 {
748                     avail_flag = !ihevcd_compare_pu_t(ps_nbr_pu[NBR_B1], ps_nbr_pu[NBR_B2]);
749                 }
750             }
751 
752             if(avail_flag)
753             {
754                 as_pu_merge_list[candidate_cnt] = *ps_nbr_pu[NBR_B2];
755                 candidate_cnt++;
756                 if(candidate_cnt == max_num_merge_cand)
757                 {
758                     ps_pu[0].mv = as_pu_merge_list[candidate_cnt - 1].mv;
759                     ps_pu[0].b2_pred_mode = as_pu_merge_list[candidate_cnt - 1].b2_pred_mode;
760                     return;
761                 }
762             }
763         }
764     }
765 
766     /***********************************************************/
767     /*          Collocated MV prediction                       */
768     /***********************************************************/
769     {
770         mv_t as_mv_col[2];
771         WORD32 avail_col_flag[2] = { 0 }, x_col, y_col;
772         WORD32 avail_col_l0, avail_col_l1;
773 //        ihevcd_collocated_mvp(ps_mv_ctxt,ps_pu,part_pos_x,part_pos_y,part_wd,part_ht,as_mv_col,avail_col_flag,0);
774 
775         /* Checking Collocated MV availability at Bottom right of PU*/
776         x_col = part_pos_x + part_wd;
777         y_col = part_pos_y + part_ht;
778         ihevcd_collocated_mvp(ps_mv_ctxt, ps_pu, as_mv_col, avail_col_flag, 0, x_col, y_col);
779 
780         avail_col_l0 = avail_col_flag[0];
781         avail_col_l1 = avail_col_flag[1];
782 
783         if(avail_col_l0 || avail_col_l1)
784         {
785             as_pu_merge_list[candidate_cnt].mv.s_l0_mv = as_mv_col[0];
786             as_pu_merge_list[candidate_cnt].mv.s_l1_mv = as_mv_col[1];
787         }
788 
789         if(avail_col_l0 == 0 || avail_col_l1 == 0)
790         {
791             /* Checking Collocated MV availability at Center of PU */
792             x_col = part_pos_x + (part_wd >> 1);
793             y_col = part_pos_y + (part_ht >> 1);
794             ihevcd_collocated_mvp(ps_mv_ctxt, ps_pu, as_mv_col, avail_col_flag, 0, x_col, y_col);
795 
796             if(avail_col_l0 == 0)
797             {
798                 as_pu_merge_list[candidate_cnt].mv.s_l0_mv = as_mv_col[0];
799             }
800             if(avail_col_l1 == 0)
801             {
802                 as_pu_merge_list[candidate_cnt].mv.s_l1_mv = as_mv_col[1];
803             }
804 
805             avail_col_l0 |= avail_col_flag[0];
806             avail_col_l1 |= avail_col_flag[1];
807         }
808 
809         as_pu_merge_list[candidate_cnt].mv.i1_l0_ref_idx = 0;
810         as_pu_merge_list[candidate_cnt].mv.i1_l1_ref_idx = 0;
811         as_pu_merge_list[candidate_cnt].b2_pred_mode = avail_col_l0 ? (avail_col_l1 ? PRED_BI : PRED_L0) : PRED_L1;
812 
813         candidate_cnt += (avail_col_l0 || avail_col_l1);
814 
815         if(candidate_cnt == max_num_merge_cand)
816         {
817             ps_pu[0].mv = as_pu_merge_list[candidate_cnt - 1].mv;
818             ps_pu[0].b2_pred_mode = as_pu_merge_list[candidate_cnt - 1].b2_pred_mode;
819             return;
820         }
821 
822     }
823     {
824         WORD32 slice_type;
825 
826         slice_type = ps_slice_hdr->i1_slice_type;
827         /* Colocated mv has to be added to list, if available */
828 
829         /******************************************************/
830         /*      Bi pred merge candidates                      */
831         /******************************************************/
832         if(slice_type == BSLICE)
833         {
834             if((candidate_cnt > 1) && (candidate_cnt < MAX_NUM_MERGE_CAND))
835             {
836                 WORD32 priority_list0[12] =
837                     { 0, 1, 0, 2, 1, 2, 0, 3, 1, 3, 2, 3 };
838                 WORD32 priority_list1[12] =
839                     { 1, 0, 2, 0, 2, 1, 3, 0, 3, 1, 3, 2 };
840                 WORD32 l0_cand, l1_cand;
841                 WORD32 bi_pred_idx = 0;
842                 WORD32 total_bi_pred_cand =
843                                 candidate_cnt * (candidate_cnt - 1);
844 
845                 while(bi_pred_idx < total_bi_pred_cand)
846                 {
847                     l0_cand = priority_list0[bi_pred_idx];
848                     l1_cand = priority_list1[bi_pred_idx];
849 
850                     if((as_pu_merge_list[l0_cand].b2_pred_mode != PRED_L1)
851                                     && (as_pu_merge_list[l1_cand].b2_pred_mode
852                                                     != PRED_L0))
853                     {
854                         WORD8 i1_l0_ref_idx, i1_l1_ref_idx;
855                         mv_t s_l0_mv, s_l1_mv;
856                         pic_buf_t *ps_pic_buf_l0, *ps_pic_buf_l1;
857 
858                         i1_l0_ref_idx = as_pu_merge_list[l0_cand].mv.i1_l0_ref_idx;
859                         i1_l1_ref_idx = as_pu_merge_list[l1_cand].mv.i1_l1_ref_idx;
860                         ps_pic_buf_l0 = (pic_buf_t *)((ps_ref_list[0][i1_l0_ref_idx].pv_pic_buf));
861                         ps_pic_buf_l1 = (pic_buf_t *)((ps_ref_list[1][i1_l1_ref_idx].pv_pic_buf));
862                         s_l0_mv = as_pu_merge_list[l0_cand].mv.s_l0_mv;
863                         s_l1_mv = as_pu_merge_list[l1_cand].mv.s_l1_mv;
864 
865                         if((ps_pic_buf_l0->i4_abs_poc != ps_pic_buf_l1->i4_abs_poc)
866                                         || (s_l0_mv.i2_mvx != s_l1_mv.i2_mvx)
867                                         || (s_l0_mv.i2_mvy != s_l1_mv.i2_mvy))
868                         {
869                             candidate_cnt++;
870                             if(candidate_cnt == max_num_merge_cand)
871                             {
872                                 ps_pu[0].mv.s_l0_mv = s_l0_mv;
873                                 ps_pu[0].mv.s_l1_mv = s_l1_mv;
874                                 ps_pu[0].mv.i1_l0_ref_idx = i1_l0_ref_idx;
875                                 ps_pu[0].mv.i1_l1_ref_idx = i1_l1_ref_idx;
876                                 ps_pu[0].b2_pred_mode = PRED_BI;
877                                 return;
878                             }
879                         }
880                     }
881 
882                     bi_pred_idx++;
883 
884                     if((bi_pred_idx == total_bi_pred_cand)
885                                     || (candidate_cnt == MAX_NUM_MERGE_CAND))
886                     {
887                         break;
888                     }
889                 }
890             }
891         }
892 
893         /******************************************************/
894         /*      Zero merge candidates                         */
895         /******************************************************/
896 //        if(candidate_cnt < max_num_merge_cand)
897         {
898             WORD32 num_ref_idx;
899             WORD32 zero_idx;
900 
901             zero_idx = max_num_merge_cand - candidate_cnt - 1;
902 
903             if(slice_type == PSLICE)
904                 num_ref_idx = ps_slice_hdr->i1_num_ref_idx_l0_active;
905             else
906                 /* Slice type B */
907                 num_ref_idx = MIN(ps_slice_hdr->i1_num_ref_idx_l0_active, ps_slice_hdr->i1_num_ref_idx_l1_active);
908 
909             if(zero_idx >= num_ref_idx)
910                 zero_idx = 0;
911 
912             ps_pu[0].mv.i1_l0_ref_idx = zero_idx;
913             if(slice_type == PSLICE)
914             {
915                 ps_pu[0].mv.i1_l1_ref_idx = 0;
916                 ps_pu[0].b2_pred_mode = PRED_L0;
917             }
918             else /* Slice type B */
919             {
920                 ps_pu[0].mv.i1_l1_ref_idx = zero_idx;
921                 ps_pu[0].b2_pred_mode = PRED_BI;
922             }
923 
924             ps_pu[0].mv.s_l0_mv.i2_mvx = 0;
925             ps_pu[0].mv.s_l0_mv.i2_mvy = 0;
926             ps_pu[0].mv.s_l1_mv.i2_mvx = 0;
927             ps_pu[0].mv.s_l1_mv.i2_mvy = 0;
928 
929             candidate_cnt++;
930         }
931     }
932 
933     return;
934 }
935 
936 
937