Go to the documentation of this file.
28 #define IS_SAME_MV(a, b) (AV_RN64A(a) == AV_RN64A(b))
33 const uint8_t plevel =
fc->ps.sps->log2_parallel_merge_level;
35 return xN >> plevel == xP >> plevel &&
36 yN >> plevel == yP >> plevel;
44 for (
int i = 0;
i < 2;
i++) {
49 if (!same_ref_idx || !same_mv)
59 int mv[2] = {motion->
x, motion->
y};
60 for (
int i = 0;
i < 2;
i++) {
61 const int s =
mv[
i] >> 17;
63 const int mask = (-1 * (1 <<
f)) >> 1;
64 const int round = (1 <<
f) >> 2;
77 tx = (0x4000 + (
abs(
td) >> 1)) /
td;
80 (scale_factor *
src->x < 0)) >> 8, 17);
82 (scale_factor *
src->y < 0)) >> 8, 17);
89 const RefPicList *refPicList_col,
int listCol,
int refidxCol)
92 int col_lt = refPicList_col[listCol].
isLongTerm[refidxCol];
93 int col_poc_diff, cur_poc_diff;
95 if (cur_lt != col_lt) {
101 col_poc_diff = colPic - refPicList_col[listCol].
list[refidxCol];
102 cur_poc_diff = poc - refPicList[
X].
list[refIdxLx];
105 if (cur_lt || col_poc_diff == cur_poc_diff) {
114 #define CHECK_MVSET(l) \
115 check_mvset(mvLXCol, temp_col.mv + l, \
116 colPic, fc->ps.ph.poc, \
117 refPicList, X, refIdxLx, \
118 refPicList_col, L ## l, temp_col.ref_idx[l])
123 int check_diffpicount = 0;
127 for (j = 0; j < 2; j++) {
135 return !check_diffpicount;
140 int refIdxLx,
Mv *mvLXCol,
int X,
141 int colPic,
const RefPicList *refPicList_col,
int sb_flag)
184 #define TAB_MVF(x, y) \
185 tab_mvf[((y) >> MIN_PU_LOG2) * min_pu_width + ((x) >> MIN_PU_LOG2)]
187 #define TAB_MVF_PU(v) \
188 TAB_MVF(x ## v, y ## v)
190 #define TAB_CP_MV(lx, x, y) \
191 fc->tab.cp_mv[lx][((((y) >> min_cb_log2_size) * min_cb_width + ((x) >> min_cb_log2_size)) ) * MAX_CONTROL_POINTS]
194 #define DERIVE_TEMPORAL_COLOCATED_MVS(sb_flag) \
195 derive_temporal_colocated_mvs(lc, temp_col, \
196 refIdxLx, mvLXCol, X, colPic, \
197 ff_vvc_get_ref_list(fc, ref, x, y), sb_flag)
201 const int refIdxLx,
Mv *mvLXCol,
const int X,
int check_center,
int sb_flag)
208 int x, y, x_end, y_end, colPic, availableFlagLXCol = 0;
209 int min_pu_width =
fc->ps.pps->min_pu_width;
215 memset(mvLXCol, 0,
sizeof(*mvLXCol));
222 tab_mvf =
ref->tab_dmvr_mvf;
229 x_end =
pps->subpic_x[subpic_idx] +
pps->subpic_width[subpic_idx];
230 y_end =
pps->subpic_y[subpic_idx] +
pps->subpic_height[subpic_idx];
233 (cu->
y0 >>
sps->ctb_log2_size_y) == (y >>
sps->ctb_log2_size_y) &&
234 x < x_end && y < y_end) {
242 if (tab_mvf && !availableFlagLXCol) {
251 return availableFlagLXCol;
258 const int min_pu_width =
fc->ps.pps->min_pu_width;
260 for (
int dy = 0; dy <
h; dy += min_pu_size) {
261 for (
int dx = 0; dx <
w; dx += min_pu_size) {
262 const int x = x0 + dx;
263 const int y = y0 + dy;
274 const int min_pu_width =
fc->ps.pps->min_pu_width;
276 for (
int dy = 0; dy < cu->
cb_height; dy += min_pu_size) {
277 for (
int dx = 0; dx < cu->
cb_width; dx += min_pu_size) {
278 const int x = cu->
x0 + dx;
279 const int y = cu->
y0 + dy;
289 const Mv* cp_mv = &
mi->mv[lx][0];
319 const int a = 4 * (2048 +
sp->d_hor_x);
320 const int b = 4 *
sp->d_hor_y;
321 const int c = 4 * (2048 +
sp->d_ver_y);
322 const int d = 4 *
sp->d_ver_x;
323 if (pred_flag ==
PF_BI) {
328 const int bx_wx4 = ((max_w4 - min_w4) >> 11) + 9;
329 const int bx_hx4 = ((max_h4 - min_h4) >> 11) + 9;
330 return bx_wx4 * bx_hx4 > 225;
332 const int bx_wxh = (
FFABS(
a) >> 11) + 9;
333 const int bx_hxh = (
FFABS(
d) >> 11) + 9;
334 const int bx_wxv = (
FFABS(
b) >> 11) + 9;
335 const int bx_hxv = (
FFABS(
c) >> 11) + 9;
336 if (bx_wxh * bx_hxh <= 165 && bx_wxv * bx_hxv <= 165)
343 const int cb_width,
const int cb_height,
const int lx)
345 const int log2_cbw =
av_log2(cb_width);
346 const int log2_cbh =
av_log2(cb_height);
347 const Mv* cp_mv =
mi->mv[lx];
348 const int num_cp_mv =
mi->motion_model_idc + 1;
351 if (num_cp_mv == 3) {
355 sp->d_hor_y = -
sp->d_ver_x;
356 sp->d_ver_y =
sp->d_hor_x;
360 sp->cb_width = cb_width;
361 sp->cb_height = cb_height;
369 const int dmv_limit = 1 << 5;
370 const int pos_offset_x = 6 * (
sp->d_hor_x +
sp->d_hor_y);
371 const int pos_offset_y = 6 * (
sp->d_ver_x +
sp->d_ver_y);
375 diff->x = x * (
sp->d_hor_x * (1 << 2)) + y * (
sp->d_hor_y * (1 << 2)) - pos_offset_x;
376 diff->y = x * (
sp->d_ver_x * (1 << 2)) + y * (
sp->d_ver_y * (1 << 2)) - pos_offset_y;
389 const int log2_min_cb_size =
fc->ps.sps->min_cb_log2_size_y;
390 const int min_cb_size =
fc->ps.sps->min_cb_size_y;
391 const int min_cb_width =
fc->ps.pps->min_cb_width;
392 const int num_cp_mv =
mi->motion_model_idc + 1;
394 for (
int dy = 0; dy < cu->
cb_height; dy += min_cb_size) {
395 for (
int dx = 0; dx < cu->
cb_width; dx += min_cb_size) {
396 const int x_cb = (cu->
x0 + dx) >> log2_min_cb_size;
397 const int y_cb = (cu->
y0 + dy) >> log2_min_cb_size;
400 memcpy(&
fc->tab.cp_mv[lx][
offset],
mi->mv[lx],
sizeof(
Mv) * num_cp_mv);
420 for (
int i = 0;
i < 2;
i++) {
422 if (
mi->pred_flag &
mask) {
430 for (
int sby = 0; sby <
mi->num_sb_y; sby++) {
431 for (
int sbx = 0; sbx <
mi->num_sb_x; sbx++) {
432 const int x0 = cu->
x0 + sbx * sbw;
433 const int y0 = cu->
y0 + sby * sbh;
434 for (
int i = 0;
i < 2;
i++) {
436 if (
mi->pred_flag &
mask) {
442 mv->x =
sp->mv_scale_hor +
sp->d_hor_x * x_pos_cb +
sp->d_hor_y * y_pos_cb;
443 mv->y =
sp->mv_scale_ver +
sp->d_ver_x * x_pos_cb +
sp->d_ver_y * y_pos_cb;
460 const int is_flip = angle_idx >= 13 &&angle_idx <= 27;
461 const int shift_hor = (angle_idx % 16 == 8 || (angle_idx % 16 && cu->
cb_height >= cu->
cb_width)) ? 0 : 1;
462 const int sign = angle_idx < 16 ? 1 : -1;
463 const int block_size = 4;
464 int offset_x = (-cu->
cb_width) >> 1;
468 offset_y += sign * ((distance_idx * cu->
cb_height) >> 3);
470 offset_x += sign * ((distance_idx * cu->
cb_width) >> 3);
472 for (
int y = 0; y < cu->
cb_height; y += block_size) {
473 for (
int x = 0; x < cu->
cb_width; x += block_size) {
474 const int motion_idx = (((x + offset_x) * (1 << 1)) + 5) * displacement_x +
475 (((y + offset_y) * (1 << 1)) + 5) * displacement_y;
476 const int s_type =
FFABS(motion_idx) < 32 ? 2 : (motion_idx <= 0 ? (1 - is_flip) : is_flip);
478 const int x0 = cu->
x0 + x;
479 const int y0 = cu->
y0 + y;
483 else if (s_type == 1 || (s_type == 2 && pred_flag !=
PF_BI))
491 mvf.
mv[lx] = mv1->
mv[lx];
514 for (
int i = 0;
i < 2;
i++) {
554 int cand_bottom_left;
557 cand_bottom_left = 0;
559 const int log2_min_cb_size =
sps->min_cb_log2_size_y;
560 const int min_cb_width =
fc->ps.pps->min_cb_width;
561 const int x = (cu->
x0 - 1) >> log2_min_cb_size;
562 const int y = (cu->
y0 + cu->
cb_height) >> log2_min_cb_size;
563 const int max_y =
FFMIN(
fc->ps.pps->height, ((cu->
y0 >>
sps->ctb_log2_size_y) + 1) <<
sps->ctb_log2_size_y);
565 cand_bottom_left = 0;
567 cand_bottom_left =
SAMPLE_CTB(
fc->tab.cb_width[0], x, y) != 0;
569 return cand_bottom_left;
576 const int x0 = cu->
x0;
577 const int y0 = cu->
y0;
583 { x0 - 1, y0 + cb_height, !a0_available },
584 { x0 - 1, y0 + cb_height - 1, !na->
cand_left },
587 { x0 + cb_width - 1, y0 - 1, !na->
cand_up },
592 memcpy(
ctx->neighbours, neighbours,
sizeof(neighbours));
607 const int min_pu_width =
fc->ps.pps->min_pu_width;
611 n->
available = !
sps->r->sps_entropy_coding_sync_enabled_flag || ((n->
x >>
sps->ctb_log2_size_y) <= (cu->
x0 >>
sps->ctb_log2_size_y));
622 const int min_pu_width =
fc->ps.pps->min_pu_width;
638 #define MV_MERGE_FROM_NB(nb) mv_merge_from_nb(&nctx, nb)
661 cand_list[num_cands] = *cand;
662 if (merge_idx == num_cands)
667 if (num_cands != 4) {
671 cand_list[num_cands] = *cand;
672 if (merge_idx == num_cands)
677 *nb_merge_cand = num_cands;
686 memset(cand, 0,
sizeof(*cand));
691 cand->
pred_flag = available_l0 + (available_l1 << 1);
702 for (
int i = 1;
i <= ep->
num_hmvp && (*num_cands <
sps->max_num_merge_cand - 1);
i++) {
706 cand_list[*num_cands] = *
h;
707 if (merge_idx == *num_cands)
719 const int num_ref_rists = is_b ? 2 : 1;
720 const MvField* p0 = cand_list + 0;
721 const MvField* p1 = cand_list + 1;
722 MvField* cand = cand_list + num_cands;
725 for (
int i = 0;
i < num_ref_rists;
i++) {
756 MvField *cand_list,
int num_cands)
760 const int num_ref_idx =
IS_P(rsh) ?
764 while (num_cands < sps->max_num_merge_cand) {
765 MvField *cand = cand_list + num_cands;
770 cand->
ref_idx[0] = zero_idx < num_ref_idx ? zero_idx : 0;
771 cand->
ref_idx[1] = zero_idx < num_ref_idx ? zero_idx : 0;
774 if (merge_idx == num_cands)
790 if (merge_idx == num_cands)
799 if (merge_idx == num_cands)
815 *
mv = cand_list[merge_idx];
817 mv->ciip_flag = ciip_flag;
826 const int idx[] = { merge_gpm_idx[0], merge_gpm_idx[1] + (merge_gpm_idx[1] >= merge_gpm_idx[0]) };
830 memset(
mv, 0, 2 *
sizeof(*
mv));
831 for (
int i = 0;
i < 2;
i++) {
841 mv[
i].mv[lx] = cand->
mv[lx];
848 const int x_nb,
int y_nb,
const int nbw,
const int nbh,
const int lx,
849 Mv *cps,
int num_cps)
853 const int x0 = cu->
x0;
854 const int y0 = cu->
y0;
858 const int min_cb_log2_size =
fc->ps.sps->min_cb_log2_size_y;
859 const int min_cb_width =
fc->ps.pps->min_cb_width;
861 const int log2_nbw =
ff_log2(nbw);
862 const int log2_nbh =
ff_log2(nbh);
863 const int is_ctb_boundary = !((y_nb + nbh) %
fc->ps.sps->ctb_size_y) && (y_nb + nbh == y0);
865 int mv_scale_hor, mv_scale_ver, d_hor_x, d_ver_x, d_hor_y, d_ver_y, motion_model_idc_nb;
866 if (is_ctb_boundary) {
867 const int min_pu_width =
fc->ps.pps->min_pu_width;
868 l = &
TAB_MVF(x_nb, y_nb + nbh - 1).mv[lx];
869 r = &
TAB_MVF(x_nb + nbw - 1, y_nb + nbh - 1).mv[lx];
871 const int x = x_nb >> min_cb_log2_size;
872 const int y = y_nb >> min_cb_log2_size;
878 mv_scale_hor = l->
x * (1 << 7);
879 mv_scale_ver = l->
y * (1 << 7);
880 d_hor_x = (
r->x - l->
x) * (1 << (7 - log2_nbw));
881 d_ver_x = (
r->y - l->
y) * (1 << (7 - log2_nbw));
883 const Mv* lb = &
TAB_CP_MV(lx, x_nb, y_nb + nbh - 1) + 2;
884 d_hor_y = (lb->
x - l->
x) * (1 << (7 - log2_nbh));
885 d_ver_y = (lb->
y - l->
y) * (1 << (7 - log2_nbh));
891 if (is_ctb_boundary) {
894 cps[0].
x = mv_scale_hor + d_hor_x * (x0 - x_nb) + d_hor_y * (y0 - y_nb);
895 cps[0].
y = mv_scale_ver + d_ver_x * (x0 - x_nb) + d_ver_y * (y0 - y_nb);
896 cps[1].
x = mv_scale_hor + d_hor_x * (x0 + cb_width - x_nb) + d_hor_y * (y0 - y_nb);
897 cps[1].
y = mv_scale_ver + d_ver_x * (x0 + cb_width - x_nb) + d_ver_y * (y0 - y_nb);
899 cps[2].
x = mv_scale_hor + d_hor_x * (x0 - x_nb) + d_hor_y * (y0 + cb_height - y_nb);
900 cps[2].
y = mv_scale_ver + d_ver_x * (x0 - x_nb) + d_ver_y * (y0 + cb_height - y_nb);
902 for (
int i = 0;
i < num_cps;
i++) {
911 const int log2_min_cb_size =
fc->ps.sps->min_cb_log2_size_y;
912 const int min_cb_width =
fc->ps.pps->min_cb_width;
913 const int x = x_nb >> log2_min_cb_size;
914 const int y = y_nb >> log2_min_cb_size;
915 const int motion_model_idc =
SAMPLE_CTB(
fc->tab.mmi, x, y);
916 if (motion_model_idc) {
922 return motion_model_idc;
929 int x, y,
w,
h, motion_model_idc;
932 if (motion_model_idc) {
933 const int min_pu_width =
fc->ps.pps->min_pu_width;
939 for (
int i = 0;
i < 2;
i++) {
941 if (
mi->pred_flag &
mask) {
946 mi->motion_model_idc = motion_model_idc;
948 return motion_model_idc;
954 for (
int i = 0;
i < num_nbs;
i++) {
961 #define AFFINE_MERGE_FROM_NBS(nbs) affine_merge_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), mi)
968 const int min_pu_width =
fc->ps.pps->min_pu_width;
969 for (
int i = 0;
i < num_neighbour;
i++) {
978 #define DERIVE_CORNER_MV(nbs) derive_corner_mvf(nctx, nbs, FF_ARRAY_ELEMS(nbs))
987 if (
A->ref_idx[lx] !=
B->ref_idx[lx])
990 if (!(
C->pred_flag &
mask))
992 if (
A->ref_idx[lx] !=
C->ref_idx[lx])
999 const int x_ctb,
const int y_ctb,
const Mv* temp_mv,
int *x,
int *y)
1003 const int ctb_log2_size =
fc->ps.sps->ctb_log2_size_y;
1005 const int x_end =
pps->subpic_x[subpic_idx] +
pps->subpic_width[subpic_idx];
1006 const int y_end =
pps->subpic_y[subpic_idx] +
pps->subpic_height[subpic_idx];
1008 *x =
av_clip(*x + temp_mv->
x, x_ctb,
FFMIN(x_end - 1, x_ctb + (1 << ctb_log2_size) + 3)) & ~7;
1009 *y =
av_clip(*y + temp_mv->
y, y_ctb,
FFMIN(y_end - 1, y_ctb + (1 << ctb_log2_size) - 1)) & ~7;
1013 const int x_ctb,
const int y_ctb,
const Mv *temp_mv,
1014 int x,
int y, uint8_t *pred_flag,
Mv *
mv)
1018 const int refIdxLx = 0;
1021 const int min_pu_width =
fc->ps.pps->min_pu_width;
1024 int colPic =
ref->poc;
1041 const int x_ctb,
const int y_ctb,
MvField *ctr_mvf,
Mv *temp_mv)
1052 memset(temp_mv, 0,
sizeof(*temp_mv));
1055 memset(ctr_mvf, 0,
sizeof(*ctr_mvf));
1062 if ((
a1->pred_flag &
PF_L0) && colPic == rpl[0].
list[
a1->ref_idx[0]])
1063 *temp_mv =
a1->mv[0];
1064 else if ((
a1->pred_flag &
PF_L1) && colPic == rpl[1].
list[
a1->ref_idx[1]])
1065 *temp_mv =
a1->mv[1];
1082 const int ctb_log2_size =
sps->ctb_log2_size_y;
1083 const int x0 = cu->
x0;
1084 const int y0 = cu->
y0;
1089 const int x_ctb = (x0 >> ctb_log2_size) << ctb_log2_size;
1090 const int y_ctb = (y0 >> ctb_log2_size) << ctb_log2_size;
1093 if (!
ph->r->ph_temporal_mvp_enabled_flag ||
1094 !
sps->r->sps_sbtmvp_enabled_flag ||
1106 for (
int sby = 0; sby <
mi->num_sb_y; sby++) {
1107 for (
int sbx = 0; sbx <
mi->num_sb_x; sbx++) {
1108 int x = x0 + sbx * sbw;
1109 int y = y0 + sby * sbh;
1113 memcpy(mvf.
mv, ctr_mvf.
mv,
sizeof(mvf.
mv));
1125 if (c0 &&
c1 &&
c2) {
1127 for (
int i = 0;
i < 2;
i++) {
1132 mi->mv[
i][0] = c0->
mv[
i];
1133 mi->mv[
i][1] =
c1->mv[
i];
1134 mi->mv[
i][2] =
c2->mv[
i];
1137 if (
mi->pred_flag) {
1149 if (c0 &&
c1 && c3) {
1151 for (
int i = 0;
i < 2;
i++) {
1156 mi->mv[
i][0] = c0->
mv[
i];
1157 mi->mv[
i][1] =
c1->mv[
i];
1163 if (
mi->pred_flag) {
1174 if (c0 &&
c2 && c3) {
1176 for (
int i = 0;
i < 2;
i++) {
1181 mi->mv[
i][0] = c0->
mv[
i];
1185 mi->mv[
i][2] =
c2->mv[
i];
1188 if (
mi->pred_flag) {
1199 if (
c1 &&
c2 && c3) {
1201 for (
int i = 0;
i < 2;
i++) {
1205 mi->ref_idx[
i] =
c1->ref_idx[
i];
1209 mi->mv[
i][1] =
c1->mv[
i];
1210 mi->mv[
i][2] =
c2->mv[
i];
1213 if (
mi->pred_flag) {
1214 mi->bcw_idx =
mi->pred_flag ==
PF_BI ?
c1->bcw_idx : 0;
1226 for (
int i = 0;
i < 2;
i++) {
1231 mi->mv[
i][0] = c0->
mv[
i];
1232 mi->mv[
i][1] =
c1->mv[
i];
1235 if (
mi->pred_flag) {
1250 for (
int i = 0;
i < 2;
i++) {
1255 mi->mv[
i][0] = c0->
mv[
i];
1262 if (
mi->pred_flag) {
1276 memset(
mi, 0,
sizeof(*
mi));
1298 if (
fc->ps.sps->r->sps_6param_affine_enabled_flag) {
1302 if (merge_subblock_idx == num_cands)
1307 memset(&corner3, 0,
sizeof(corner3));
1308 if (
fc->ps.ph.r->ph_temporal_mvp_enabled_flag){
1313 corner3.
pred_flag = available_l0 + (available_l1 << 1);
1320 if (merge_subblock_idx == num_cands)
1327 if (merge_subblock_idx == num_cands)
1334 if (merge_subblock_idx == num_cands)
1342 if (merge_subblock_idx == num_cands)
1348 if (merge_subblock_idx == num_cands)
1368 if (merge_subblock_idx == num_cands)
1377 if (
sps->r->sps_affine_enabled_flag) {
1382 if (merge_subblock_idx == num_cands)
1389 if (merge_subblock_idx == num_cands)
1413 const int lx,
const int8_t *ref_idx,
Mv *
mv)
1417 const int min_pu_width =
fc->ps.pps->min_pu_width;
1421 const int poc = rpl[lx].
list[ref_idx[lx]];
1440 const int x_cand,
const int y_cand,
const int lx,
const int8_t *ref_idx,
1441 Mv *cps,
const int num_cp)
1444 int x_nb, y_nb, nbw, nbh, motion_model_idc,
available = 0;
1447 if (motion_model_idc) {
1448 const int min_pu_width =
fc->ps.pps->min_pu_width;
1453 const int poc = rpl[lx].
list[ref_idx[lx]];
1472 const NeighbourIdx *nbs,
const int num_nbs,
const int lx,
const int8_t *ref_idx,
const int amvr_shift,
1473 Mv *cps,
const int num_cps)
1478 for (
int i = 0;
i < num_nbs;
i++) {
1486 for (
int c = 0;
c < num_cps;
c++)
1496 #define AFFINE_MVP_FROM_NBS(nbs) \
1497 mvp_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), lx, ref_idx, amvr_shift, cps, num_cp) \
1499 #define MVP_FROM_NBS(nbs) \
1500 mvp_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), lx, ref_idx, amvr_shift, mv, 1) \
1503 const int mvp_lx_flag,
const int lx,
const int8_t* ref_idx,
const int amvr_shift,
1504 Mv*
mv,
int *nb_merge_cand)
1509 int available_a, num_cands = 0;
1516 if (mvp_lx_flag == num_cands)
1523 if (mvp_lx_flag == num_cands)
1528 *nb_merge_cand = num_cands;
1533 const int mvp_lx_flag,
const int lx,
const int8_t *ref_idx,
const int amvr_shift,
1534 Mv*
mv,
int *num_cands)
1537 if (mvp_lx_flag == *num_cands) {
1548 const int mvp_lx_flag,
const int lx,
const int8_t ref_idx,
const int amvr_shift,
1549 Mv *
mv,
int num_cands)
1553 const int poc = rpl[lx].
list[ref_idx];
1559 for (
int j = 0; j < 2; j++) {
1560 const int ly = (j ? !lx : lx);
1562 if ((
h->pred_flag &
mask) && poc == rpl[ly].
list[
h->ref_idx[ly]]) {
1563 if (mvp_lx_flag == num_cands) {
1577 const int8_t *ref_idx,
const int amvr_shift,
Mv *
mv)
1590 memset(
mv, 0,
sizeof(*
mv));
1601 mvp(lc, mvp_lx_flag[
L0],
L0,
mi->ref_idx, amvr_shift, &
mi->mv[
L0][0]);
1603 mvp(lc, mvp_lx_flag[
L1],
L1,
mi->ref_idx, amvr_shift, &
mi->mv[
L1][0]);
1610 const int min_pu_width =
fc->ps.pps->min_pu_width;
1628 if (num_cands > merge_idx)
1633 if (!num_cands || !
IS_SAME_MV(&cand_list[0], mvf->
mv)) {
1634 cand_list[num_cands++] = mvf->
mv[
L0];
1635 if (num_cands > merge_idx)
1640 *nb_merge_cand = num_cands;
1645 const int merge_idx,
Mv *cand_list,
int *nb_merge_cand)
1650 int num_cands = *nb_merge_cand;
1653 int same_motion = 0;
1655 for (
int j = 0; j < *nb_merge_cand; j++) {
1656 same_motion = is_gt4by4 &&
i == 1 &&
IS_SAME_MV(&mvf->
mv[
L0], &cand_list[j]);
1661 cand_list[num_cands++] = mvf->
mv[
L0];
1662 if (num_cands > merge_idx)
1667 *nb_merge_cand = num_cands;
1672 #define IBC_SHIFT(v) ((v) >= (1 << (MV_BITS - 1)) ? ((v) - (1 << MV_BITS)) : (v))
1691 *
mv = cand_list[merge_idx];
1696 memset(
mv, 0,
sizeof(*
mv));
1713 const NeighbourIdx *neighbour,
const int num_neighbour,
1714 const int lx,
const int8_t ref_idx,
const int amvr_shift,
Mv *cp)
1719 const int min_pu_width =
fc->ps.pps->min_pu_width;
1723 for (
int i = 0;
i < num_neighbour;
i++) {
1728 const int poc = rpl[lx].
list[ref_idx];
1749 #define AFFINE_MVP_CONSTRUCTED_CP(cands, cp) \
1750 affine_mvp_constructed_cp(nctx, cands, FF_ARRAY_ELEMS(cands), lx, ref_idx, \
1755 const int lx,
const int8_t ref_idx,
const int amvr_shift,
1771 const Mv mv = cps[idx];
1772 for (
int j = 0; j < num_cp; j++)
1778 const int mvp_lx_flag,
const int lx,
const int8_t *ref_idx,
const int amvr_shift,
1783 const int num_cp = motion_model_idc + 1;
1791 if (mvp_lx_flag == num_cands)
1797 if (mvp_lx_flag == num_cands)
1805 if (mvp_lx_flag == num_cands)
1812 for (
int i = 2;
i >= 0;
i--) {
1814 if (mvp_lx_flag == num_cands) {
1822 if (mvp_lx_flag == num_cands) {
1824 for (
int i = 1;
i < num_cp;
i++)
1832 memset(cps, 0, num_cp *
sizeof(
Mv));
1853 const int offset = 1 << (rshift - 1);
1854 mv->x = ((
mv->x +
offset - (
mv->x >= 0)) >> rshift) * (1 << lshift);
1855 mv->y = ((
mv->y +
offset - (
mv->y >= 0)) >> rshift) * (1 << lshift);
1857 mv->x =
mv->x * (1 << lshift);
1858 mv->y =
mv->y * (1 << lshift);
1864 mv->x =
av_clip(
mv->x, -(1 << 17), (1 << 17) - 1);
1865 mv->y =
av_clip(
mv->y, -(1 << 17), (1 << 17) - 1);
1871 const uint8_t plevel =
fc->ps.sps->log2_parallel_merge_level;
1873 return x0_br >> plevel > x0 >> plevel &&
1874 y0_br >> plevel > y0 >> plevel;
1881 for (
i = 0;
i < *num_hmvp;
i++) {
1892 memmove(hmvp +
i, hmvp +
i + 1, (*num_hmvp -
i) *
sizeof(
MvField));
1893 hmvp[(*num_hmvp)++] = *mvf;
1907 const int min_pu_width =
fc->ps.pps->min_pu_width;
1924 const int min_pu_width =
fc->ps.pps->min_pu_width;
static int mv_merge_temporal_candidate(const VVCLocalContext *lc, MvField *cand)
static int affine_mvp_constructed_cp(NeighbourContext *ctx, const NeighbourIdx *neighbour, const int num_neighbour, const int lx, const int8_t ref_idx, const int amvr_shift, Mv *cp)
static av_always_inline int is_greater_mer(const VVCFrameContext *fc, const int x0, const int y0, const int x0_br, const int y0_br)
F H1 F F H1 F F F F H1<-F-------F-------F v v v H2 H3 H2 ^ ^ ^ F-------F-------F-> H1<-F-------F-------F|||||||||F H1 F|||||||||F H1 Funavailable fullpel samples(outside the picture for example) shall be equalto the closest available fullpel sampleSmaller pel interpolation:--------------------------if diag_mc is set then points which lie on a line between 2 vertically, horizontally or diagonally adjacent halfpel points shall be interpolatedlinearly with rounding to nearest and halfway values rounded up.points which lie on 2 diagonals at the same time should only use the onediagonal not containing the fullpel point F--> O q O<--h1-> O q O<--F v \/v \/v O O O O O O O|/|\|q q q q q|/|\|O O O O O O O ^/\ ^/\ ^ h2--> O q O<--h3-> O q O<--h2 v \/v \/v O O O O O O O|\|/|q q q q q|\|/|O O O O O O O ^/\ ^/\ ^ F--> O q O<--h1-> O q O<--Fthe remaining points shall be bilinearly interpolated from theup to 4 surrounding halfpel and fullpel points, again rounding should be tonearest and halfway values rounded upcompliant Snow decoders MUST support 1-1/8 pel luma and 1/2-1/16 pel chromainterpolation at leastOverlapped block motion compensation:-------------------------------------FIXMELL band prediction:===================Each sample in the LL0 subband is predicted by the median of the left, top andleft+top-topleft samples, samples outside the subband shall be considered tobe 0. To reverse this prediction in the decoder apply the following.for(y=0;y< height;y++){ for(x=0;x< width;x++){ sample[y][x]+=median(sample[y-1][x], sample[y][x-1], sample[y-1][x]+sample[y][x-1]-sample[y-1][x-1]);}}sample[-1][ *]=sample[ *][-1]=0;width, height here are the width and height of the LL0 subband not of the finalvideoDequantization:===============FIXMEWavelet Transform:==================Snow supports 2 wavelet transforms, the symmetric biorthogonal 5/3 integertransform and an integer approximation of the symmetric biorthogonal 9/7daubechies wavelet.2D IDWT(inverse discrete wavelet transform) --------------------------------------------The 2D IDWT applies a 2D filter recursively, each time combining the4 lowest frequency subbands into a single subband until only 1 subbandremains.The 2D filter is done by first applying a 1D filter in the vertical directionand then applying it in the horizontal one. --------------- --------------- --------------- ---------------|LL0|HL0|||||||||||||---+---|HL1||L0|H0|HL1||LL1|HL1|||||LH0|HH0|||||||||||||-------+-------|-> L1 H1 LH1 HH1 LH1 HH1 LH1 HH1 L1
static int sb_temporal_merge_candidate(const VVCLocalContext *lc, NeighbourContext *nctx, PredictionUnit *pu)
int ff_vvc_no_backward_pred_flag(const VVCLocalContext *lc)
#define MVP_FROM_NBS(nbs)
static int is_fallback_mode(const SubblockParams *sp, const PredFlag pred_flag)
const int8_t ff_vvc_gpm_distance_lut[VVC_GPM_NUM_ANGLES]
const uint8_t ff_vvc_gpm_distance_idx[VVC_GPM_NUM_PARTITION]
static const int8_t mv[256][2]
#define AFFINE_MVP_CONSTRUCTED_CP(cands, cp)
uint8_t gpm_partition_idx
#define AFFINE_MVP_FROM_NBS(nbs)
void ff_vvc_luma_mv_merge_mode(VVCLocalContext *lc, const int merge_idx, const int ciip_flag, MvField *mv)
static int affine_merge_const5(const MvField *c0, const MvField *c1, MotionInfo *mi)
void ff_vvc_store_mv(const VVCLocalContext *lc, const MotionInfo *mi)
static av_always_inline int is_same_mer(const VVCFrameContext *fc, const int xN, const int yN, const int xP, const int yP)
static int FUNC() ph(CodedBitstreamContext *ctx, RWContext *rw, H266RawPH *current)
#define MAX_NUM_HMVP_CANDS
static void affine_merge_zero_motion(const VVCLocalContext *lc, MotionInfo *mi)
int16_t y
vertical component of motion vector
static void affine_cps_from_nb(const VVCLocalContext *lc, const int x_nb, int y_nb, const int nbw, const int nbh, const int lx, Mv *cps, int num_cps)
const H266RawSliceHeader * r
RefStruct reference.
static int affine_merge_const1(const MvField *c0, const MvField *c1, const MvField *c2, MotionInfo *mi)
static int mvp_history_candidates(const VVCLocalContext *lc, const int mvp_lx_flag, const int lx, const int8_t ref_idx, const int amvr_shift, Mv *mv, int num_cands)
#define fc(width, name, range_min, range_max)
static void derive_subblock_diff_mvs(const VVCLocalContext *lc, PredictionUnit *pu, const SubblockParams *sp, const int lx)
static void affine_mvp(const VVCLocalContext *lc, const int mvp_lx_flag, const int lx, const int8_t *ref_idx, const int amvr_shift, MotionModelIdc motion_model_idc, Mv *cps)
static int mvp_from_nbs(NeighbourContext *ctx, const NeighbourIdx *nbs, const int num_nbs, const int lx, const int8_t *ref_idx, const int amvr_shift, Mv *cps, const int num_cps)
static void FUNC() dmvr(int16_t *dst, const uint8_t *_src, const ptrdiff_t _src_stride, const int height, const intptr_t mx, const intptr_t my, const int width)
void ff_vvc_mvp_ibc(VVCLocalContext *lc, const int mvp_l0_flag, const int amvr_shift, Mv *mv)
void ff_vvc_sb_mv_merge_mode(VVCLocalContext *lc, const int merge_subblock_idx, PredictionUnit *pu)
void ff_vvc_clip_mv(Mv *mv)
static void init_subblock_params(SubblockParams *sp, const MotionInfo *mi, const int cb_width, const int cb_height, const int lx)
static void init_neighbour_context(NeighbourContext *ctx, const VVCLocalContext *lc)
const VVCSPS * sps
RefStruct reference.
static int affine_merge_const6(const MvField *c0, const MvField *c2, const int cb_width, const int cb_height, MotionInfo *mi)
static double b1(void *priv, double x, double y)
void ff_vvc_luma_mv_merge_ibc(VVCLocalContext *lc, const int merge_idx, Mv *mv)
static int is_a0_available(const VVCLocalContext *lc, const CodingUnit *cu)
static const MvField * mv_merge_from_nb(NeighbourContext *ctx, const NeighbourIdx nb)
static int mv_merge_history_candidates(const VVCLocalContext *lc, const int merge_idx, const MvField **nb_list, MvField *cand_list, int *num_cands)
static int affine_merge_const2(const MvField *c0, const MvField *c1, const MvField *c3, MotionInfo *mi)
static int affine_mvp_const1(NeighbourContext *nctx, const int lx, const int8_t ref_idx, const int amvr_shift, Mv *cps, int *available)
MvField * ff_vvc_get_mvf(const VVCFrameContext *fc, const int x0, const int y0)
#define MRG_MAX_NUM_CANDS
static void mv_merge_zero_motion_candidate(const VVCLocalContext *lc, const int merge_idx, MvField *cand_list, int num_cands)
static int derive_temporal_colocated_mvs(const VVCLocalContext *lc, MvField temp_col, int refIdxLx, Mv *mvLXCol, int X, int colPic, const RefPicList *refPicList_col, int sb_flag)
s EdgeDetect Foobar g libavfilter vf_edgedetect c libavfilter vf_foobar c edit libavfilter and add an entry for foobar following the pattern of the other filters edit libavfilter allfilters and add an entry for foobar following the pattern of the other filters configure make j< whatever > ffmpeg ffmpeg i you should get a foobar png with Lena edge detected That s your new playground is ready Some little details about what s going which in turn will define variables for the build system and the C
#define FF_ARRAY_ELEMS(a)
static const uint16_t mask[17]
static int check_mvset(Mv *mvLXCol, Mv *mvCol, int colPic, int poc, const RefPicList *refPicList, int X, int refIdxLx, const RefPicList *refPicList_col, int listCol, int refidxCol)
#define DERIVE_TEMPORAL_COLOCATED_MVS(sb_flag)
static void ibc_merge_candidates(VVCLocalContext *lc, const int merge_idx, Mv *mv)
static const MvField * derive_corner_mvf(NeighbourContext *ctx, const NeighbourIdx *neighbour, const int num_neighbour)
static void affine_mvp_const2(const int idx, Mv *cps, const int num_cp)
static int derive_cb_prof_flag_lx(const VVCLocalContext *lc, const PredictionUnit *pu, int lx, int is_fallback)
void ff_vvc_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift, MotionInfo *mi)
static av_always_inline void sb_clip_location(const VVCLocalContext *lc, const int x_ctb, const int y_ctb, const Mv *temp_mv, int *x, int *y)
void ff_vvc_store_mvf(const VVCLocalContext *lc, const MvField *mvf)
static av_always_inline int compare_pf_ref_idx(const MvField *A, const struct MvField *B, const struct MvField *C, const int lx)
const uint8_t ff_vvc_gpm_angle_idx[VVC_GPM_NUM_PARTITION]
static int mvp_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand, const int lx, const int8_t *ref_idx, Mv *mv)
static int temporal_luma_motion_vector(const VVCLocalContext *lc, const int refIdxLx, Mv *mvLXCol, const int X, int check_center, int sb_flag)
#define LOCAL_ALIGNED_8(t, v,...)
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
static int compare_l0_mv(const MvField *n, const MvField *o)
void ff_vvc_store_gpm_mvf(const VVCLocalContext *lc, const PredictionUnit *pu)
static int ibc_history_candidates(const VVCLocalContext *lc, const int merge_idx, Mv *cand_list, int *nb_merge_cand)
static av_always_inline void mv_compression(Mv *motion)
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining list
static int affine_merge_const4(const MvField *c1, const MvField *c2, const MvField *c3, MotionInfo *mi)
void ff_vvc_update_hmvp(VVCLocalContext *lc, const MotionInfo *mi)
uint8_t ciip_flag
ciip_flag
int16_t x
horizontal component of motion vector
const H266RawPictureHeader * r
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
#define SAMPLE_CTB(tab, x, y)
Neighbour neighbours[NUM_NBS]
int num_hmvp_ibc
NumHmvpIbcCand.
int isLongTerm[HEVC_MAX_REFS]
static int shift(int a, int b)
const VVCLocalContext * lc
static int affine_merge_const_candidates(const VVCLocalContext *lc, MotionInfo *mi, NeighbourContext *nctx, const int merge_subblock_idx, int num_cands)
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)
#define AFFINE_MIN_BLOCK_SIZE
void ff_vvc_round_mv(Mv *mv, const int lshift, const int rshift)
int16_t diff_mv_x[2][AFFINE_MIN_BLOCK_SIZE *AFFINE_MIN_BLOCK_SIZE]
diffMvLX
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
#define MAX_CONTROL_POINTS
static void sb_temproal_luma_motion(const VVCLocalContext *lc, const int x_ctb, const int y_ctb, const Mv *temp_mv, int x, int y, uint8_t *pred_flag, Mv *mv)
static int check_available(Neighbour *n, const VVCLocalContext *lc, const int check_mer)
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
void ff_vvc_store_sb_mvs(const VVCLocalContext *lc, PredictionUnit *pu)
static av_always_inline PredMode pred_flag_to_mode(PredFlag pred)
void ff_vvc_luma_mv_merge_gpm(VVCLocalContext *lc, const int merge_gpm_idx[2], MvField *mv)
uint8_t hpel_if_idx
hpelIfIdx
static void update_hmvp(MvField *hmvp, int *num_hmvp, const MvField *mvf, int(*compare)(const MvField *n, const MvField *o))
static int mvp_temporal_candidates(const VVCLocalContext *lc, const int mvp_lx_flag, const int lx, const int8_t *ref_idx, const int amvr_shift, Mv *mv, int *num_cands)
MvField hmvp[MAX_NUM_HMVP_CANDS]
HmvpCandList.
#define i(width, name, range_min, range_max)
static av_always_inline av_const double round(double x)
static av_always_inline int compare_mv_ref_idx(const MvField *n, const MvField *o)
static int mvp_spatial_candidates(const VVCLocalContext *lc, const int mvp_lx_flag, const int lx, const int8_t *ref_idx, const int amvr_shift, Mv *mv, int *nb_merge_cand)
int32_t poc
PicOrderCntVal.
static int sb_mv_merge_mode(const VVCLocalContext *lc, const int merge_subblock_idx, PredictionUnit *pu)
static int mv_merge_spatial_candidates(const VVCLocalContext *lc, const int merge_idx, const MvField **nb_list, MvField *cand_list, int *nb_merge_cand)
static int affine_merge_from_nbs(NeighbourContext *ctx, const NeighbourIdx *nbs, const int num_nbs, MotionInfo *cand)
static int affine_merge_const3(const MvField *c0, const MvField *c2, const MvField *c3, MotionInfo *mi)
#define TAB_CP_MV(lx, x, y)
static int mv_merge_pairwise_candidate(MvField *cand_list, const int num_cands, const int is_b)
static const float pred[4]
static int FUNC() sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
static void store_cp_mv(const VVCLocalContext *lc, const MotionInfo *mi, const int lx)
uint8_t inter_affine_flag
void ff_vvc_set_neighbour_available(VVCLocalContext *lc, const int x0, const int y0, const int w, const int h)
#define AFFINE_MERGE_FROM_NBS(nbs)
static float compare(const AVFrame *haystack, const AVFrame *obj, int offx, int offy)
void ff_vvc_set_mvf(const VVCLocalContext *lc, const int x0, const int y0, const int w, const int h, const MvField *mvf)
#define DERIVE_CORNER_MV(nbs)
static int sb_temporal_luma_motion_data(const VVCLocalContext *lc, const MvField *a1, const int x_ctb, const int y_ctb, MvField *ctr_mvf, Mv *temp_mv)
enum PredMode pred_mode
PredMode.
static int affine_mvp_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand, const int lx, const int8_t *ref_idx, Mv *cps, const int num_cp)
static int ref[MAX_W *MAX_W]
static void ibc_add_mvp(Mv *mv, Mv *mvp, const int amvr_shift)
int16_t diff_mv_y[2][AFFINE_MIN_BLOCK_SIZE *AFFINE_MIN_BLOCK_SIZE]
diffMvLX
static const MvField * mv_merge_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand)
MvField hmvp_ibc[MAX_NUM_HMVP_CANDS]
HmvpIbcCandList.
int8_t ref_idx[2]
refIdxL0, refIdxL1
static int ibc_spatial_candidates(const VVCLocalContext *lc, const int merge_idx, Mv *const cand_list, int *nb_merge_cand)
void ff_vvc_affine_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift, MotionInfo *mi)
static void mvp(const VVCLocalContext *lc, const int mvp_lx_flag, const int lx, const int8_t *ref_idx, const int amvr_shift, Mv *mv)
static int affine_neighbour_cb(const VVCFrameContext *fc, const int x_nb, const int y_nb, int *x_cb, int *y_cb, int *cbw, int *cbh)
void ff_vvc_set_intra_mvf(const VVCLocalContext *lc, const int dmvr)
static void mv_merge_mode(const VVCLocalContext *lc, const int merge_idx, MvField *cand_list)
#define MV_MERGE_FROM_NB(nb)
static int affine_merge_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand, MotionInfo *mi)
void ff_vvc_mv_scale(Mv *dst, const Mv *src, int td, int tb)