1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * HEVC video decoder 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * Copyright (C) 2012 - 2013 Guillaume Martres 5cabdff1aSopenharmony_ci * Copyright (C) 2013 Anand Meher Kotra 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * This file is part of FFmpeg. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 10cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 11cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 12cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 15cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 16cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17cabdff1aSopenharmony_ci * Lesser General Public License for more details. 18cabdff1aSopenharmony_ci * 19cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 20cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 21cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22cabdff1aSopenharmony_ci */ 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci#include "hevc.h" 25cabdff1aSopenharmony_ci#include "hevcdec.h" 26cabdff1aSopenharmony_ci#include "threadframe.h" 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_cistatic const uint8_t l0_l1_cand_idx[12][2] = { 29cabdff1aSopenharmony_ci { 0, 1, }, 30cabdff1aSopenharmony_ci { 1, 0, }, 31cabdff1aSopenharmony_ci { 0, 2, }, 32cabdff1aSopenharmony_ci { 2, 0, }, 33cabdff1aSopenharmony_ci { 1, 2, }, 34cabdff1aSopenharmony_ci { 2, 1, }, 35cabdff1aSopenharmony_ci { 0, 3, }, 36cabdff1aSopenharmony_ci { 3, 0, }, 37cabdff1aSopenharmony_ci { 1, 3, }, 38cabdff1aSopenharmony_ci { 3, 1, }, 39cabdff1aSopenharmony_ci { 2, 3, }, 40cabdff1aSopenharmony_ci { 3, 2, }, 41cabdff1aSopenharmony_ci}; 42cabdff1aSopenharmony_ci 43cabdff1aSopenharmony_civoid ff_hevc_set_neighbour_available(HEVCContext *s, int x0, int y0, 44cabdff1aSopenharmony_ci int nPbW, int nPbH) 45cabdff1aSopenharmony_ci{ 46cabdff1aSopenharmony_ci HEVCLocalContext *lc = s->HEVClc; 47cabdff1aSopenharmony_ci int x0b = av_mod_uintp2(x0, s->ps.sps->log2_ctb_size); 48cabdff1aSopenharmony_ci int y0b = av_mod_uintp2(y0, s->ps.sps->log2_ctb_size); 49cabdff1aSopenharmony_ci 50cabdff1aSopenharmony_ci lc->na.cand_up = (lc->ctb_up_flag || y0b); 51cabdff1aSopenharmony_ci lc->na.cand_left = (lc->ctb_left_flag || x0b); 52cabdff1aSopenharmony_ci lc->na.cand_up_left = (x0b || y0b) ? lc->na.cand_left && lc->na.cand_up : lc->ctb_up_left_flag; 53cabdff1aSopenharmony_ci lc->na.cand_up_right_sap = 54cabdff1aSopenharmony_ci (x0b + nPbW == 1 << s->ps.sps->log2_ctb_size) ? 55cabdff1aSopenharmony_ci lc->ctb_up_right_flag && !y0b : lc->na.cand_up; 56cabdff1aSopenharmony_ci lc->na.cand_up_right = 57cabdff1aSopenharmony_ci lc->na.cand_up_right_sap 58cabdff1aSopenharmony_ci && (x0 + nPbW) < lc->end_of_tiles_x; 59cabdff1aSopenharmony_ci lc->na.cand_bottom_left = ((y0 + nPbH) >= lc->end_of_tiles_y) ? 0 : lc->na.cand_left; 60cabdff1aSopenharmony_ci} 61cabdff1aSopenharmony_ci 62cabdff1aSopenharmony_ci/* 63cabdff1aSopenharmony_ci * 6.4.1 Derivation process for z-scan order block availability 64cabdff1aSopenharmony_ci */ 65cabdff1aSopenharmony_cistatic av_always_inline int z_scan_block_avail(HEVCContext *s, int xCurr, int yCurr, 66cabdff1aSopenharmony_ci int xN, int yN) 67cabdff1aSopenharmony_ci{ 68cabdff1aSopenharmony_ci#define MIN_TB_ADDR_ZS(x, y) \ 69cabdff1aSopenharmony_ci s->ps.pps->min_tb_addr_zs[(y) * (s->ps.sps->tb_mask+2) + (x)] 70cabdff1aSopenharmony_ci 71cabdff1aSopenharmony_ci int xCurr_ctb = xCurr >> s->ps.sps->log2_ctb_size; 72cabdff1aSopenharmony_ci int yCurr_ctb = yCurr >> s->ps.sps->log2_ctb_size; 73cabdff1aSopenharmony_ci int xN_ctb = xN >> s->ps.sps->log2_ctb_size; 74cabdff1aSopenharmony_ci int yN_ctb = yN >> s->ps.sps->log2_ctb_size; 75cabdff1aSopenharmony_ci if( yN_ctb < yCurr_ctb || xN_ctb < xCurr_ctb ) 76cabdff1aSopenharmony_ci return 1; 77cabdff1aSopenharmony_ci else { 78cabdff1aSopenharmony_ci int Curr = MIN_TB_ADDR_ZS((xCurr >> s->ps.sps->log2_min_tb_size) & s->ps.sps->tb_mask, 79cabdff1aSopenharmony_ci (yCurr >> s->ps.sps->log2_min_tb_size) & s->ps.sps->tb_mask); 80cabdff1aSopenharmony_ci int N = MIN_TB_ADDR_ZS((xN >> s->ps.sps->log2_min_tb_size) & s->ps.sps->tb_mask, 81cabdff1aSopenharmony_ci (yN >> s->ps.sps->log2_min_tb_size) & s->ps.sps->tb_mask); 82cabdff1aSopenharmony_ci return N <= Curr; 83cabdff1aSopenharmony_ci } 84cabdff1aSopenharmony_ci} 85cabdff1aSopenharmony_ci 86cabdff1aSopenharmony_ci//check if the two luma locations belong to the same motion estimation region 87cabdff1aSopenharmony_cistatic av_always_inline int is_diff_mer(HEVCContext *s, int xN, int yN, int xP, int yP) 88cabdff1aSopenharmony_ci{ 89cabdff1aSopenharmony_ci uint8_t plevel = s->ps.pps->log2_parallel_merge_level; 90cabdff1aSopenharmony_ci 91cabdff1aSopenharmony_ci return xN >> plevel == xP >> plevel && 92cabdff1aSopenharmony_ci yN >> plevel == yP >> plevel; 93cabdff1aSopenharmony_ci} 94cabdff1aSopenharmony_ci 95cabdff1aSopenharmony_ci#define MATCH_MV(x) (AV_RN32A(&A.x) == AV_RN32A(&B.x)) 96cabdff1aSopenharmony_ci#define MATCH(x) (A.x == B.x) 97cabdff1aSopenharmony_ci 98cabdff1aSopenharmony_ci// check if the mv's and refidx are the same between A and B 99cabdff1aSopenharmony_cistatic av_always_inline int compare_mv_ref_idx(struct MvField A, struct MvField B) 100cabdff1aSopenharmony_ci{ 101cabdff1aSopenharmony_ci int a_pf = A.pred_flag; 102cabdff1aSopenharmony_ci int b_pf = B.pred_flag; 103cabdff1aSopenharmony_ci if (a_pf == b_pf) { 104cabdff1aSopenharmony_ci if (a_pf == PF_BI) { 105cabdff1aSopenharmony_ci return MATCH(ref_idx[0]) && MATCH_MV(mv[0]) && 106cabdff1aSopenharmony_ci MATCH(ref_idx[1]) && MATCH_MV(mv[1]); 107cabdff1aSopenharmony_ci } else if (a_pf == PF_L0) { 108cabdff1aSopenharmony_ci return MATCH(ref_idx[0]) && MATCH_MV(mv[0]); 109cabdff1aSopenharmony_ci } else if (a_pf == PF_L1) { 110cabdff1aSopenharmony_ci return MATCH(ref_idx[1]) && MATCH_MV(mv[1]); 111cabdff1aSopenharmony_ci } 112cabdff1aSopenharmony_ci } 113cabdff1aSopenharmony_ci return 0; 114cabdff1aSopenharmony_ci} 115cabdff1aSopenharmony_ci 116cabdff1aSopenharmony_cistatic av_always_inline void mv_scale(Mv *dst, const Mv *src, int td, int tb) 117cabdff1aSopenharmony_ci{ 118cabdff1aSopenharmony_ci int tx, scale_factor; 119cabdff1aSopenharmony_ci 120cabdff1aSopenharmony_ci td = av_clip_int8(td); 121cabdff1aSopenharmony_ci tb = av_clip_int8(tb); 122cabdff1aSopenharmony_ci tx = (0x4000 + abs(td / 2)) / td; 123cabdff1aSopenharmony_ci scale_factor = av_clip_intp2((tb * tx + 32) >> 6, 12); 124cabdff1aSopenharmony_ci dst->x = av_clip_int16((scale_factor * src->x + 127 + 125cabdff1aSopenharmony_ci (scale_factor * src->x < 0)) >> 8); 126cabdff1aSopenharmony_ci dst->y = av_clip_int16((scale_factor * src->y + 127 + 127cabdff1aSopenharmony_ci (scale_factor * src->y < 0)) >> 8); 128cabdff1aSopenharmony_ci} 129cabdff1aSopenharmony_ci 130cabdff1aSopenharmony_cistatic int check_mvset(Mv *mvLXCol, const Mv *mvCol, 131cabdff1aSopenharmony_ci int colPic, int poc, 132cabdff1aSopenharmony_ci const RefPicList *refPicList, int X, int refIdxLx, 133cabdff1aSopenharmony_ci const RefPicList *refPicList_col, int listCol, int refidxCol) 134cabdff1aSopenharmony_ci{ 135cabdff1aSopenharmony_ci int cur_lt = refPicList[X].isLongTerm[refIdxLx]; 136cabdff1aSopenharmony_ci int col_lt = refPicList_col[listCol].isLongTerm[refidxCol]; 137cabdff1aSopenharmony_ci int col_poc_diff, cur_poc_diff; 138cabdff1aSopenharmony_ci 139cabdff1aSopenharmony_ci if (cur_lt != col_lt) { 140cabdff1aSopenharmony_ci mvLXCol->x = 0; 141cabdff1aSopenharmony_ci mvLXCol->y = 0; 142cabdff1aSopenharmony_ci return 0; 143cabdff1aSopenharmony_ci } 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_ci col_poc_diff = colPic - refPicList_col[listCol].list[refidxCol]; 146cabdff1aSopenharmony_ci cur_poc_diff = poc - refPicList[X].list[refIdxLx]; 147cabdff1aSopenharmony_ci 148cabdff1aSopenharmony_ci if (cur_lt || col_poc_diff == cur_poc_diff || !col_poc_diff) { 149cabdff1aSopenharmony_ci mvLXCol->x = mvCol->x; 150cabdff1aSopenharmony_ci mvLXCol->y = mvCol->y; 151cabdff1aSopenharmony_ci } else { 152cabdff1aSopenharmony_ci mv_scale(mvLXCol, mvCol, col_poc_diff, cur_poc_diff); 153cabdff1aSopenharmony_ci } 154cabdff1aSopenharmony_ci return 1; 155cabdff1aSopenharmony_ci} 156cabdff1aSopenharmony_ci 157cabdff1aSopenharmony_ci#define CHECK_MVSET(l) \ 158cabdff1aSopenharmony_ci check_mvset(mvLXCol, temp_col.mv + l, \ 159cabdff1aSopenharmony_ci colPic, s->poc, \ 160cabdff1aSopenharmony_ci refPicList, X, refIdxLx, \ 161cabdff1aSopenharmony_ci refPicList_col, L ## l, temp_col.ref_idx[l]) 162cabdff1aSopenharmony_ci 163cabdff1aSopenharmony_ci// derive the motion vectors section 8.5.3.1.8 164cabdff1aSopenharmony_cistatic int derive_temporal_colocated_mvs(HEVCContext *s, MvField temp_col, 165cabdff1aSopenharmony_ci int refIdxLx, Mv *mvLXCol, int X, 166cabdff1aSopenharmony_ci int colPic, const RefPicList *refPicList_col) 167cabdff1aSopenharmony_ci{ 168cabdff1aSopenharmony_ci RefPicList *refPicList = s->ref->refPicList; 169cabdff1aSopenharmony_ci 170cabdff1aSopenharmony_ci if (temp_col.pred_flag == PF_INTRA) 171cabdff1aSopenharmony_ci return 0; 172cabdff1aSopenharmony_ci 173cabdff1aSopenharmony_ci if (!(temp_col.pred_flag & PF_L0)) 174cabdff1aSopenharmony_ci return CHECK_MVSET(1); 175cabdff1aSopenharmony_ci else if (temp_col.pred_flag == PF_L0) 176cabdff1aSopenharmony_ci return CHECK_MVSET(0); 177cabdff1aSopenharmony_ci else if (temp_col.pred_flag == PF_BI) { 178cabdff1aSopenharmony_ci int check_diffpicount = 0; 179cabdff1aSopenharmony_ci int i, j; 180cabdff1aSopenharmony_ci for (j = 0; j < 2; j++) { 181cabdff1aSopenharmony_ci for (i = 0; i < refPicList[j].nb_refs; i++) { 182cabdff1aSopenharmony_ci if (refPicList[j].list[i] > s->poc) { 183cabdff1aSopenharmony_ci check_diffpicount++; 184cabdff1aSopenharmony_ci break; 185cabdff1aSopenharmony_ci } 186cabdff1aSopenharmony_ci } 187cabdff1aSopenharmony_ci } 188cabdff1aSopenharmony_ci if (!check_diffpicount) { 189cabdff1aSopenharmony_ci if (X==0) 190cabdff1aSopenharmony_ci return CHECK_MVSET(0); 191cabdff1aSopenharmony_ci else 192cabdff1aSopenharmony_ci return CHECK_MVSET(1); 193cabdff1aSopenharmony_ci } else { 194cabdff1aSopenharmony_ci if (s->sh.collocated_list == L1) 195cabdff1aSopenharmony_ci return CHECK_MVSET(0); 196cabdff1aSopenharmony_ci else 197cabdff1aSopenharmony_ci return CHECK_MVSET(1); 198cabdff1aSopenharmony_ci } 199cabdff1aSopenharmony_ci } 200cabdff1aSopenharmony_ci 201cabdff1aSopenharmony_ci return 0; 202cabdff1aSopenharmony_ci} 203cabdff1aSopenharmony_ci 204cabdff1aSopenharmony_ci#define TAB_MVF(x, y) \ 205cabdff1aSopenharmony_ci tab_mvf[(y) * min_pu_width + x] 206cabdff1aSopenharmony_ci 207cabdff1aSopenharmony_ci#define TAB_MVF_PU(v) \ 208cabdff1aSopenharmony_ci TAB_MVF(((x ## v) >> s->ps.sps->log2_min_pu_size), \ 209cabdff1aSopenharmony_ci ((y ## v) >> s->ps.sps->log2_min_pu_size)) 210cabdff1aSopenharmony_ci 211cabdff1aSopenharmony_ci#define DERIVE_TEMPORAL_COLOCATED_MVS \ 212cabdff1aSopenharmony_ci derive_temporal_colocated_mvs(s, temp_col, \ 213cabdff1aSopenharmony_ci refIdxLx, mvLXCol, X, colPic, \ 214cabdff1aSopenharmony_ci ff_hevc_get_ref_list(s, ref, x, y)) 215cabdff1aSopenharmony_ci 216cabdff1aSopenharmony_ci/* 217cabdff1aSopenharmony_ci * 8.5.3.1.7 temporal luma motion vector prediction 218cabdff1aSopenharmony_ci */ 219cabdff1aSopenharmony_cistatic int temporal_luma_motion_vector(HEVCContext *s, int x0, int y0, 220cabdff1aSopenharmony_ci int nPbW, int nPbH, int refIdxLx, 221cabdff1aSopenharmony_ci Mv *mvLXCol, int X) 222cabdff1aSopenharmony_ci{ 223cabdff1aSopenharmony_ci MvField *tab_mvf; 224cabdff1aSopenharmony_ci MvField temp_col; 225cabdff1aSopenharmony_ci int x, y, x_pu, y_pu; 226cabdff1aSopenharmony_ci int min_pu_width = s->ps.sps->min_pu_width; 227cabdff1aSopenharmony_ci int availableFlagLXCol = 0; 228cabdff1aSopenharmony_ci int colPic; 229cabdff1aSopenharmony_ci 230cabdff1aSopenharmony_ci HEVCFrame *ref = s->ref->collocated_ref; 231cabdff1aSopenharmony_ci 232cabdff1aSopenharmony_ci if (!ref) { 233cabdff1aSopenharmony_ci memset(mvLXCol, 0, sizeof(*mvLXCol)); 234cabdff1aSopenharmony_ci return 0; 235cabdff1aSopenharmony_ci } 236cabdff1aSopenharmony_ci 237cabdff1aSopenharmony_ci tab_mvf = ref->tab_mvf; 238cabdff1aSopenharmony_ci colPic = ref->poc; 239cabdff1aSopenharmony_ci 240cabdff1aSopenharmony_ci //bottom right collocated motion vector 241cabdff1aSopenharmony_ci x = x0 + nPbW; 242cabdff1aSopenharmony_ci y = y0 + nPbH; 243cabdff1aSopenharmony_ci 244cabdff1aSopenharmony_ci if (tab_mvf && 245cabdff1aSopenharmony_ci (y0 >> s->ps.sps->log2_ctb_size) == (y >> s->ps.sps->log2_ctb_size) && 246cabdff1aSopenharmony_ci y < s->ps.sps->height && 247cabdff1aSopenharmony_ci x < s->ps.sps->width) { 248cabdff1aSopenharmony_ci x &= ~15; 249cabdff1aSopenharmony_ci y &= ~15; 250cabdff1aSopenharmony_ci if (s->threads_type == FF_THREAD_FRAME) 251cabdff1aSopenharmony_ci ff_thread_await_progress(&ref->tf, y, 0); 252cabdff1aSopenharmony_ci x_pu = x >> s->ps.sps->log2_min_pu_size; 253cabdff1aSopenharmony_ci y_pu = y >> s->ps.sps->log2_min_pu_size; 254cabdff1aSopenharmony_ci temp_col = TAB_MVF(x_pu, y_pu); 255cabdff1aSopenharmony_ci availableFlagLXCol = DERIVE_TEMPORAL_COLOCATED_MVS; 256cabdff1aSopenharmony_ci } 257cabdff1aSopenharmony_ci 258cabdff1aSopenharmony_ci // derive center collocated motion vector 259cabdff1aSopenharmony_ci if (tab_mvf && !availableFlagLXCol) { 260cabdff1aSopenharmony_ci x = x0 + (nPbW >> 1); 261cabdff1aSopenharmony_ci y = y0 + (nPbH >> 1); 262cabdff1aSopenharmony_ci x &= ~15; 263cabdff1aSopenharmony_ci y &= ~15; 264cabdff1aSopenharmony_ci if (s->threads_type == FF_THREAD_FRAME) 265cabdff1aSopenharmony_ci ff_thread_await_progress(&ref->tf, y, 0); 266cabdff1aSopenharmony_ci x_pu = x >> s->ps.sps->log2_min_pu_size; 267cabdff1aSopenharmony_ci y_pu = y >> s->ps.sps->log2_min_pu_size; 268cabdff1aSopenharmony_ci temp_col = TAB_MVF(x_pu, y_pu); 269cabdff1aSopenharmony_ci availableFlagLXCol = DERIVE_TEMPORAL_COLOCATED_MVS; 270cabdff1aSopenharmony_ci } 271cabdff1aSopenharmony_ci return availableFlagLXCol; 272cabdff1aSopenharmony_ci} 273cabdff1aSopenharmony_ci 274cabdff1aSopenharmony_ci#define AVAILABLE(cand, v) \ 275cabdff1aSopenharmony_ci (cand && !(TAB_MVF_PU(v).pred_flag == PF_INTRA)) 276cabdff1aSopenharmony_ci 277cabdff1aSopenharmony_ci#define PRED_BLOCK_AVAILABLE(v) \ 278cabdff1aSopenharmony_ci z_scan_block_avail(s, x0, y0, x ## v, y ## v) 279cabdff1aSopenharmony_ci 280cabdff1aSopenharmony_ci#define COMPARE_MV_REFIDX(a, b) \ 281cabdff1aSopenharmony_ci compare_mv_ref_idx(TAB_MVF_PU(a), TAB_MVF_PU(b)) 282cabdff1aSopenharmony_ci 283cabdff1aSopenharmony_ci/* 284cabdff1aSopenharmony_ci * 8.5.3.1.2 Derivation process for spatial merging candidates 285cabdff1aSopenharmony_ci */ 286cabdff1aSopenharmony_cistatic void derive_spatial_merge_candidates(HEVCContext *s, int x0, int y0, 287cabdff1aSopenharmony_ci int nPbW, int nPbH, 288cabdff1aSopenharmony_ci int log2_cb_size, 289cabdff1aSopenharmony_ci int singleMCLFlag, int part_idx, 290cabdff1aSopenharmony_ci int merge_idx, 291cabdff1aSopenharmony_ci struct MvField mergecandlist[]) 292cabdff1aSopenharmony_ci{ 293cabdff1aSopenharmony_ci HEVCLocalContext *lc = s->HEVClc; 294cabdff1aSopenharmony_ci RefPicList *refPicList = s->ref->refPicList; 295cabdff1aSopenharmony_ci MvField *tab_mvf = s->ref->tab_mvf; 296cabdff1aSopenharmony_ci 297cabdff1aSopenharmony_ci const int min_pu_width = s->ps.sps->min_pu_width; 298cabdff1aSopenharmony_ci 299cabdff1aSopenharmony_ci const int cand_bottom_left = lc->na.cand_bottom_left; 300cabdff1aSopenharmony_ci const int cand_left = lc->na.cand_left; 301cabdff1aSopenharmony_ci const int cand_up_left = lc->na.cand_up_left; 302cabdff1aSopenharmony_ci const int cand_up = lc->na.cand_up; 303cabdff1aSopenharmony_ci const int cand_up_right = lc->na.cand_up_right_sap; 304cabdff1aSopenharmony_ci 305cabdff1aSopenharmony_ci const int xA1 = x0 - 1; 306cabdff1aSopenharmony_ci const int yA1 = y0 + nPbH - 1; 307cabdff1aSopenharmony_ci 308cabdff1aSopenharmony_ci const int xB1 = x0 + nPbW - 1; 309cabdff1aSopenharmony_ci const int yB1 = y0 - 1; 310cabdff1aSopenharmony_ci 311cabdff1aSopenharmony_ci const int xB0 = x0 + nPbW; 312cabdff1aSopenharmony_ci const int yB0 = y0 - 1; 313cabdff1aSopenharmony_ci 314cabdff1aSopenharmony_ci const int xA0 = x0 - 1; 315cabdff1aSopenharmony_ci const int yA0 = y0 + nPbH; 316cabdff1aSopenharmony_ci 317cabdff1aSopenharmony_ci const int xB2 = x0 - 1; 318cabdff1aSopenharmony_ci const int yB2 = y0 - 1; 319cabdff1aSopenharmony_ci 320cabdff1aSopenharmony_ci const int nb_refs = (s->sh.slice_type == HEVC_SLICE_P) ? 321cabdff1aSopenharmony_ci s->sh.nb_refs[0] : FFMIN(s->sh.nb_refs[0], s->sh.nb_refs[1]); 322cabdff1aSopenharmony_ci 323cabdff1aSopenharmony_ci int zero_idx = 0; 324cabdff1aSopenharmony_ci 325cabdff1aSopenharmony_ci int nb_merge_cand = 0; 326cabdff1aSopenharmony_ci int nb_orig_merge_cand = 0; 327cabdff1aSopenharmony_ci 328cabdff1aSopenharmony_ci int is_available_a0; 329cabdff1aSopenharmony_ci int is_available_a1; 330cabdff1aSopenharmony_ci int is_available_b0; 331cabdff1aSopenharmony_ci int is_available_b1; 332cabdff1aSopenharmony_ci int is_available_b2; 333cabdff1aSopenharmony_ci 334cabdff1aSopenharmony_ci 335cabdff1aSopenharmony_ci if (!singleMCLFlag && part_idx == 1 && 336cabdff1aSopenharmony_ci (lc->cu.part_mode == PART_Nx2N || 337cabdff1aSopenharmony_ci lc->cu.part_mode == PART_nLx2N || 338cabdff1aSopenharmony_ci lc->cu.part_mode == PART_nRx2N) || 339cabdff1aSopenharmony_ci is_diff_mer(s, xA1, yA1, x0, y0)) { 340cabdff1aSopenharmony_ci is_available_a1 = 0; 341cabdff1aSopenharmony_ci } else { 342cabdff1aSopenharmony_ci is_available_a1 = AVAILABLE(cand_left, A1); 343cabdff1aSopenharmony_ci if (is_available_a1) { 344cabdff1aSopenharmony_ci mergecandlist[nb_merge_cand] = TAB_MVF_PU(A1); 345cabdff1aSopenharmony_ci if (merge_idx == 0) 346cabdff1aSopenharmony_ci return; 347cabdff1aSopenharmony_ci nb_merge_cand++; 348cabdff1aSopenharmony_ci } 349cabdff1aSopenharmony_ci } 350cabdff1aSopenharmony_ci 351cabdff1aSopenharmony_ci if (!singleMCLFlag && part_idx == 1 && 352cabdff1aSopenharmony_ci (lc->cu.part_mode == PART_2NxN || 353cabdff1aSopenharmony_ci lc->cu.part_mode == PART_2NxnU || 354cabdff1aSopenharmony_ci lc->cu.part_mode == PART_2NxnD) || 355cabdff1aSopenharmony_ci is_diff_mer(s, xB1, yB1, x0, y0)) { 356cabdff1aSopenharmony_ci is_available_b1 = 0; 357cabdff1aSopenharmony_ci } else { 358cabdff1aSopenharmony_ci is_available_b1 = AVAILABLE(cand_up, B1); 359cabdff1aSopenharmony_ci if (is_available_b1 && 360cabdff1aSopenharmony_ci !(is_available_a1 && COMPARE_MV_REFIDX(B1, A1))) { 361cabdff1aSopenharmony_ci mergecandlist[nb_merge_cand] = TAB_MVF_PU(B1); 362cabdff1aSopenharmony_ci if (merge_idx == nb_merge_cand) 363cabdff1aSopenharmony_ci return; 364cabdff1aSopenharmony_ci nb_merge_cand++; 365cabdff1aSopenharmony_ci } 366cabdff1aSopenharmony_ci } 367cabdff1aSopenharmony_ci 368cabdff1aSopenharmony_ci // above right spatial merge candidate 369cabdff1aSopenharmony_ci is_available_b0 = AVAILABLE(cand_up_right, B0) && 370cabdff1aSopenharmony_ci xB0 < s->ps.sps->width && 371cabdff1aSopenharmony_ci PRED_BLOCK_AVAILABLE(B0) && 372cabdff1aSopenharmony_ci !is_diff_mer(s, xB0, yB0, x0, y0); 373cabdff1aSopenharmony_ci 374cabdff1aSopenharmony_ci if (is_available_b0 && 375cabdff1aSopenharmony_ci !(is_available_b1 && COMPARE_MV_REFIDX(B0, B1))) { 376cabdff1aSopenharmony_ci mergecandlist[nb_merge_cand] = TAB_MVF_PU(B0); 377cabdff1aSopenharmony_ci if (merge_idx == nb_merge_cand) 378cabdff1aSopenharmony_ci return; 379cabdff1aSopenharmony_ci nb_merge_cand++; 380cabdff1aSopenharmony_ci } 381cabdff1aSopenharmony_ci 382cabdff1aSopenharmony_ci // left bottom spatial merge candidate 383cabdff1aSopenharmony_ci is_available_a0 = AVAILABLE(cand_bottom_left, A0) && 384cabdff1aSopenharmony_ci yA0 < s->ps.sps->height && 385cabdff1aSopenharmony_ci PRED_BLOCK_AVAILABLE(A0) && 386cabdff1aSopenharmony_ci !is_diff_mer(s, xA0, yA0, x0, y0); 387cabdff1aSopenharmony_ci 388cabdff1aSopenharmony_ci if (is_available_a0 && 389cabdff1aSopenharmony_ci !(is_available_a1 && COMPARE_MV_REFIDX(A0, A1))) { 390cabdff1aSopenharmony_ci mergecandlist[nb_merge_cand] = TAB_MVF_PU(A0); 391cabdff1aSopenharmony_ci if (merge_idx == nb_merge_cand) 392cabdff1aSopenharmony_ci return; 393cabdff1aSopenharmony_ci nb_merge_cand++; 394cabdff1aSopenharmony_ci } 395cabdff1aSopenharmony_ci 396cabdff1aSopenharmony_ci // above left spatial merge candidate 397cabdff1aSopenharmony_ci is_available_b2 = AVAILABLE(cand_up_left, B2) && 398cabdff1aSopenharmony_ci !is_diff_mer(s, xB2, yB2, x0, y0); 399cabdff1aSopenharmony_ci 400cabdff1aSopenharmony_ci if (is_available_b2 && 401cabdff1aSopenharmony_ci !(is_available_a1 && COMPARE_MV_REFIDX(B2, A1)) && 402cabdff1aSopenharmony_ci !(is_available_b1 && COMPARE_MV_REFIDX(B2, B1)) && 403cabdff1aSopenharmony_ci nb_merge_cand != 4) { 404cabdff1aSopenharmony_ci mergecandlist[nb_merge_cand] = TAB_MVF_PU(B2); 405cabdff1aSopenharmony_ci if (merge_idx == nb_merge_cand) 406cabdff1aSopenharmony_ci return; 407cabdff1aSopenharmony_ci nb_merge_cand++; 408cabdff1aSopenharmony_ci } 409cabdff1aSopenharmony_ci 410cabdff1aSopenharmony_ci // temporal motion vector candidate 411cabdff1aSopenharmony_ci if (s->sh.slice_temporal_mvp_enabled_flag && 412cabdff1aSopenharmony_ci nb_merge_cand < s->sh.max_num_merge_cand) { 413cabdff1aSopenharmony_ci Mv mv_l0_col = { 0 }, mv_l1_col = { 0 }; 414cabdff1aSopenharmony_ci int available_l0 = temporal_luma_motion_vector(s, x0, y0, nPbW, nPbH, 415cabdff1aSopenharmony_ci 0, &mv_l0_col, 0); 416cabdff1aSopenharmony_ci int available_l1 = (s->sh.slice_type == HEVC_SLICE_B) ? 417cabdff1aSopenharmony_ci temporal_luma_motion_vector(s, x0, y0, nPbW, nPbH, 418cabdff1aSopenharmony_ci 0, &mv_l1_col, 1) : 0; 419cabdff1aSopenharmony_ci 420cabdff1aSopenharmony_ci if (available_l0 || available_l1) { 421cabdff1aSopenharmony_ci mergecandlist[nb_merge_cand].pred_flag = available_l0 + (available_l1 << 1); 422cabdff1aSopenharmony_ci AV_ZERO16(mergecandlist[nb_merge_cand].ref_idx); 423cabdff1aSopenharmony_ci mergecandlist[nb_merge_cand].mv[0] = mv_l0_col; 424cabdff1aSopenharmony_ci mergecandlist[nb_merge_cand].mv[1] = mv_l1_col; 425cabdff1aSopenharmony_ci 426cabdff1aSopenharmony_ci if (merge_idx == nb_merge_cand) 427cabdff1aSopenharmony_ci return; 428cabdff1aSopenharmony_ci nb_merge_cand++; 429cabdff1aSopenharmony_ci } 430cabdff1aSopenharmony_ci } 431cabdff1aSopenharmony_ci 432cabdff1aSopenharmony_ci nb_orig_merge_cand = nb_merge_cand; 433cabdff1aSopenharmony_ci 434cabdff1aSopenharmony_ci // combined bi-predictive merge candidates (applies for B slices) 435cabdff1aSopenharmony_ci if (s->sh.slice_type == HEVC_SLICE_B && nb_orig_merge_cand > 1 && 436cabdff1aSopenharmony_ci nb_orig_merge_cand < s->sh.max_num_merge_cand) { 437cabdff1aSopenharmony_ci int comb_idx = 0; 438cabdff1aSopenharmony_ci 439cabdff1aSopenharmony_ci for (comb_idx = 0; nb_merge_cand < s->sh.max_num_merge_cand && 440cabdff1aSopenharmony_ci comb_idx < nb_orig_merge_cand * (nb_orig_merge_cand - 1); comb_idx++) { 441cabdff1aSopenharmony_ci int l0_cand_idx = l0_l1_cand_idx[comb_idx][0]; 442cabdff1aSopenharmony_ci int l1_cand_idx = l0_l1_cand_idx[comb_idx][1]; 443cabdff1aSopenharmony_ci MvField l0_cand = mergecandlist[l0_cand_idx]; 444cabdff1aSopenharmony_ci MvField l1_cand = mergecandlist[l1_cand_idx]; 445cabdff1aSopenharmony_ci 446cabdff1aSopenharmony_ci if ((l0_cand.pred_flag & PF_L0) && (l1_cand.pred_flag & PF_L1) && 447cabdff1aSopenharmony_ci (refPicList[0].list[l0_cand.ref_idx[0]] != 448cabdff1aSopenharmony_ci refPicList[1].list[l1_cand.ref_idx[1]] || 449cabdff1aSopenharmony_ci AV_RN32A(&l0_cand.mv[0]) != AV_RN32A(&l1_cand.mv[1]))) { 450cabdff1aSopenharmony_ci mergecandlist[nb_merge_cand].ref_idx[0] = l0_cand.ref_idx[0]; 451cabdff1aSopenharmony_ci mergecandlist[nb_merge_cand].ref_idx[1] = l1_cand.ref_idx[1]; 452cabdff1aSopenharmony_ci mergecandlist[nb_merge_cand].pred_flag = PF_BI; 453cabdff1aSopenharmony_ci AV_COPY32(&mergecandlist[nb_merge_cand].mv[0], &l0_cand.mv[0]); 454cabdff1aSopenharmony_ci AV_COPY32(&mergecandlist[nb_merge_cand].mv[1], &l1_cand.mv[1]); 455cabdff1aSopenharmony_ci if (merge_idx == nb_merge_cand) 456cabdff1aSopenharmony_ci return; 457cabdff1aSopenharmony_ci nb_merge_cand++; 458cabdff1aSopenharmony_ci } 459cabdff1aSopenharmony_ci } 460cabdff1aSopenharmony_ci } 461cabdff1aSopenharmony_ci 462cabdff1aSopenharmony_ci // append Zero motion vector candidates 463cabdff1aSopenharmony_ci while (nb_merge_cand < s->sh.max_num_merge_cand) { 464cabdff1aSopenharmony_ci mergecandlist[nb_merge_cand].pred_flag = PF_L0 + ((s->sh.slice_type == HEVC_SLICE_B) << 1); 465cabdff1aSopenharmony_ci AV_ZERO32(mergecandlist[nb_merge_cand].mv + 0); 466cabdff1aSopenharmony_ci AV_ZERO32(mergecandlist[nb_merge_cand].mv + 1); 467cabdff1aSopenharmony_ci mergecandlist[nb_merge_cand].ref_idx[0] = zero_idx < nb_refs ? zero_idx : 0; 468cabdff1aSopenharmony_ci mergecandlist[nb_merge_cand].ref_idx[1] = zero_idx < nb_refs ? zero_idx : 0; 469cabdff1aSopenharmony_ci 470cabdff1aSopenharmony_ci if (merge_idx == nb_merge_cand) 471cabdff1aSopenharmony_ci return; 472cabdff1aSopenharmony_ci nb_merge_cand++; 473cabdff1aSopenharmony_ci zero_idx++; 474cabdff1aSopenharmony_ci } 475cabdff1aSopenharmony_ci} 476cabdff1aSopenharmony_ci 477cabdff1aSopenharmony_ci/* 478cabdff1aSopenharmony_ci * 8.5.3.1.1 Derivation process of luma Mvs for merge mode 479cabdff1aSopenharmony_ci */ 480cabdff1aSopenharmony_civoid ff_hevc_luma_mv_merge_mode(HEVCContext *s, int x0, int y0, int nPbW, 481cabdff1aSopenharmony_ci int nPbH, int log2_cb_size, int part_idx, 482cabdff1aSopenharmony_ci int merge_idx, MvField *mv) 483cabdff1aSopenharmony_ci{ 484cabdff1aSopenharmony_ci int singleMCLFlag = 0; 485cabdff1aSopenharmony_ci int nCS = 1 << log2_cb_size; 486cabdff1aSopenharmony_ci MvField mergecand_list[MRG_MAX_NUM_CANDS]; 487cabdff1aSopenharmony_ci int nPbW2 = nPbW; 488cabdff1aSopenharmony_ci int nPbH2 = nPbH; 489cabdff1aSopenharmony_ci HEVCLocalContext *lc = s->HEVClc; 490cabdff1aSopenharmony_ci 491cabdff1aSopenharmony_ci if (s->ps.pps->log2_parallel_merge_level > 2 && nCS == 8) { 492cabdff1aSopenharmony_ci singleMCLFlag = 1; 493cabdff1aSopenharmony_ci x0 = lc->cu.x; 494cabdff1aSopenharmony_ci y0 = lc->cu.y; 495cabdff1aSopenharmony_ci nPbW = nCS; 496cabdff1aSopenharmony_ci nPbH = nCS; 497cabdff1aSopenharmony_ci part_idx = 0; 498cabdff1aSopenharmony_ci } 499cabdff1aSopenharmony_ci 500cabdff1aSopenharmony_ci ff_hevc_set_neighbour_available(s, x0, y0, nPbW, nPbH); 501cabdff1aSopenharmony_ci derive_spatial_merge_candidates(s, x0, y0, nPbW, nPbH, log2_cb_size, 502cabdff1aSopenharmony_ci singleMCLFlag, part_idx, 503cabdff1aSopenharmony_ci merge_idx, mergecand_list); 504cabdff1aSopenharmony_ci 505cabdff1aSopenharmony_ci if (mergecand_list[merge_idx].pred_flag == PF_BI && 506cabdff1aSopenharmony_ci (nPbW2 + nPbH2) == 12) { 507cabdff1aSopenharmony_ci mergecand_list[merge_idx].pred_flag = PF_L0; 508cabdff1aSopenharmony_ci } 509cabdff1aSopenharmony_ci 510cabdff1aSopenharmony_ci *mv = mergecand_list[merge_idx]; 511cabdff1aSopenharmony_ci} 512cabdff1aSopenharmony_ci 513cabdff1aSopenharmony_cistatic av_always_inline void dist_scale(HEVCContext *s, Mv *mv, 514cabdff1aSopenharmony_ci int min_pu_width, int x, int y, 515cabdff1aSopenharmony_ci int elist, int ref_idx_curr, int ref_idx) 516cabdff1aSopenharmony_ci{ 517cabdff1aSopenharmony_ci RefPicList *refPicList = s->ref->refPicList; 518cabdff1aSopenharmony_ci MvField *tab_mvf = s->ref->tab_mvf; 519cabdff1aSopenharmony_ci int ref_pic_elist = refPicList[elist].list[TAB_MVF(x, y).ref_idx[elist]]; 520cabdff1aSopenharmony_ci int ref_pic_curr = refPicList[ref_idx_curr].list[ref_idx]; 521cabdff1aSopenharmony_ci 522cabdff1aSopenharmony_ci if (ref_pic_elist != ref_pic_curr) { 523cabdff1aSopenharmony_ci int poc_diff = s->poc - ref_pic_elist; 524cabdff1aSopenharmony_ci if (!poc_diff) 525cabdff1aSopenharmony_ci poc_diff = 1; 526cabdff1aSopenharmony_ci mv_scale(mv, mv, poc_diff, s->poc - ref_pic_curr); 527cabdff1aSopenharmony_ci } 528cabdff1aSopenharmony_ci} 529cabdff1aSopenharmony_ci 530cabdff1aSopenharmony_cistatic int mv_mp_mode_mx(HEVCContext *s, int x, int y, int pred_flag_index, 531cabdff1aSopenharmony_ci Mv *mv, int ref_idx_curr, int ref_idx) 532cabdff1aSopenharmony_ci{ 533cabdff1aSopenharmony_ci MvField *tab_mvf = s->ref->tab_mvf; 534cabdff1aSopenharmony_ci int min_pu_width = s->ps.sps->min_pu_width; 535cabdff1aSopenharmony_ci 536cabdff1aSopenharmony_ci RefPicList *refPicList = s->ref->refPicList; 537cabdff1aSopenharmony_ci 538cabdff1aSopenharmony_ci if (((TAB_MVF(x, y).pred_flag) & (1 << pred_flag_index)) && 539cabdff1aSopenharmony_ci refPicList[pred_flag_index].list[TAB_MVF(x, y).ref_idx[pred_flag_index]] == refPicList[ref_idx_curr].list[ref_idx]) { 540cabdff1aSopenharmony_ci *mv = TAB_MVF(x, y).mv[pred_flag_index]; 541cabdff1aSopenharmony_ci return 1; 542cabdff1aSopenharmony_ci } 543cabdff1aSopenharmony_ci return 0; 544cabdff1aSopenharmony_ci} 545cabdff1aSopenharmony_ci 546cabdff1aSopenharmony_cistatic int mv_mp_mode_mx_lt(HEVCContext *s, int x, int y, int pred_flag_index, 547cabdff1aSopenharmony_ci Mv *mv, int ref_idx_curr, int ref_idx) 548cabdff1aSopenharmony_ci{ 549cabdff1aSopenharmony_ci MvField *tab_mvf = s->ref->tab_mvf; 550cabdff1aSopenharmony_ci int min_pu_width = s->ps.sps->min_pu_width; 551cabdff1aSopenharmony_ci 552cabdff1aSopenharmony_ci RefPicList *refPicList = s->ref->refPicList; 553cabdff1aSopenharmony_ci 554cabdff1aSopenharmony_ci if ((TAB_MVF(x, y).pred_flag) & (1 << pred_flag_index)) { 555cabdff1aSopenharmony_ci int currIsLongTerm = refPicList[ref_idx_curr].isLongTerm[ref_idx]; 556cabdff1aSopenharmony_ci 557cabdff1aSopenharmony_ci int colIsLongTerm = 558cabdff1aSopenharmony_ci refPicList[pred_flag_index].isLongTerm[(TAB_MVF(x, y).ref_idx[pred_flag_index])]; 559cabdff1aSopenharmony_ci 560cabdff1aSopenharmony_ci if (colIsLongTerm == currIsLongTerm) { 561cabdff1aSopenharmony_ci *mv = TAB_MVF(x, y).mv[pred_flag_index]; 562cabdff1aSopenharmony_ci if (!currIsLongTerm) 563cabdff1aSopenharmony_ci dist_scale(s, mv, min_pu_width, x, y, 564cabdff1aSopenharmony_ci pred_flag_index, ref_idx_curr, ref_idx); 565cabdff1aSopenharmony_ci return 1; 566cabdff1aSopenharmony_ci } 567cabdff1aSopenharmony_ci } 568cabdff1aSopenharmony_ci return 0; 569cabdff1aSopenharmony_ci} 570cabdff1aSopenharmony_ci 571cabdff1aSopenharmony_ci#define MP_MX(v, pred, mx) \ 572cabdff1aSopenharmony_ci mv_mp_mode_mx(s, \ 573cabdff1aSopenharmony_ci (x ## v) >> s->ps.sps->log2_min_pu_size, \ 574cabdff1aSopenharmony_ci (y ## v) >> s->ps.sps->log2_min_pu_size, \ 575cabdff1aSopenharmony_ci pred, &mx, ref_idx_curr, ref_idx) 576cabdff1aSopenharmony_ci 577cabdff1aSopenharmony_ci#define MP_MX_LT(v, pred, mx) \ 578cabdff1aSopenharmony_ci mv_mp_mode_mx_lt(s, \ 579cabdff1aSopenharmony_ci (x ## v) >> s->ps.sps->log2_min_pu_size, \ 580cabdff1aSopenharmony_ci (y ## v) >> s->ps.sps->log2_min_pu_size, \ 581cabdff1aSopenharmony_ci pred, &mx, ref_idx_curr, ref_idx) 582cabdff1aSopenharmony_ci 583cabdff1aSopenharmony_civoid ff_hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, int nPbW, 584cabdff1aSopenharmony_ci int nPbH, int log2_cb_size, int part_idx, 585cabdff1aSopenharmony_ci int merge_idx, MvField *mv, 586cabdff1aSopenharmony_ci int mvp_lx_flag, int LX) 587cabdff1aSopenharmony_ci{ 588cabdff1aSopenharmony_ci HEVCLocalContext *lc = s->HEVClc; 589cabdff1aSopenharmony_ci MvField *tab_mvf = s->ref->tab_mvf; 590cabdff1aSopenharmony_ci int isScaledFlag_L0 = 0; 591cabdff1aSopenharmony_ci int availableFlagLXA0 = 1; 592cabdff1aSopenharmony_ci int availableFlagLXB0 = 1; 593cabdff1aSopenharmony_ci int numMVPCandLX = 0; 594cabdff1aSopenharmony_ci int min_pu_width = s->ps.sps->min_pu_width; 595cabdff1aSopenharmony_ci 596cabdff1aSopenharmony_ci int xA0, yA0; 597cabdff1aSopenharmony_ci int is_available_a0; 598cabdff1aSopenharmony_ci int xA1, yA1; 599cabdff1aSopenharmony_ci int is_available_a1; 600cabdff1aSopenharmony_ci int xB0, yB0; 601cabdff1aSopenharmony_ci int is_available_b0; 602cabdff1aSopenharmony_ci int xB1, yB1; 603cabdff1aSopenharmony_ci int is_available_b1; 604cabdff1aSopenharmony_ci int xB2, yB2; 605cabdff1aSopenharmony_ci int is_available_b2; 606cabdff1aSopenharmony_ci 607cabdff1aSopenharmony_ci Mv mvpcand_list[2] = { { 0 } }; 608cabdff1aSopenharmony_ci Mv mxA; 609cabdff1aSopenharmony_ci Mv mxB; 610cabdff1aSopenharmony_ci int ref_idx_curr; 611cabdff1aSopenharmony_ci int ref_idx = 0; 612cabdff1aSopenharmony_ci int pred_flag_index_l0; 613cabdff1aSopenharmony_ci int pred_flag_index_l1; 614cabdff1aSopenharmony_ci 615cabdff1aSopenharmony_ci const int cand_bottom_left = lc->na.cand_bottom_left; 616cabdff1aSopenharmony_ci const int cand_left = lc->na.cand_left; 617cabdff1aSopenharmony_ci const int cand_up_left = lc->na.cand_up_left; 618cabdff1aSopenharmony_ci const int cand_up = lc->na.cand_up; 619cabdff1aSopenharmony_ci const int cand_up_right = lc->na.cand_up_right_sap; 620cabdff1aSopenharmony_ci ref_idx_curr = LX; 621cabdff1aSopenharmony_ci ref_idx = mv->ref_idx[LX]; 622cabdff1aSopenharmony_ci pred_flag_index_l0 = LX; 623cabdff1aSopenharmony_ci pred_flag_index_l1 = !LX; 624cabdff1aSopenharmony_ci 625cabdff1aSopenharmony_ci // left bottom spatial candidate 626cabdff1aSopenharmony_ci xA0 = x0 - 1; 627cabdff1aSopenharmony_ci yA0 = y0 + nPbH; 628cabdff1aSopenharmony_ci 629cabdff1aSopenharmony_ci is_available_a0 = AVAILABLE(cand_bottom_left, A0) && 630cabdff1aSopenharmony_ci yA0 < s->ps.sps->height && 631cabdff1aSopenharmony_ci PRED_BLOCK_AVAILABLE(A0); 632cabdff1aSopenharmony_ci 633cabdff1aSopenharmony_ci //left spatial merge candidate 634cabdff1aSopenharmony_ci xA1 = x0 - 1; 635cabdff1aSopenharmony_ci yA1 = y0 + nPbH - 1; 636cabdff1aSopenharmony_ci 637cabdff1aSopenharmony_ci is_available_a1 = AVAILABLE(cand_left, A1); 638cabdff1aSopenharmony_ci if (is_available_a0 || is_available_a1) 639cabdff1aSopenharmony_ci isScaledFlag_L0 = 1; 640cabdff1aSopenharmony_ci 641cabdff1aSopenharmony_ci if (is_available_a0) { 642cabdff1aSopenharmony_ci if (MP_MX(A0, pred_flag_index_l0, mxA)) { 643cabdff1aSopenharmony_ci goto b_candidates; 644cabdff1aSopenharmony_ci } 645cabdff1aSopenharmony_ci if (MP_MX(A0, pred_flag_index_l1, mxA)) { 646cabdff1aSopenharmony_ci goto b_candidates; 647cabdff1aSopenharmony_ci } 648cabdff1aSopenharmony_ci } 649cabdff1aSopenharmony_ci 650cabdff1aSopenharmony_ci if (is_available_a1) { 651cabdff1aSopenharmony_ci if (MP_MX(A1, pred_flag_index_l0, mxA)) { 652cabdff1aSopenharmony_ci goto b_candidates; 653cabdff1aSopenharmony_ci } 654cabdff1aSopenharmony_ci if (MP_MX(A1, pred_flag_index_l1, mxA)) { 655cabdff1aSopenharmony_ci goto b_candidates; 656cabdff1aSopenharmony_ci } 657cabdff1aSopenharmony_ci } 658cabdff1aSopenharmony_ci 659cabdff1aSopenharmony_ci if (is_available_a0) { 660cabdff1aSopenharmony_ci if (MP_MX_LT(A0, pred_flag_index_l0, mxA)) { 661cabdff1aSopenharmony_ci goto b_candidates; 662cabdff1aSopenharmony_ci } 663cabdff1aSopenharmony_ci if (MP_MX_LT(A0, pred_flag_index_l1, mxA)) { 664cabdff1aSopenharmony_ci goto b_candidates; 665cabdff1aSopenharmony_ci } 666cabdff1aSopenharmony_ci } 667cabdff1aSopenharmony_ci 668cabdff1aSopenharmony_ci if (is_available_a1) { 669cabdff1aSopenharmony_ci if (MP_MX_LT(A1, pred_flag_index_l0, mxA)) { 670cabdff1aSopenharmony_ci goto b_candidates; 671cabdff1aSopenharmony_ci } 672cabdff1aSopenharmony_ci if (MP_MX_LT(A1, pred_flag_index_l1, mxA)) { 673cabdff1aSopenharmony_ci goto b_candidates; 674cabdff1aSopenharmony_ci } 675cabdff1aSopenharmony_ci } 676cabdff1aSopenharmony_ci availableFlagLXA0 = 0; 677cabdff1aSopenharmony_ci 678cabdff1aSopenharmony_cib_candidates: 679cabdff1aSopenharmony_ci // B candidates 680cabdff1aSopenharmony_ci // above right spatial merge candidate 681cabdff1aSopenharmony_ci xB0 = x0 + nPbW; 682cabdff1aSopenharmony_ci yB0 = y0 - 1; 683cabdff1aSopenharmony_ci 684cabdff1aSopenharmony_ci is_available_b0 = AVAILABLE(cand_up_right, B0) && 685cabdff1aSopenharmony_ci xB0 < s->ps.sps->width && 686cabdff1aSopenharmony_ci PRED_BLOCK_AVAILABLE(B0); 687cabdff1aSopenharmony_ci 688cabdff1aSopenharmony_ci // above spatial merge candidate 689cabdff1aSopenharmony_ci xB1 = x0 + nPbW - 1; 690cabdff1aSopenharmony_ci yB1 = y0 - 1; 691cabdff1aSopenharmony_ci is_available_b1 = AVAILABLE(cand_up, B1); 692cabdff1aSopenharmony_ci 693cabdff1aSopenharmony_ci // above left spatial merge candidate 694cabdff1aSopenharmony_ci xB2 = x0 - 1; 695cabdff1aSopenharmony_ci yB2 = y0 - 1; 696cabdff1aSopenharmony_ci is_available_b2 = AVAILABLE(cand_up_left, B2); 697cabdff1aSopenharmony_ci 698cabdff1aSopenharmony_ci // above right spatial merge candidate 699cabdff1aSopenharmony_ci if (is_available_b0) { 700cabdff1aSopenharmony_ci if (MP_MX(B0, pred_flag_index_l0, mxB)) { 701cabdff1aSopenharmony_ci goto scalef; 702cabdff1aSopenharmony_ci } 703cabdff1aSopenharmony_ci if (MP_MX(B0, pred_flag_index_l1, mxB)) { 704cabdff1aSopenharmony_ci goto scalef; 705cabdff1aSopenharmony_ci } 706cabdff1aSopenharmony_ci } 707cabdff1aSopenharmony_ci 708cabdff1aSopenharmony_ci // above spatial merge candidate 709cabdff1aSopenharmony_ci if (is_available_b1) { 710cabdff1aSopenharmony_ci if (MP_MX(B1, pred_flag_index_l0, mxB)) { 711cabdff1aSopenharmony_ci goto scalef; 712cabdff1aSopenharmony_ci } 713cabdff1aSopenharmony_ci if (MP_MX(B1, pred_flag_index_l1, mxB)) { 714cabdff1aSopenharmony_ci goto scalef; 715cabdff1aSopenharmony_ci } 716cabdff1aSopenharmony_ci } 717cabdff1aSopenharmony_ci 718cabdff1aSopenharmony_ci // above left spatial merge candidate 719cabdff1aSopenharmony_ci if (is_available_b2) { 720cabdff1aSopenharmony_ci if (MP_MX(B2, pred_flag_index_l0, mxB)) { 721cabdff1aSopenharmony_ci goto scalef; 722cabdff1aSopenharmony_ci } 723cabdff1aSopenharmony_ci if (MP_MX(B2, pred_flag_index_l1, mxB)) { 724cabdff1aSopenharmony_ci goto scalef; 725cabdff1aSopenharmony_ci } 726cabdff1aSopenharmony_ci } 727cabdff1aSopenharmony_ci availableFlagLXB0 = 0; 728cabdff1aSopenharmony_ci 729cabdff1aSopenharmony_ciscalef: 730cabdff1aSopenharmony_ci if (!isScaledFlag_L0) { 731cabdff1aSopenharmony_ci if (availableFlagLXB0) { 732cabdff1aSopenharmony_ci availableFlagLXA0 = 1; 733cabdff1aSopenharmony_ci mxA = mxB; 734cabdff1aSopenharmony_ci } 735cabdff1aSopenharmony_ci availableFlagLXB0 = 0; 736cabdff1aSopenharmony_ci 737cabdff1aSopenharmony_ci // XB0 and L1 738cabdff1aSopenharmony_ci if (is_available_b0) { 739cabdff1aSopenharmony_ci availableFlagLXB0 = MP_MX_LT(B0, pred_flag_index_l0, mxB); 740cabdff1aSopenharmony_ci if (!availableFlagLXB0) 741cabdff1aSopenharmony_ci availableFlagLXB0 = MP_MX_LT(B0, pred_flag_index_l1, mxB); 742cabdff1aSopenharmony_ci } 743cabdff1aSopenharmony_ci 744cabdff1aSopenharmony_ci if (is_available_b1 && !availableFlagLXB0) { 745cabdff1aSopenharmony_ci availableFlagLXB0 = MP_MX_LT(B1, pred_flag_index_l0, mxB); 746cabdff1aSopenharmony_ci if (!availableFlagLXB0) 747cabdff1aSopenharmony_ci availableFlagLXB0 = MP_MX_LT(B1, pred_flag_index_l1, mxB); 748cabdff1aSopenharmony_ci } 749cabdff1aSopenharmony_ci 750cabdff1aSopenharmony_ci if (is_available_b2 && !availableFlagLXB0) { 751cabdff1aSopenharmony_ci availableFlagLXB0 = MP_MX_LT(B2, pred_flag_index_l0, mxB); 752cabdff1aSopenharmony_ci if (!availableFlagLXB0) 753cabdff1aSopenharmony_ci availableFlagLXB0 = MP_MX_LT(B2, pred_flag_index_l1, mxB); 754cabdff1aSopenharmony_ci } 755cabdff1aSopenharmony_ci } 756cabdff1aSopenharmony_ci 757cabdff1aSopenharmony_ci if (availableFlagLXA0) 758cabdff1aSopenharmony_ci mvpcand_list[numMVPCandLX++] = mxA; 759cabdff1aSopenharmony_ci 760cabdff1aSopenharmony_ci if (availableFlagLXB0 && (!availableFlagLXA0 || mxA.x != mxB.x || mxA.y != mxB.y)) 761cabdff1aSopenharmony_ci mvpcand_list[numMVPCandLX++] = mxB; 762cabdff1aSopenharmony_ci 763cabdff1aSopenharmony_ci //temporal motion vector prediction candidate 764cabdff1aSopenharmony_ci if (numMVPCandLX < 2 && s->sh.slice_temporal_mvp_enabled_flag && 765cabdff1aSopenharmony_ci mvp_lx_flag == numMVPCandLX) { 766cabdff1aSopenharmony_ci Mv mv_col; 767cabdff1aSopenharmony_ci int available_col = temporal_luma_motion_vector(s, x0, y0, nPbW, 768cabdff1aSopenharmony_ci nPbH, ref_idx, 769cabdff1aSopenharmony_ci &mv_col, LX); 770cabdff1aSopenharmony_ci if (available_col) 771cabdff1aSopenharmony_ci mvpcand_list[numMVPCandLX++] = mv_col; 772cabdff1aSopenharmony_ci } 773cabdff1aSopenharmony_ci 774cabdff1aSopenharmony_ci mv->mv[LX] = mvpcand_list[mvp_lx_flag]; 775cabdff1aSopenharmony_ci} 776