yN >> plevel == yP >> plevel;
}
+#define MATCH_MV(x) (AV_RN32A(&A.x) == AV_RN32A(&B.x))
#define MATCH(x) (A.x == B.x)
// check if the mv's and refidx are the same between A and B
static int compareMVrefidx(struct MvField A, struct MvField B)
{
if (A.pred_flag[0] && A.pred_flag[1] && B.pred_flag[0] && B.pred_flag[1])
- return MATCH(ref_idx[0]) && MATCH(mv[0].x) && MATCH(mv[0].y) &&
- MATCH(ref_idx[1]) && MATCH(mv[1].x) && MATCH(mv[1].y);
+ return MATCH(ref_idx[0]) && MATCH_MV(mv[0]) &&
+ MATCH(ref_idx[1]) && MATCH_MV(mv[1]);
if (A.pred_flag[0] && !A.pred_flag[1] && B.pred_flag[0] && !B.pred_flag[1])
- return MATCH(ref_idx[0]) && MATCH(mv[0].x) && MATCH(mv[0].y);
+ return MATCH(ref_idx[0]) && MATCH_MV(mv[0]);
if (!A.pred_flag[0] && A.pred_flag[1] && !B.pred_flag[0] && B.pred_flag[1])
- return MATCH(ref_idx[1]) && MATCH(mv[1].x) && MATCH(mv[1].y);
+ return MATCH(ref_idx[1]) && MATCH_MV(mv[1]);
return 0;
}
HEVCFrame *ref = s->ref->collocated_ref;
- if (!ref)
+ if (!ref) {
+ memset(mvLXCol, 0, sizeof(*mvLXCol));
return 0;
+ }
tab_mvf = ref->tab_mvf;
colPic = ref->poc;
x = x0 + nPbW;
y = y0 + nPbH;
- ff_thread_await_progress(&ref->tf, y, 0);
if (tab_mvf &&
(y0 >> s->sps->log2_ctb_size) == (y >> s->sps->log2_ctb_size) &&
y < s->sps->height &&
x < s->sps->width) {
- x = ((x >> 4) << 4);
- y = ((y >> 4) << 4);
+ x &= ~15;
+ y &= ~15;
+ ff_thread_await_progress(&ref->tf, y, 0);
x_pu = x >> s->sps->log2_min_pu_size;
y_pu = y >> s->sps->log2_min_pu_size;
temp_col = TAB_MVF(x_pu, y_pu);
if (tab_mvf && !availableFlagLXCol) {
x = x0 + (nPbW >> 1);
y = y0 + (nPbH >> 1);
- x = ((x >> 4) << 4);
- y = ((y >> 4) << 4);
+ x &= ~15;
+ y &= ~15;
+ ff_thread_await_progress(&ref->tf, y, 0);
x_pu = x >> s->sps->log2_min_pu_size;
y_pu = y >> s->sps->log2_min_pu_size;
temp_col = TAB_MVF(x_pu, y_pu);
int nPbW, int nPbH,
int log2_cb_size,
int singleMCLFlag, int part_idx,
+ int merge_idx,
struct MvField mergecandlist[])
{
HEVCLocalContext *lc = &s->HEVClc;
is_available_a1 = 0;
}
- if (is_available_a1)
- mergecandlist[nb_merge_cand++] = TAB_MVF_PU(A1);
+ if (is_available_a1) {
+ mergecandlist[0] = TAB_MVF_PU(A1);
+ if (merge_idx == 0)
+ return;
+ nb_merge_cand++;
+ }
// above spatial merge candidate
is_available_b1 = AVAILABLE(cand_up, B1);
if (is_available_b1 && is_available_b0)
check_MER = !COMPARE_MV_REFIDX(B0, B1);
- if (is_available_b0 && check_MER)
- mergecandlist[nb_merge_cand++] = TAB_MVF_PU(B0);
+ if (is_available_b0 && check_MER) {
+ mergecandlist[nb_merge_cand] = TAB_MVF_PU(B0);
+ if (merge_idx == nb_merge_cand)
+ return;
+ nb_merge_cand++;
+ }
// left bottom spatial merge candidate
check_MER = 1;
if (is_available_a1 && is_available_a0)
check_MER = !COMPARE_MV_REFIDX(A0, A1);
- if (is_available_a0 && check_MER)
- mergecandlist[nb_merge_cand++] = TAB_MVF_PU(A0);
+ if (is_available_a0 && check_MER) {
+ mergecandlist[nb_merge_cand] = TAB_MVF_PU(A0);
+ if (merge_idx == nb_merge_cand)
+ return;
+ nb_merge_cand++;
+ }
// above left spatial merge candidate
check_MER = 1;
if (is_available_b1 && is_available_b2)
check_MER_1 = !COMPARE_MV_REFIDX(B2, B1);
- if (is_available_b2 && check_MER && check_MER_1 && nb_merge_cand != 4)
- mergecandlist[nb_merge_cand++] = TAB_MVF_PU(B2);
+ if (is_available_b2 && check_MER && check_MER_1 && nb_merge_cand != 4) {
+ mergecandlist[nb_merge_cand] = TAB_MVF_PU(B2);
+ if (merge_idx == nb_merge_cand)
+ return;
+ nb_merge_cand++;
+ }
// temporal motion vector candidate
if (s->sh.slice_temporal_mvp_enabled_flag &&
nb_merge_cand < s->sh.max_num_merge_cand) {
- Mv mv_l0_col, mv_l1_col;
+ Mv mv_l0_col = { 0 }, mv_l1_col = { 0 };
int available_l0 = temporal_luma_motion_vector(s, x0, y0, nPbW, nPbH,
0, &mv_l0_col, 0);
int available_l1 = (s->sh.slice_type == B_SLICE) ?
mergecandlist[nb_merge_cand].is_intra = 0;
mergecandlist[nb_merge_cand].pred_flag[0] = available_l0;
mergecandlist[nb_merge_cand].pred_flag[1] = available_l1;
- if (available_l0) {
- mergecandlist[nb_merge_cand].mv[0] = mv_l0_col;
- mergecandlist[nb_merge_cand].ref_idx[0] = 0;
- }
- if (available_l1) {
- mergecandlist[nb_merge_cand].mv[1] = mv_l1_col;
- mergecandlist[nb_merge_cand].ref_idx[1] = 0;
- }
+ AV_ZERO16(mergecandlist[nb_merge_cand].ref_idx);
+ mergecandlist[nb_merge_cand].mv[0] = mv_l0_col;
+ mergecandlist[nb_merge_cand].mv[1] = mv_l1_col;
+
+ if (merge_idx == nb_merge_cand)
+ return;
nb_merge_cand++;
}
}
if (l0_cand.pred_flag[0] && l1_cand.pred_flag[1] &&
(refPicList[0].list[l0_cand.ref_idx[0]] !=
refPicList[1].list[l1_cand.ref_idx[1]] ||
- l0_cand.mv[0].x != l1_cand.mv[1].x ||
- l0_cand.mv[0].y != l1_cand.mv[1].y)) {
+ AV_RN32A(&l0_cand.mv[0]) != AV_RN32A(&l1_cand.mv[1]))) {
mergecandlist[nb_merge_cand].ref_idx[0] = l0_cand.ref_idx[0];
mergecandlist[nb_merge_cand].ref_idx[1] = l1_cand.ref_idx[1];
mergecandlist[nb_merge_cand].pred_flag[0] = 1;
mergecandlist[nb_merge_cand].pred_flag[1] = 1;
- mergecandlist[nb_merge_cand].mv[0].x = l0_cand.mv[0].x;
- mergecandlist[nb_merge_cand].mv[0].y = l0_cand.mv[0].y;
- mergecandlist[nb_merge_cand].mv[1].x = l1_cand.mv[1].x;
- mergecandlist[nb_merge_cand].mv[1].y = l1_cand.mv[1].y;
+ AV_COPY32(&mergecandlist[nb_merge_cand].mv[0], &l0_cand.mv[0]);
+ AV_COPY32(&mergecandlist[nb_merge_cand].mv[1], &l1_cand.mv[1]);
mergecandlist[nb_merge_cand].is_intra = 0;
+ if (merge_idx == nb_merge_cand)
+ return;
nb_merge_cand++;
}
}
while (nb_merge_cand < s->sh.max_num_merge_cand) {
mergecandlist[nb_merge_cand].pred_flag[0] = 1;
mergecandlist[nb_merge_cand].pred_flag[1] = s->sh.slice_type == B_SLICE;
- mergecandlist[nb_merge_cand].mv[0].x = 0;
- mergecandlist[nb_merge_cand].mv[0].y = 0;
- mergecandlist[nb_merge_cand].mv[1].x = 0;
- mergecandlist[nb_merge_cand].mv[1].y = 0;
+ AV_ZERO32(mergecandlist[nb_merge_cand].mv + 0);
+ AV_ZERO32(mergecandlist[nb_merge_cand].mv + 1);
mergecandlist[nb_merge_cand].is_intra = 0;
mergecandlist[nb_merge_cand].ref_idx[0] = zero_idx < nb_refs ? zero_idx : 0;
mergecandlist[nb_merge_cand].ref_idx[1] = zero_idx < nb_refs ? zero_idx : 0;
+ if (merge_idx == nb_merge_cand)
+ return;
nb_merge_cand++;
zero_idx++;
}
{
int singleMCLFlag = 0;
int nCS = 1 << log2_cb_size;
- struct MvField mergecand_list[MRG_MAX_NUM_CANDS] = { { { { 0 } } } };
+ LOCAL_ALIGNED(4, MvField, mergecand_list, [MRG_MAX_NUM_CANDS]);
int nPbW2 = nPbW;
int nPbH2 = nPbH;
HEVCLocalContext *lc = &s->HEVClc;
ff_hevc_set_neighbour_available(s, x0, y0, nPbW, nPbH);
derive_spatial_merge_candidates(s, x0, y0, nPbW, nPbH, log2_cb_size,
- singleMCLFlag, part_idx, mergecand_list);
+ singleMCLFlag, part_idx,
+ merge_idx, mergecand_list);
if (mergecand_list[merge_idx].pred_flag[0] == 1 &&
mergecand_list[merge_idx].pred_flag[1] == 1 &&
availableFlagLXA0 = MP_MX_LT(A1, pred_flag_index_l1, mxA);
}
+ if (availableFlagLXA0 && !mvp_lx_flag) {
+ mv->mv[LX] = mxA;
+ return;
+ }
+
// B candidates
// above right spatial merge candidate
xB0 = x0 + nPbW;
mvpcand_list[numMVPCandLX++] = mxB;
//temporal motion vector prediction candidate
- if (numMVPCandLX < 2 && s->sh.slice_temporal_mvp_enabled_flag) {
+ if (numMVPCandLX < 2 && s->sh.slice_temporal_mvp_enabled_flag &&
+ mvp_lx_flag == numMVPCandLX) {
Mv mv_col;
int available_col = temporal_luma_motion_vector(s, x0, y0, nPbW,
nPbH, ref_idx,