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