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