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