4 * Copyright (C) 2012 - 2013 Guillaume Martres
5 * Copyright (C) 2013 Anand Meher Kotra
7 * This file is part of FFmpeg.
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 static const uint8_t l0_l1_cand_idx
[12][2] = {
41 void ff_hevc_set_neighbour_available(HEVCContext
*s
, int x0
, int y0
,
44 HEVCLocalContext
*lc
= s
->HEVClc
;
45 int x0b
= x0
& ((1 << s
->sps
->log2_ctb_size
) - 1);
46 int y0b
= y0
& ((1 << s
->sps
->log2_ctb_size
) - 1);
48 lc
->na
.cand_up
= (lc
->ctb_up_flag
|| y0b
);
49 lc
->na
.cand_left
= (lc
->ctb_left_flag
|| x0b
);
50 lc
->na
.cand_up_left
= (!x0b
&& !y0b
) ? lc
->ctb_up_left_flag
: lc
->na
.cand_left
&& lc
->na
.cand_up
;
51 lc
->na
.cand_up_right_sap
=
52 ((x0b
+ nPbW
) == (1 << s
->sps
->log2_ctb_size
)) ?
53 lc
->ctb_up_right_flag
&& !y0b
: lc
->na
.cand_up
;
54 lc
->na
.cand_up_right
=
55 lc
->na
.cand_up_right_sap
56 && (x0
+ nPbW
) < lc
->end_of_tiles_x
;
57 lc
->na
.cand_bottom_left
= ((y0
+ nPbH
) >= lc
->end_of_tiles_y
) ? 0 : lc
->na
.cand_left
;
61 * 6.4.1 Derivation process for z-scan order block availability
63 static av_always_inline
int z_scan_block_avail(HEVCContext
*s
, int xCurr
, int yCurr
,
66 #define MIN_TB_ADDR_ZS(x, y) \
67 s->pps->min_tb_addr_zs[(y) * (s->sps->tb_mask+2) + (x)]
69 int xCurr_ctb
= xCurr
>> s
->sps
->log2_ctb_size
;
70 int yCurr_ctb
= yCurr
>> s
->sps
->log2_ctb_size
;
71 int xN_ctb
= xN
>> s
->sps
->log2_ctb_size
;
72 int yN_ctb
= yN
>> s
->sps
->log2_ctb_size
;
73 if( yN_ctb
< yCurr_ctb
|| xN_ctb
< xCurr_ctb
)
76 int Curr
= MIN_TB_ADDR_ZS((xCurr
>> s
->sps
->log2_min_tb_size
) & s
->sps
->tb_mask
,
77 (yCurr
>> s
->sps
->log2_min_tb_size
) & s
->sps
->tb_mask
);
78 int N
= MIN_TB_ADDR_ZS((xN
>> s
->sps
->log2_min_tb_size
) & s
->sps
->tb_mask
,
79 (yN
>> s
->sps
->log2_min_tb_size
) & s
->sps
->tb_mask
);
84 //check if the two luma locations belong to the same mostion estimation region
85 static av_always_inline
int is_diff_mer(HEVCContext
*s
, int xN
, int yN
, int xP
, int yP
)
87 uint8_t plevel
= s
->pps
->log2_parallel_merge_level
;
89 return xN
>> plevel
== xP
>> plevel
&&
90 yN
>> plevel
== yP
>> plevel
;
93 #define MATCH_MV(x) (AV_RN32A(&A.x) == AV_RN32A(&B.x))
94 #define MATCH(x) (A.x == B.x)
96 // check if the mv's and refidx are the same between A and B
97 static av_always_inline
int compare_mv_ref_idx(struct MvField A
, struct MvField B
)
99 int a_pf
= A
.pred_flag
;
100 int b_pf
= B
.pred_flag
;
103 return MATCH(ref_idx
[0]) && MATCH_MV(mv
[0]) &&
104 MATCH(ref_idx
[1]) && MATCH_MV(mv
[1]);
105 } else if (a_pf
== PF_L0
) {
106 return MATCH(ref_idx
[0]) && MATCH_MV(mv
[0]);
107 } else if (a_pf
== PF_L1
) {
108 return MATCH(ref_idx
[1]) && MATCH_MV(mv
[1]);
114 static av_always_inline
void mv_scale(Mv
*dst
, Mv
*src
, int td
, int tb
)
116 int tx
, scale_factor
;
118 td
= av_clip_int8(td
);
119 tb
= av_clip_int8(tb
);
120 tx
= (0x4000 + abs(td
/ 2)) / td
;
121 scale_factor
= av_clip((tb
* tx
+ 32) >> 6, -4096, 4095);
122 dst
->x
= av_clip_int16((scale_factor
* src
->x
+ 127 +
123 (scale_factor
* src
->x
< 0)) >> 8);
124 dst
->y
= av_clip_int16((scale_factor
* src
->y
+ 127 +
125 (scale_factor
* src
->y
< 0)) >> 8);
128 static int check_mvset(Mv
*mvLXCol
, Mv
*mvCol
,
130 RefPicList
*refPicList
, int X
, int refIdxLx
,
131 RefPicList
*refPicList_col
, int listCol
, int refidxCol
)
133 int cur_lt
= refPicList
[X
].isLongTerm
[refIdxLx
];
134 int col_lt
= refPicList_col
[listCol
].isLongTerm
[refidxCol
];
135 int col_poc_diff
, cur_poc_diff
;
137 if (cur_lt
!= col_lt
) {
143 col_poc_diff
= colPic
- refPicList_col
[listCol
].list
[refidxCol
];
144 cur_poc_diff
= poc
- refPicList
[X
].list
[refIdxLx
];
146 if (cur_lt
|| col_poc_diff
== cur_poc_diff
|| !col_poc_diff
) {
147 mvLXCol
->x
= mvCol
->x
;
148 mvLXCol
->y
= mvCol
->y
;
150 mv_scale(mvLXCol
, mvCol
, col_poc_diff
, cur_poc_diff
);
155 #define CHECK_MVSET(l) \
156 check_mvset(mvLXCol, temp_col.mv + l, \
158 refPicList, X, refIdxLx, \
159 refPicList_col, L ## l, temp_col.ref_idx[l])
161 // derive the motion vectors section 8.5.3.1.8
162 static int derive_temporal_colocated_mvs(HEVCContext
*s
, MvField temp_col
,
163 int refIdxLx
, Mv
*mvLXCol
, int X
,
164 int colPic
, RefPicList
*refPicList_col
)
166 RefPicList
*refPicList
= s
->ref
->refPicList
;
168 if (temp_col
.pred_flag
== PF_INTRA
)
171 if (!(temp_col
.pred_flag
& PF_L0
))
172 return CHECK_MVSET(1);
173 else if (temp_col
.pred_flag
== PF_L0
)
174 return CHECK_MVSET(0);
175 else if (temp_col
.pred_flag
== PF_BI
) {
176 int check_diffpicount
= 0;
178 for (j
= 0; j
< 2; j
++) {
179 for (i
= 0; i
< refPicList
[j
].nb_refs
; i
++) {
180 if (refPicList
[j
].list
[i
] > s
->poc
) {
186 if (!check_diffpicount
) {
188 return CHECK_MVSET(0);
190 return CHECK_MVSET(1);
192 if (s
->sh
.collocated_list
== L1
)
193 return CHECK_MVSET(0);
195 return CHECK_MVSET(1);
202 #define TAB_MVF(x, y) \
203 tab_mvf[(y) * min_pu_width + x]
205 #define TAB_MVF_PU(v) \
206 TAB_MVF(((x ## v) >> s->sps->log2_min_pu_size), \
207 ((y ## v) >> s->sps->log2_min_pu_size))
209 #define DERIVE_TEMPORAL_COLOCATED_MVS \
210 derive_temporal_colocated_mvs(s, temp_col, \
211 refIdxLx, mvLXCol, X, colPic, \
212 ff_hevc_get_ref_list(s, ref, x, y))
215 * 8.5.3.1.7 temporal luma motion vector prediction
217 static int temporal_luma_motion_vector(HEVCContext
*s
, int x0
, int y0
,
218 int nPbW
, int nPbH
, int refIdxLx
,
223 int x
, y
, x_pu
, y_pu
;
224 int min_pu_width
= s
->sps
->min_pu_width
;
225 int availableFlagLXCol
= 0;
228 HEVCFrame
*ref
= s
->ref
->collocated_ref
;
231 memset(mvLXCol
, 0, sizeof(*mvLXCol
));
235 tab_mvf
= ref
->tab_mvf
;
238 //bottom right collocated motion vector
243 (y0
>> s
->sps
->log2_ctb_size
) == (y
>> s
->sps
->log2_ctb_size
) &&
244 y
< s
->sps
->height
&&
248 if (s
->threads_type
== FF_THREAD_FRAME
)
249 ff_thread_await_progress(&ref
->tf
, y
, 0);
250 x_pu
= x
>> s
->sps
->log2_min_pu_size
;
251 y_pu
= y
>> s
->sps
->log2_min_pu_size
;
252 temp_col
= TAB_MVF(x_pu
, y_pu
);
253 availableFlagLXCol
= DERIVE_TEMPORAL_COLOCATED_MVS
;
256 // derive center collocated motion vector
257 if (tab_mvf
&& !availableFlagLXCol
) {
258 x
= x0
+ (nPbW
>> 1);
259 y
= y0
+ (nPbH
>> 1);
262 if (s
->threads_type
== FF_THREAD_FRAME
)
263 ff_thread_await_progress(&ref
->tf
, y
, 0);
264 x_pu
= x
>> s
->sps
->log2_min_pu_size
;
265 y_pu
= y
>> s
->sps
->log2_min_pu_size
;
266 temp_col
= TAB_MVF(x_pu
, y_pu
);
267 availableFlagLXCol
= DERIVE_TEMPORAL_COLOCATED_MVS
;
269 return availableFlagLXCol
;
272 #define AVAILABLE(cand, v) \
273 (cand && !(TAB_MVF_PU(v).pred_flag == PF_INTRA))
275 #define PRED_BLOCK_AVAILABLE(v) \
276 z_scan_block_avail(s, x0, y0, x ## v, y ## v)
278 #define COMPARE_MV_REFIDX(a, b) \
279 compare_mv_ref_idx(TAB_MVF_PU(a), TAB_MVF_PU(b))
282 * 8.5.3.1.2 Derivation process for spatial merging candidates
284 static void derive_spatial_merge_candidates(HEVCContext
*s
, int x0
, int y0
,
287 int singleMCLFlag
, int part_idx
,
289 struct MvField mergecandlist
[])
291 HEVCLocalContext
*lc
= s
->HEVClc
;
292 RefPicList
*refPicList
= s
->ref
->refPicList
;
293 MvField
*tab_mvf
= s
->ref
->tab_mvf
;
295 const int min_pu_width
= s
->sps
->min_pu_width
;
297 const int cand_bottom_left
= lc
->na
.cand_bottom_left
;
298 const int cand_left
= lc
->na
.cand_left
;
299 const int cand_up_left
= lc
->na
.cand_up_left
;
300 const int cand_up
= lc
->na
.cand_up
;
301 const int cand_up_right
= lc
->na
.cand_up_right_sap
;
303 const int xA1
= x0
- 1;
304 const int yA1
= y0
+ nPbH
- 1;
306 const int xB1
= x0
+ nPbW
- 1;
307 const int yB1
= y0
- 1;
309 const int xB0
= x0
+ nPbW
;
310 const int yB0
= y0
- 1;
312 const int xA0
= x0
- 1;
313 const int yA0
= y0
+ nPbH
;
315 const int xB2
= x0
- 1;
316 const int yB2
= y0
- 1;
318 const int nb_refs
= (s
->sh
.slice_type
== P_SLICE
) ?
319 s
->sh
.nb_refs
[0] : FFMIN(s
->sh
.nb_refs
[0], s
->sh
.nb_refs
[1]);
323 int nb_merge_cand
= 0;
324 int nb_orig_merge_cand
= 0;
333 if (!singleMCLFlag
&& part_idx
== 1 &&
334 (lc
->cu
.part_mode
== PART_Nx2N
||
335 lc
->cu
.part_mode
== PART_nLx2N
||
336 lc
->cu
.part_mode
== PART_nRx2N
) ||
337 is_diff_mer(s
, xA1
, yA1
, x0
, y0
)) {
340 is_available_a1
= AVAILABLE(cand_left
, A1
);
341 if (is_available_a1
) {
342 mergecandlist
[nb_merge_cand
] = TAB_MVF_PU(A1
);
349 if (!singleMCLFlag
&& part_idx
== 1 &&
350 (lc
->cu
.part_mode
== PART_2NxN
||
351 lc
->cu
.part_mode
== PART_2NxnU
||
352 lc
->cu
.part_mode
== PART_2NxnD
) ||
353 is_diff_mer(s
, xB1
, yB1
, x0
, y0
)) {
356 is_available_b1
= AVAILABLE(cand_up
, B1
);
357 if (is_available_b1
&&
358 !(is_available_a1
&& COMPARE_MV_REFIDX(B1
, A1
))) {
359 mergecandlist
[nb_merge_cand
] = TAB_MVF_PU(B1
);
360 if (merge_idx
== nb_merge_cand
)
366 // above right spatial merge candidate
367 is_available_b0
= AVAILABLE(cand_up_right
, B0
) &&
368 xB0
< s
->sps
->width
&&
369 PRED_BLOCK_AVAILABLE(B0
) &&
370 !is_diff_mer(s
, xB0
, yB0
, x0
, y0
);
372 if (is_available_b0
&&
373 !(is_available_b1
&& COMPARE_MV_REFIDX(B0
, B1
))) {
374 mergecandlist
[nb_merge_cand
] = TAB_MVF_PU(B0
);
375 if (merge_idx
== nb_merge_cand
)
380 // left bottom spatial merge candidate
381 is_available_a0
= AVAILABLE(cand_bottom_left
, A0
) &&
382 yA0
< s
->sps
->height
&&
383 PRED_BLOCK_AVAILABLE(A0
) &&
384 !is_diff_mer(s
, xA0
, yA0
, x0
, y0
);
386 if (is_available_a0
&&
387 !(is_available_a1
&& COMPARE_MV_REFIDX(A0
, A1
))) {
388 mergecandlist
[nb_merge_cand
] = TAB_MVF_PU(A0
);
389 if (merge_idx
== nb_merge_cand
)
394 // above left spatial merge candidate
395 is_available_b2
= AVAILABLE(cand_up_left
, B2
) &&
396 !is_diff_mer(s
, xB2
, yB2
, x0
, y0
);
398 if (is_available_b2
&&
399 !(is_available_a1
&& COMPARE_MV_REFIDX(B2
, A1
)) &&
400 !(is_available_b1
&& COMPARE_MV_REFIDX(B2
, B1
)) &&
401 nb_merge_cand
!= 4) {
402 mergecandlist
[nb_merge_cand
] = TAB_MVF_PU(B2
);
403 if (merge_idx
== nb_merge_cand
)
408 // temporal motion vector candidate
409 if (s
->sh
.slice_temporal_mvp_enabled_flag
&&
410 nb_merge_cand
< s
->sh
.max_num_merge_cand
) {
411 Mv mv_l0_col
= { 0 }, mv_l1_col
= { 0 };
412 int available_l0
= temporal_luma_motion_vector(s
, x0
, y0
, nPbW
, nPbH
,
414 int available_l1
= (s
->sh
.slice_type
== B_SLICE
) ?
415 temporal_luma_motion_vector(s
, x0
, y0
, nPbW
, nPbH
,
416 0, &mv_l1_col
, 1) : 0;
418 if (available_l0
|| available_l1
) {
419 mergecandlist
[nb_merge_cand
].pred_flag
= available_l0
+ (available_l1
<< 1);
420 AV_ZERO16(mergecandlist
[nb_merge_cand
].ref_idx
);
421 mergecandlist
[nb_merge_cand
].mv
[0] = mv_l0_col
;
422 mergecandlist
[nb_merge_cand
].mv
[1] = mv_l1_col
;
424 if (merge_idx
== nb_merge_cand
)
430 nb_orig_merge_cand
= nb_merge_cand
;
432 // combined bi-predictive merge candidates (applies for B slices)
433 if (s
->sh
.slice_type
== B_SLICE
&& nb_orig_merge_cand
> 1 &&
434 nb_orig_merge_cand
< s
->sh
.max_num_merge_cand
) {
437 for (comb_idx
= 0; nb_merge_cand
< s
->sh
.max_num_merge_cand
&&
438 comb_idx
< nb_orig_merge_cand
* (nb_orig_merge_cand
- 1); comb_idx
++) {
439 int l0_cand_idx
= l0_l1_cand_idx
[comb_idx
][0];
440 int l1_cand_idx
= l0_l1_cand_idx
[comb_idx
][1];
441 MvField l0_cand
= mergecandlist
[l0_cand_idx
];
442 MvField l1_cand
= mergecandlist
[l1_cand_idx
];
444 if ((l0_cand
.pred_flag
& PF_L0
) && (l1_cand
.pred_flag
& PF_L1
) &&
445 (refPicList
[0].list
[l0_cand
.ref_idx
[0]] !=
446 refPicList
[1].list
[l1_cand
.ref_idx
[1]] ||
447 AV_RN32A(&l0_cand
.mv
[0]) != AV_RN32A(&l1_cand
.mv
[1]))) {
448 mergecandlist
[nb_merge_cand
].ref_idx
[0] = l0_cand
.ref_idx
[0];
449 mergecandlist
[nb_merge_cand
].ref_idx
[1] = l1_cand
.ref_idx
[1];
450 mergecandlist
[nb_merge_cand
].pred_flag
= PF_BI
;
451 AV_COPY32(&mergecandlist
[nb_merge_cand
].mv
[0], &l0_cand
.mv
[0]);
452 AV_COPY32(&mergecandlist
[nb_merge_cand
].mv
[1], &l1_cand
.mv
[1]);
453 if (merge_idx
== nb_merge_cand
)
460 // append Zero motion vector candidates
461 while (nb_merge_cand
< s
->sh
.max_num_merge_cand
) {
462 mergecandlist
[nb_merge_cand
].pred_flag
= PF_L0
+ ((s
->sh
.slice_type
== B_SLICE
) << 1);
463 AV_ZERO32(mergecandlist
[nb_merge_cand
].mv
+ 0);
464 AV_ZERO32(mergecandlist
[nb_merge_cand
].mv
+ 1);
465 mergecandlist
[nb_merge_cand
].ref_idx
[0] = zero_idx
< nb_refs
? zero_idx
: 0;
466 mergecandlist
[nb_merge_cand
].ref_idx
[1] = zero_idx
< nb_refs
? zero_idx
: 0;
468 if (merge_idx
== nb_merge_cand
)
476 * 8.5.3.1.1 Derivation process of luma Mvs for merge mode
478 void ff_hevc_luma_mv_merge_mode(HEVCContext
*s
, int x0
, int y0
, int nPbW
,
479 int nPbH
, int log2_cb_size
, int part_idx
,
480 int merge_idx
, MvField
*mv
)
482 int singleMCLFlag
= 0;
483 int nCS
= 1 << log2_cb_size
;
484 LOCAL_ALIGNED(4, MvField
, mergecand_list
, [MRG_MAX_NUM_CANDS
]);
487 HEVCLocalContext
*lc
= s
->HEVClc
;
489 if (s
->pps
->log2_parallel_merge_level
> 2 && nCS
== 8) {
498 ff_hevc_set_neighbour_available(s
, x0
, y0
, nPbW
, nPbH
);
499 derive_spatial_merge_candidates(s
, x0
, y0
, nPbW
, nPbH
, log2_cb_size
,
500 singleMCLFlag
, part_idx
,
501 merge_idx
, mergecand_list
);
503 if (mergecand_list
[merge_idx
].pred_flag
== PF_BI
&&
504 (nPbW2
+ nPbH2
) == 12) {
505 mergecand_list
[merge_idx
].pred_flag
= PF_L0
;
508 *mv
= mergecand_list
[merge_idx
];
511 static av_always_inline
void dist_scale(HEVCContext
*s
, Mv
*mv
,
512 int min_pu_width
, int x
, int y
,
513 int elist
, int ref_idx_curr
, int ref_idx
)
515 RefPicList
*refPicList
= s
->ref
->refPicList
;
516 MvField
*tab_mvf
= s
->ref
->tab_mvf
;
517 int ref_pic_elist
= refPicList
[elist
].list
[TAB_MVF(x
, y
).ref_idx
[elist
]];
518 int ref_pic_curr
= refPicList
[ref_idx_curr
].list
[ref_idx
];
520 if (ref_pic_elist
!= ref_pic_curr
) {
521 int poc_diff
= s
->poc
- ref_pic_elist
;
524 mv_scale(mv
, mv
, poc_diff
, s
->poc
- ref_pic_curr
);
528 static int mv_mp_mode_mx(HEVCContext
*s
, int x
, int y
, int pred_flag_index
,
529 Mv
*mv
, int ref_idx_curr
, int ref_idx
)
531 MvField
*tab_mvf
= s
->ref
->tab_mvf
;
532 int min_pu_width
= s
->sps
->min_pu_width
;
534 RefPicList
*refPicList
= s
->ref
->refPicList
;
536 if (((TAB_MVF(x
, y
).pred_flag
) & (1 << pred_flag_index
)) &&
537 refPicList
[pred_flag_index
].list
[TAB_MVF(x
, y
).ref_idx
[pred_flag_index
]] == refPicList
[ref_idx_curr
].list
[ref_idx
]) {
538 *mv
= TAB_MVF(x
, y
).mv
[pred_flag_index
];
544 static int mv_mp_mode_mx_lt(HEVCContext
*s
, int x
, int y
, int pred_flag_index
,
545 Mv
*mv
, int ref_idx_curr
, int ref_idx
)
547 MvField
*tab_mvf
= s
->ref
->tab_mvf
;
548 int min_pu_width
= s
->sps
->min_pu_width
;
550 RefPicList
*refPicList
= s
->ref
->refPicList
;
552 if ((TAB_MVF(x
, y
).pred_flag
) & (1 << pred_flag_index
)) {
553 int currIsLongTerm
= refPicList
[ref_idx_curr
].isLongTerm
[ref_idx
];
556 refPicList
[pred_flag_index
].isLongTerm
[(TAB_MVF(x
, y
).ref_idx
[pred_flag_index
])];
558 if (colIsLongTerm
== currIsLongTerm
) {
559 *mv
= TAB_MVF(x
, y
).mv
[pred_flag_index
];
561 dist_scale(s
, mv
, min_pu_width
, x
, y
,
562 pred_flag_index
, ref_idx_curr
, ref_idx
);
569 #define MP_MX(v, pred, mx) \
571 (x ## v) >> s->sps->log2_min_pu_size, \
572 (y ## v) >> s->sps->log2_min_pu_size, \
573 pred, &mx, ref_idx_curr, ref_idx)
575 #define MP_MX_LT(v, pred, mx) \
576 mv_mp_mode_mx_lt(s, \
577 (x ## v) >> s->sps->log2_min_pu_size, \
578 (y ## v) >> s->sps->log2_min_pu_size, \
579 pred, &mx, ref_idx_curr, ref_idx)
581 void ff_hevc_luma_mv_mvp_mode(HEVCContext
*s
, int x0
, int y0
, int nPbW
,
582 int nPbH
, int log2_cb_size
, int part_idx
,
583 int merge_idx
, MvField
*mv
,
584 int mvp_lx_flag
, int LX
)
586 HEVCLocalContext
*lc
= s
->HEVClc
;
587 MvField
*tab_mvf
= s
->ref
->tab_mvf
;
588 int isScaledFlag_L0
= 0;
589 int availableFlagLXA0
= 1;
590 int availableFlagLXB0
= 1;
591 int numMVPCandLX
= 0;
592 int min_pu_width
= s
->sps
->min_pu_width
;
605 Mv mvpcand_list
[2] = { { 0 } };
610 int pred_flag_index_l0
;
611 int pred_flag_index_l1
;
613 const int cand_bottom_left
= lc
->na
.cand_bottom_left
;
614 const int cand_left
= lc
->na
.cand_left
;
615 const int cand_up_left
= lc
->na
.cand_up_left
;
616 const int cand_up
= lc
->na
.cand_up
;
617 const int cand_up_right
= lc
->na
.cand_up_right_sap
;
619 ref_idx
= mv
->ref_idx
[LX
];
620 pred_flag_index_l0
= LX
;
621 pred_flag_index_l1
= !LX
;
623 // left bottom spatial candidate
627 is_available_a0
= AVAILABLE(cand_bottom_left
, A0
) &&
628 yA0
< s
->sps
->height
&&
629 PRED_BLOCK_AVAILABLE(A0
);
631 //left spatial merge candidate
635 is_available_a1
= AVAILABLE(cand_left
, A1
);
636 if (is_available_a0
|| is_available_a1
)
639 if (is_available_a0
) {
640 if (MP_MX(A0
, pred_flag_index_l0
, mxA
)) {
643 if (MP_MX(A0
, pred_flag_index_l1
, mxA
)) {
648 if (is_available_a1
) {
649 if (MP_MX(A1
, pred_flag_index_l0
, mxA
)) {
652 if (MP_MX(A1
, pred_flag_index_l1
, mxA
)) {
657 if (is_available_a0
) {
658 if (MP_MX_LT(A0
, pred_flag_index_l0
, mxA
)) {
661 if (MP_MX_LT(A0
, pred_flag_index_l1
, mxA
)) {
666 if (is_available_a1
) {
667 if (MP_MX_LT(A1
, pred_flag_index_l0
, mxA
)) {
670 if (MP_MX_LT(A1
, pred_flag_index_l1
, mxA
)) {
674 availableFlagLXA0
= 0;
678 // above right spatial merge candidate
682 is_available_b0
= AVAILABLE(cand_up_right
, B0
) &&
683 xB0
< s
->sps
->width
&&
684 PRED_BLOCK_AVAILABLE(B0
);
686 // above spatial merge candidate
689 is_available_b1
= AVAILABLE(cand_up
, B1
);
691 // above left spatial merge candidate
694 is_available_b2
= AVAILABLE(cand_up_left
, B2
);
696 // above right spatial merge candidate
697 if (is_available_b0
) {
698 if (MP_MX(B0
, pred_flag_index_l0
, mxB
)) {
701 if (MP_MX(B0
, pred_flag_index_l1
, mxB
)) {
706 // above spatial merge candidate
707 if (is_available_b1
) {
708 if (MP_MX(B1
, pred_flag_index_l0
, mxB
)) {
711 if (MP_MX(B1
, pred_flag_index_l1
, mxB
)) {
716 // above left spatial merge candidate
717 if (is_available_b2
) {
718 if (MP_MX(B2
, pred_flag_index_l0
, mxB
)) {
721 if (MP_MX(B2
, pred_flag_index_l1
, mxB
)) {
725 availableFlagLXB0
= 0;
728 if (!isScaledFlag_L0
) {
729 if (availableFlagLXB0
) {
730 availableFlagLXA0
= 1;
733 availableFlagLXB0
= 0;
736 if (is_available_b0
) {
737 availableFlagLXB0
= MP_MX_LT(B0
, pred_flag_index_l0
, mxB
);
738 if (!availableFlagLXB0
)
739 availableFlagLXB0
= MP_MX_LT(B0
, pred_flag_index_l1
, mxB
);
742 if (is_available_b1
&& !availableFlagLXB0
) {
743 availableFlagLXB0
= MP_MX_LT(B1
, pred_flag_index_l0
, mxB
);
744 if (!availableFlagLXB0
)
745 availableFlagLXB0
= MP_MX_LT(B1
, pred_flag_index_l1
, mxB
);
748 if (is_available_b2
&& !availableFlagLXB0
) {
749 availableFlagLXB0
= MP_MX_LT(B2
, pred_flag_index_l0
, mxB
);
750 if (!availableFlagLXB0
)
751 availableFlagLXB0
= MP_MX_LT(B2
, pred_flag_index_l1
, mxB
);
755 if (availableFlagLXA0
)
756 mvpcand_list
[numMVPCandLX
++] = mxA
;
758 if (availableFlagLXB0
&& (!availableFlagLXA0
|| mxA
.x
!= mxB
.x
|| mxA
.y
!= mxB
.y
))
759 mvpcand_list
[numMVPCandLX
++] = mxB
;
761 //temporal motion vector prediction candidate
762 if (numMVPCandLX
< 2 && s
->sh
.slice_temporal_mvp_enabled_flag
&&
763 mvp_lx_flag
== numMVPCandLX
) {
765 int available_col
= temporal_luma_motion_vector(s
, x0
, y0
, nPbW
,
769 mvpcand_list
[numMVPCandLX
++] = mv_col
;
772 mv
->mv
[LX
] = mvpcand_list
[mvp_lx_flag
];