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)
206 int x, y, colPic, availableFlagLXCol = 0;
207 int min_pu_width =
fc->ps.pps->min_pu_width;
213 memset(mvLXCol, 0,
sizeof(*mvLXCol));
220 tab_mvf =
ref->tab_dmvr_mvf;
228 (cu->
y0 >>
sps->ctb_log2_size_y) == (y >>
sps->ctb_log2_size_y) &&
229 y < fc->ps.pps->height &&
230 x < fc->ps.pps->width) {
238 if (tab_mvf && !availableFlagLXCol) {
247 return availableFlagLXCol;
254 const int min_pu_width =
fc->ps.pps->min_pu_width;
256 for (
int dy = 0; dy <
h; dy += min_pu_size) {
257 for (
int dx = 0; dx <
w; dx += min_pu_size) {
258 const int x = x0 + dx;
259 const int y = y0 + dy;
270 const int min_pu_width =
fc->ps.pps->min_pu_width;
272 for (
int dy = 0; dy < cu->
cb_height; dy += min_pu_size) {
273 for (
int dx = 0; dx < cu->
cb_width; dx += min_pu_size) {
274 const int x = cu->
x0 + dx;
275 const int y = cu->
y0 + dy;
285 const Mv* cp_mv = &
mi->mv[lx][0];
315 const int a = 4 * (2048 +
sp->d_hor_x);
316 const int b = 4 *
sp->d_hor_y;
317 const int c = 4 * (2048 +
sp->d_ver_y);
318 const int d = 4 *
sp->d_ver_x;
319 if (pred_flag ==
PF_BI) {
324 const int bx_wx4 = ((max_w4 - min_w4) >> 11) + 9;
325 const int bx_hx4 = ((max_h4 - min_h4) >> 11) + 9;
326 return bx_wx4 * bx_hx4 > 225;
328 const int bx_wxh = (
FFABS(
a) >> 11) + 9;
329 const int bx_hxh = (
FFABS(
d) >> 11) + 9;
330 const int bx_wxv = (
FFABS(
b) >> 11) + 9;
331 const int bx_hxv = (
FFABS(
c) >> 11) + 9;
332 if (bx_wxh * bx_hxh <= 165 && bx_wxv * bx_hxv <= 165)
339 const int cb_width,
const int cb_height,
const int lx)
341 const int log2_cbw =
av_log2(cb_width);
342 const int log2_cbh =
av_log2(cb_height);
343 const Mv* cp_mv =
mi->mv[lx];
344 const int num_cp_mv =
mi->motion_model_idc + 1;
347 if (num_cp_mv == 3) {
351 sp->d_hor_y = -
sp->d_ver_x;
352 sp->d_ver_y =
sp->d_hor_x;
356 sp->cb_width = cb_width;
357 sp->cb_height = cb_height;
365 const int dmv_limit = 1 << 5;
366 const int pos_offset_x = 6 * (
sp->d_hor_x +
sp->d_hor_y);
367 const int pos_offset_y = 6 * (
sp->d_ver_x +
sp->d_ver_y);
371 diff->x = x * (
sp->d_hor_x * (1 << 2)) + y * (
sp->d_hor_y * (1 << 2)) - pos_offset_x;
372 diff->y = x * (
sp->d_ver_x * (1 << 2)) + y * (
sp->d_ver_y * (1 << 2)) - pos_offset_y;
385 const int log2_min_cb_size =
fc->ps.sps->min_cb_log2_size_y;
386 const int min_cb_size =
fc->ps.sps->min_cb_size_y;
387 const int min_cb_width =
fc->ps.pps->min_cb_width;
388 const int num_cp_mv =
mi->motion_model_idc + 1;
390 for (
int dy = 0; dy < cu->
cb_height; dy += min_cb_size) {
391 for (
int dx = 0; dx < cu->
cb_width; dx += min_cb_size) {
392 const int x_cb = (cu->
x0 + dx) >> log2_min_cb_size;
393 const int y_cb = (cu->
y0 + dy) >> log2_min_cb_size;
396 memcpy(&
fc->tab.cp_mv[lx][
offset],
mi->mv[lx],
sizeof(
Mv) * num_cp_mv);
416 for (
int i = 0;
i < 2;
i++) {
418 if (
mi->pred_flag &
mask) {
426 for (
int sby = 0; sby <
mi->num_sb_y; sby++) {
427 for (
int sbx = 0; sbx <
mi->num_sb_x; sbx++) {
428 const int x0 = cu->
x0 + sbx * sbw;
429 const int y0 = cu->
y0 + sby * sbh;
430 for (
int i = 0;
i < 2;
i++) {
432 if (
mi->pred_flag &
mask) {
438 mv->x =
sp->mv_scale_hor +
sp->d_hor_x * x_pos_cb +
sp->d_hor_y * y_pos_cb;
439 mv->y =
sp->mv_scale_ver +
sp->d_ver_x * x_pos_cb +
sp->d_ver_y * y_pos_cb;
456 const int is_flip = angle_idx >= 13 &&angle_idx <= 27;
457 const int shift_hor = (angle_idx % 16 == 8 || (angle_idx % 16 && cu->
cb_height >= cu->
cb_width)) ? 0 : 1;
458 const int sign = angle_idx < 16 ? 1 : -1;
459 const int block_size = 4;
460 int offset_x = (-cu->
cb_width) >> 1;
464 offset_y += sign * ((distance_idx * cu->
cb_height) >> 3);
466 offset_x += sign * ((distance_idx * cu->
cb_width) >> 3);
468 for (
int y = 0; y < cu->
cb_height; y += block_size) {
469 for (
int x = 0; x < cu->
cb_width; x += block_size) {
470 const int motion_idx = (((x + offset_x) * (1 << 1)) + 5) * displacement_x +
471 (((y + offset_y) * (1 << 1)) + 5) * displacement_y;
472 const int s_type =
FFABS(motion_idx) < 32 ? 2 : (motion_idx <= 0 ? (1 - is_flip) : is_flip);
474 const int x0 = cu->
x0 + x;
475 const int y0 = cu->
y0 + y;
479 else if (s_type == 1 || (s_type == 2 && pred_flag !=
PF_BI))
487 mvf.
mv[lx] = mv1->
mv[lx];
510 for (
int i = 0;
i < 2;
i++) {
550 int cand_bottom_left;
553 cand_bottom_left = 0;
555 const int log2_min_cb_size =
sps->min_cb_log2_size_y;
556 const int min_cb_width =
fc->ps.pps->min_cb_width;
557 const int x = (cu->
x0 - 1) >> log2_min_cb_size;
558 const int y = (cu->
y0 + cu->
cb_height) >> log2_min_cb_size;
559 const int max_y =
FFMIN(
fc->ps.pps->height, ((cu->
y0 >>
sps->ctb_log2_size_y) + 1) <<
sps->ctb_log2_size_y);
561 cand_bottom_left = 0;
563 cand_bottom_left =
SAMPLE_CTB(
fc->tab.cb_width[0], x, y) != 0;
565 return cand_bottom_left;
572 const int x0 = cu->
x0;
573 const int y0 = cu->
y0;
579 { x0 - 1, y0 + cb_height, !a0_available },
580 { x0 - 1, y0 + cb_height - 1, !na->
cand_left },
583 { x0 + cb_width - 1, y0 - 1, !na->
cand_up },
588 memcpy(
ctx->neighbours, neighbours,
sizeof(neighbours));
603 const int min_pu_width =
fc->ps.pps->min_pu_width;
607 n->
available = !
sps->r->sps_entropy_coding_sync_enabled_flag || ((n->
x >>
sps->ctb_log2_size_y) <= (cu->
x0 >>
sps->ctb_log2_size_y));
618 const int min_pu_width =
fc->ps.pps->min_pu_width;
634 #define MV_MERGE_FROM_NB(nb) mv_merge_from_nb(&nctx, nb)
657 cand_list[num_cands] = *cand;
658 if (merge_idx == num_cands)
663 if (num_cands != 4) {
667 cand_list[num_cands] = *cand;
668 if (merge_idx == num_cands)
673 *nb_merge_cand = num_cands;
682 memset(cand, 0,
sizeof(*cand));
687 cand->
pred_flag = available_l0 + (available_l1 << 1);
698 for (
int i = 1;
i <= ep->
num_hmvp && (*num_cands <
sps->max_num_merge_cand - 1);
i++) {
702 cand_list[*num_cands] = *
h;
703 if (merge_idx == *num_cands)
715 const int num_ref_rists = is_b ? 2 : 1;
716 const MvField* p0 = cand_list + 0;
717 const MvField* p1 = cand_list + 1;
718 MvField* cand = cand_list + num_cands;
721 for (
int i = 0;
i < num_ref_rists;
i++) {
752 MvField *cand_list,
int num_cands)
756 const int num_ref_idx =
IS_P(rsh) ?
760 while (num_cands < sps->max_num_merge_cand) {
761 MvField *cand = cand_list + num_cands;
766 cand->
ref_idx[0] = zero_idx < num_ref_idx ? zero_idx : 0;
767 cand->
ref_idx[1] = zero_idx < num_ref_idx ? zero_idx : 0;
770 if (merge_idx == num_cands)
786 if (merge_idx == num_cands)
795 if (merge_idx == num_cands)
811 *
mv = cand_list[merge_idx];
813 mv->ciip_flag = ciip_flag;
822 const int idx[] = { merge_gpm_idx[0], merge_gpm_idx[1] + (merge_gpm_idx[1] >= merge_gpm_idx[0]) };
826 memset(
mv, 0, 2 *
sizeof(*
mv));
827 for (
int i = 0;
i < 2;
i++) {
837 mv[
i].mv[lx] = cand->
mv[lx];
844 const int x_nb,
int y_nb,
const int nbw,
const int nbh,
const int lx,
845 Mv *cps,
int num_cps)
849 const int x0 = cu->
x0;
850 const int y0 = cu->
y0;
854 const int min_cb_log2_size =
fc->ps.sps->min_cb_log2_size_y;
855 const int min_cb_width =
fc->ps.pps->min_cb_width;
857 const int log2_nbw =
ff_log2(nbw);
858 const int log2_nbh =
ff_log2(nbh);
859 const int is_ctb_boundary = !((y_nb + nbh) %
fc->ps.sps->ctb_size_y) && (y_nb + nbh == y0);
861 int mv_scale_hor, mv_scale_ver, d_hor_x, d_ver_x, d_hor_y, d_ver_y, motion_model_idc_nb;
862 if (is_ctb_boundary) {
863 const int min_pu_width =
fc->ps.pps->min_pu_width;
864 l = &
TAB_MVF(x_nb, y_nb + nbh - 1).mv[lx];
865 r = &
TAB_MVF(x_nb + nbw - 1, y_nb + nbh - 1).mv[lx];
867 const int x = x_nb >> min_cb_log2_size;
868 const int y = y_nb >> min_cb_log2_size;
874 mv_scale_hor = l->
x * (1 << 7);
875 mv_scale_ver = l->
y * (1 << 7);
876 d_hor_x = (
r->x - l->
x) * (1 << (7 - log2_nbw));
877 d_ver_x = (
r->y - l->
y) * (1 << (7 - log2_nbw));
879 const Mv* lb = &
TAB_CP_MV(lx, x_nb, y_nb + nbh - 1) + 2;
880 d_hor_y = (lb->
x - l->
x) * (1 << (7 - log2_nbh));
881 d_ver_y = (lb->
y - l->
y) * (1 << (7 - log2_nbh));
887 if (is_ctb_boundary) {
890 cps[0].
x = mv_scale_hor + d_hor_x * (x0 - x_nb) + d_hor_y * (y0 - y_nb);
891 cps[0].
y = mv_scale_ver + d_ver_x * (x0 - x_nb) + d_ver_y * (y0 - y_nb);
892 cps[1].
x = mv_scale_hor + d_hor_x * (x0 + cb_width - x_nb) + d_hor_y * (y0 - y_nb);
893 cps[1].
y = mv_scale_ver + d_ver_x * (x0 + cb_width - x_nb) + d_ver_y * (y0 - y_nb);
895 cps[2].
x = mv_scale_hor + d_hor_x * (x0 - x_nb) + d_hor_y * (y0 + cb_height - y_nb);
896 cps[2].
y = mv_scale_ver + d_ver_x * (x0 - x_nb) + d_ver_y * (y0 + cb_height - y_nb);
898 for (
int i = 0;
i < num_cps;
i++) {
907 const int log2_min_cb_size =
fc->ps.sps->min_cb_log2_size_y;
908 const int min_cb_width =
fc->ps.pps->min_cb_width;
909 const int x = x_nb >> log2_min_cb_size;
910 const int y = y_nb >> log2_min_cb_size;
911 const int motion_model_idc =
SAMPLE_CTB(
fc->tab.mmi, x, y);
912 if (motion_model_idc) {
918 return motion_model_idc;
925 int x, y,
w,
h, motion_model_idc;
928 if (motion_model_idc) {
929 const int min_pu_width =
fc->ps.pps->min_pu_width;
935 for (
int i = 0;
i < 2;
i++) {
937 if (
mi->pred_flag &
mask) {
942 mi->motion_model_idc = motion_model_idc;
944 return motion_model_idc;
950 for (
int i = 0;
i < num_nbs;
i++) {
957 #define AFFINE_MERGE_FROM_NBS(nbs) affine_merge_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), mi)
964 const int min_pu_width =
fc->ps.pps->min_pu_width;
965 for (
int i = 0;
i < num_neighbour;
i++) {
974 #define DERIVE_CORNER_MV(nbs) derive_corner_mvf(nctx, nbs, FF_ARRAY_ELEMS(nbs))
983 if (
A->ref_idx[lx] !=
B->ref_idx[lx])
986 if (!(
C->pred_flag &
mask))
988 if (
A->ref_idx[lx] !=
C->ref_idx[lx])
995 const int x_ctb,
const int y_ctb,
const Mv* temp_mv,
int *x,
int *y)
998 const int ctb_log2_size =
fc->ps.sps->ctb_log2_size_y;
999 *y =
av_clip(*y + temp_mv->
y, y_ctb,
FFMIN(
pps->height - 1, y_ctb + (1 << ctb_log2_size) - 1)) & ~7;
1000 *x =
av_clip(*x + temp_mv->
x, x_ctb,
FFMIN(
pps->width - 1, x_ctb + (1 << ctb_log2_size) + 3)) & ~7;
1004 const int x_ctb,
const int y_ctb,
const Mv *temp_mv,
1005 int x,
int y, uint8_t *pred_flag,
Mv *
mv)
1009 const int refIdxLx = 0;
1012 const int min_pu_width =
fc->ps.pps->min_pu_width;
1015 int colPic =
ref->poc;
1032 const int x_ctb,
const int y_ctb,
MvField *ctr_mvf,
Mv *temp_mv)
1043 memset(temp_mv, 0,
sizeof(*temp_mv));
1046 memset(ctr_mvf, 0,
sizeof(*ctr_mvf));
1053 if ((
a1->pred_flag &
PF_L0) && colPic == rpl[0].
list[
a1->ref_idx[0]])
1054 *temp_mv =
a1->mv[0];
1055 else if ((
a1->pred_flag &
PF_L1) && colPic == rpl[1].
list[
a1->ref_idx[1]])
1056 *temp_mv =
a1->mv[1];
1073 const int ctb_log2_size =
sps->ctb_log2_size_y;
1074 const int x0 = cu->
x0;
1075 const int y0 = cu->
y0;
1080 const int x_ctb = (x0 >> ctb_log2_size) << ctb_log2_size;
1081 const int y_ctb = (y0 >> ctb_log2_size) << ctb_log2_size;
1084 if (!
ph->r->ph_temporal_mvp_enabled_flag ||
1085 !
sps->r->sps_sbtmvp_enabled_flag ||
1097 for (
int sby = 0; sby <
mi->num_sb_y; sby++) {
1098 for (
int sbx = 0; sbx <
mi->num_sb_x; sbx++) {
1099 int x = x0 + sbx * sbw;
1100 int y = y0 + sby * sbh;
1104 memcpy(mvf.
mv, ctr_mvf.
mv,
sizeof(mvf.
mv));
1116 if (c0 &&
c1 &&
c2) {
1118 for (
int i = 0;
i < 2;
i++) {
1123 mi->mv[
i][0] = c0->
mv[
i];
1124 mi->mv[
i][1] =
c1->mv[
i];
1125 mi->mv[
i][2] =
c2->mv[
i];
1128 if (
mi->pred_flag) {
1140 if (c0 &&
c1 && c3) {
1142 for (
int i = 0;
i < 2;
i++) {
1147 mi->mv[
i][0] = c0->
mv[
i];
1148 mi->mv[
i][1] =
c1->mv[
i];
1154 if (
mi->pred_flag) {
1165 if (c0 &&
c2 && c3) {
1167 for (
int i = 0;
i < 2;
i++) {
1172 mi->mv[
i][0] = c0->
mv[
i];
1176 mi->mv[
i][2] =
c2->mv[
i];
1179 if (
mi->pred_flag) {
1190 if (
c1 &&
c2 && c3) {
1192 for (
int i = 0;
i < 2;
i++) {
1196 mi->ref_idx[
i] =
c1->ref_idx[
i];
1200 mi->mv[
i][1] =
c1->mv[
i];
1201 mi->mv[
i][2] =
c2->mv[
i];
1204 if (
mi->pred_flag) {
1205 mi->bcw_idx =
mi->pred_flag ==
PF_BI ?
c1->bcw_idx : 0;
1217 for (
int i = 0;
i < 2;
i++) {
1222 mi->mv[
i][0] = c0->
mv[
i];
1223 mi->mv[
i][1] =
c1->mv[
i];
1226 if (
mi->pred_flag) {
1241 for (
int i = 0;
i < 2;
i++) {
1246 mi->mv[
i][0] = c0->
mv[
i];
1253 if (
mi->pred_flag) {
1267 memset(
mi, 0,
sizeof(*
mi));
1289 if (
fc->ps.sps->r->sps_6param_affine_enabled_flag) {
1293 if (merge_subblock_idx == num_cands)
1298 memset(&corner3, 0,
sizeof(corner3));
1299 if (
fc->ps.ph.r->ph_temporal_mvp_enabled_flag){
1304 corner3.
pred_flag = available_l0 + (available_l1 << 1);
1311 if (merge_subblock_idx == num_cands)
1318 if (merge_subblock_idx == num_cands)
1325 if (merge_subblock_idx == num_cands)
1333 if (merge_subblock_idx == num_cands)
1339 if (merge_subblock_idx == num_cands)
1359 if (merge_subblock_idx == num_cands)
1368 if (
sps->r->sps_affine_enabled_flag) {
1373 if (merge_subblock_idx == num_cands)
1380 if (merge_subblock_idx == num_cands)
1404 const int lx,
const int8_t *ref_idx,
Mv *
mv)
1408 const int min_pu_width =
fc->ps.pps->min_pu_width;
1412 const int poc = rpl[lx].
list[ref_idx[lx]];
1431 const int x_cand,
const int y_cand,
const int lx,
const int8_t *ref_idx,
1432 Mv *cps,
const int num_cp)
1435 int x_nb, y_nb, nbw, nbh, motion_model_idc,
available = 0;
1438 if (motion_model_idc) {
1439 const int min_pu_width =
fc->ps.pps->min_pu_width;
1444 const int poc = rpl[lx].
list[ref_idx[lx]];
1463 const NeighbourIdx *nbs,
const int num_nbs,
const int lx,
const int8_t *ref_idx,
const int amvr_shift,
1464 Mv *cps,
const int num_cps)
1469 for (
int i = 0;
i < num_nbs;
i++) {
1477 for (
int c = 0;
c < num_cps;
c++)
1487 #define AFFINE_MVP_FROM_NBS(nbs) \
1488 mvp_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), lx, ref_idx, amvr_shift, cps, num_cp) \
1490 #define MVP_FROM_NBS(nbs) \
1491 mvp_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), lx, ref_idx, amvr_shift, mv, 1) \
1494 const int mvp_lx_flag,
const int lx,
const int8_t* ref_idx,
const int amvr_shift,
1495 Mv*
mv,
int *nb_merge_cand)
1500 int available_a, num_cands = 0;
1507 if (mvp_lx_flag == num_cands)
1514 if (mvp_lx_flag == num_cands)
1519 *nb_merge_cand = num_cands;
1524 const int mvp_lx_flag,
const int lx,
const int8_t *ref_idx,
const int amvr_shift,
1525 Mv*
mv,
int *num_cands)
1528 if (mvp_lx_flag == *num_cands) {
1539 const int mvp_lx_flag,
const int lx,
const int8_t ref_idx,
const int amvr_shift,
1540 Mv *
mv,
int num_cands)
1544 const int poc = rpl[lx].
list[ref_idx];
1550 for (
int j = 0; j < 2; j++) {
1551 const int ly = (j ? !lx : lx);
1553 if ((
h->pred_flag &
mask) && poc == rpl[ly].
list[
h->ref_idx[ly]]) {
1554 if (mvp_lx_flag == num_cands) {
1568 const int8_t *ref_idx,
const int amvr_shift,
Mv *
mv)
1581 memset(
mv, 0,
sizeof(*
mv));
1592 mvp(lc, mvp_lx_flag[
L0],
L0,
mi->ref_idx, amvr_shift, &
mi->mv[
L0][0]);
1594 mvp(lc, mvp_lx_flag[
L1],
L1,
mi->ref_idx, amvr_shift, &
mi->mv[
L1][0]);
1601 const int min_pu_width =
fc->ps.pps->min_pu_width;
1619 if (num_cands > merge_idx)
1624 if (!num_cands || !
IS_SAME_MV(&cand_list[0], mvf->
mv)) {
1625 cand_list[num_cands++] = mvf->
mv[
L0];
1626 if (num_cands > merge_idx)
1631 *nb_merge_cand = num_cands;
1636 const int merge_idx,
Mv *cand_list,
int *nb_merge_cand)
1641 int num_cands = *nb_merge_cand;
1644 int same_motion = 0;
1646 for (
int j = 0; j < *nb_merge_cand; j++) {
1647 same_motion = is_gt4by4 &&
i == 1 &&
IS_SAME_MV(&mvf->
mv[
L0], &cand_list[j]);
1652 cand_list[num_cands++] = mvf->
mv[
L0];
1653 if (num_cands > merge_idx)
1658 *nb_merge_cand = num_cands;
1663 #define IBC_SHIFT(v) ((v) >= (1 << (MV_BITS - 1)) ? ((v) - (1 << MV_BITS)) : (v))
1682 *
mv = cand_list[merge_idx];
1687 memset(
mv, 0,
sizeof(*
mv));
1704 const NeighbourIdx *neighbour,
const int num_neighbour,
1705 const int lx,
const int8_t ref_idx,
const int amvr_shift,
Mv *cp)
1710 const int min_pu_width =
fc->ps.pps->min_pu_width;
1714 for (
int i = 0;
i < num_neighbour;
i++) {
1719 const int poc = rpl[lx].
list[ref_idx];
1740 #define AFFINE_MVP_CONSTRUCTED_CP(cands, cp) \
1741 affine_mvp_constructed_cp(nctx, cands, FF_ARRAY_ELEMS(cands), lx, ref_idx, \
1746 const int lx,
const int8_t ref_idx,
const int amvr_shift,
1762 const Mv mv = cps[idx];
1763 for (
int j = 0; j < num_cp; j++)
1769 const int mvp_lx_flag,
const int lx,
const int8_t *ref_idx,
const int amvr_shift,
1774 const int num_cp = motion_model_idc + 1;
1782 if (mvp_lx_flag == num_cands)
1788 if (mvp_lx_flag == num_cands)
1796 if (mvp_lx_flag == num_cands)
1803 for (
int i = 2;
i >= 0;
i--) {
1805 if (mvp_lx_flag == num_cands) {
1813 if (mvp_lx_flag == num_cands) {
1815 for (
int i = 1;
i < num_cp;
i++)
1823 memset(cps, 0, num_cp *
sizeof(
Mv));
1844 const int offset = 1 << (rshift - 1);
1845 mv->x = ((
mv->x +
offset - (
mv->x >= 0)) >> rshift) * (1 << lshift);
1846 mv->y = ((
mv->y +
offset - (
mv->y >= 0)) >> rshift) * (1 << lshift);
1848 mv->x =
mv->x * (1 << lshift);
1849 mv->y =
mv->y * (1 << lshift);
1855 mv->x =
av_clip(
mv->x, -(1 << 17), (1 << 17) - 1);
1856 mv->y =
av_clip(
mv->y, -(1 << 17), (1 << 17) - 1);
1862 const uint8_t plevel =
fc->ps.sps->log2_parallel_merge_level;
1864 return x0_br >> plevel > x0 >> plevel &&
1865 y0_br >> plevel > y0 >> plevel;
1872 for (
i = 0;
i < *num_hmvp;
i++) {
1883 memmove(hmvp +
i, hmvp +
i + 1, (*num_hmvp -
i) *
sizeof(
MvField));
1884 hmvp[(*num_hmvp)++] = *mvf;
1898 const int min_pu_width =
fc->ps.pps->min_pu_width;
1915 const int min_pu_width =
fc->ps.pps->min_pu_width;
static const MvField * mv_merge_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand)
static int sb_mv_merge_mode(const VVCLocalContext *lc, const int merge_subblock_idx, PredictionUnit *pu)
static void affine_mvp_const2(const int idx, Mv *cps, const int num_cp)
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 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)
static int mv_merge_temporal_candidate(const VVCLocalContext *lc, MvField *cand)
static void init_neighbour_context(NeighbourContext *ctx, const VVCLocalContext *lc)
static void mv_merge_zero_motion_candidate(const VVCLocalContext *lc, const int merge_idx, MvField *cand_list, int num_cands)
static int check_available(Neighbour *n, const VVCLocalContext *lc, const int check_mer)
MvField * ff_vvc_get_mvf(const VVCFrameContext *fc, const int x0, const int y0)
static const int8_t mv[256][2]
void ff_vvc_sb_mv_merge_mode(VVCLocalContext *lc, const int merge_subblock_idx, PredictionUnit *pu)
static int affine_merge_const6(const MvField *c0, const MvField *c2, const int cb_width, const int cb_height, MotionInfo *mi)
uint8_t gpm_partition_idx
static int FUNC() ph(CodedBitstreamContext *ctx, RWContext *rw, H266RawPH *current)
static int affine_merge_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand, MotionInfo *mi)
static void ibc_merge_candidates(VVCLocalContext *lc, const int merge_idx, Mv *mv)
const uint8_t ff_vvc_gpm_angle_idx[VVC_GPM_NUM_PARTITION]
static int affine_merge_from_nbs(NeighbourContext *ctx, const NeighbourIdx *nbs, const int num_nbs, MotionInfo *cand)
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 const MvField * derive_corner_mvf(NeighbourContext *ctx, const NeighbourIdx *neighbour, const int num_neighbour)
int16_t y
vertical component of motion vector
void ff_vvc_luma_mv_merge_mode(VVCLocalContext *lc, const int merge_idx, const int ciip_flag, MvField *mv)
const H266RawSliceHeader * r
RefStruct reference.
static av_always_inline void sb_clip_location(const VVCFrameContext *fc, const int x_ctb, const int y_ctb, const Mv *temp_mv, int *x, int *y)
void ff_vvc_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift, MotionInfo *mi)
#define fc(width, name, range_min, range_max)
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)
#define AFFINE_MVP_CONSTRUCTED_CP(cands, cp)
static int mv_merge_pairwise_candidate(MvField *cand_list, const int num_cands, const int is_b)
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)
static av_always_inline int is_same_mer(const VVCFrameContext *fc, const int xN, const int yN, const int xP, const int yP)
void ff_vvc_store_gpm_mvf(const VVCLocalContext *lc, const PredictionUnit *pu)
static void ibc_add_mvp(Mv *mv, Mv *mvp, const int amvr_shift)
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)
const VVCSPS * sps
RefStruct reference.
static double b1(void *priv, double x, double y)
static int is_a0_available(const VVCLocalContext *lc, const CodingUnit *cu)
#define AFFINE_MERGE_FROM_NBS(nbs)
static int ibc_spatial_candidates(const VVCLocalContext *lc, const int merge_idx, Mv *const cand_list, int *nb_merge_cand)
#define MRG_MAX_NUM_CANDS
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
void ff_vvc_luma_mv_merge_gpm(VVCLocalContext *lc, const int merge_gpm_idx[2], MvField *mv)
#define FF_ARRAY_ELEMS(a)
static const uint16_t mask[17]
static int affine_merge_const3(const MvField *c0, const MvField *c2, const MvField *c3, MotionInfo *mi)
void ff_vvc_store_mv(const VVCLocalContext *lc, const MotionInfo *mi)
void ff_vvc_mv_scale(Mv *dst, const Mv *src, int td, int tb)
static int affine_merge_const4(const MvField *c1, const MvField *c2, const MvField *c3, MotionInfo *mi)
#define MAX_NUM_HMVP_CANDS
static int compare_l0_mv(const MvField *n, const MvField *o)
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)
#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 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)
#define MAX_CONTROL_POINTS
int ff_vvc_no_backward_pred_flag(const VVCLocalContext *lc)
static void mv_merge_mode(const VVCLocalContext *lc, const int merge_idx, MvField *cand_list)
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)
static int is_fallback_mode(const SubblockParams *sp, const PredFlag pred_flag)
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
#define DERIVE_CORNER_MV(nbs)
void ff_vvc_set_intra_mvf(const VVCLocalContext *lc, const int dmvr)
static void update_hmvp(MvField *hmvp, int *num_hmvp, const MvField *mvf, int(*compare)(const MvField *n, const MvField *o))
uint8_t ciip_flag
ciip_flag
#define MV_MERGE_FROM_NB(nb)
int16_t x
horizontal component of motion vector
const H266RawPictureHeader * r
static av_always_inline void mv_compression(Mv *motion)
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)
void ff_vvc_luma_mv_merge_ibc(VVCLocalContext *lc, const int merge_idx, Mv *mv)
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)
Neighbour neighbours[NUM_NBS]
int num_hmvp_ibc
NumHmvpIbcCand.
static int FUNC() pps(CodedBitstreamContext *ctx, RWContext *rw, H264RawPPS *current)
int isLongTerm[HEVC_MAX_REFS]
static int shift(int a, int b)
const VVCLocalContext * lc
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)
#define AFFINE_MIN_BLOCK_SIZE
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)
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
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
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 const MvField * mv_merge_from_nb(NeighbourContext *ctx, const NeighbourIdx nb)
uint8_t hpel_if_idx
hpelIfIdx
void ff_vvc_mvp_ibc(VVCLocalContext *lc, const int mvp_l0_flag, const int amvr_shift, Mv *mv)
static int affine_merge_const1(const MvField *c0, const MvField *c1, const MvField *c2, MotionInfo *mi)
void ff_vvc_set_mvf(const VVCLocalContext *lc, const int x0, const int y0, const int w, const int h, const MvField *mvf)
static int affine_merge_const_candidates(const VVCLocalContext *lc, MotionInfo *mi, NeighbourContext *nctx, const int merge_subblock_idx, int num_cands)
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 sb_temporal_merge_candidate(const VVCLocalContext *lc, NeighbourContext *nctx, PredictionUnit *pu)
#define DERIVE_TEMPORAL_COLOCATED_MVS(sb_flag)
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)
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)
void ff_vvc_store_sb_mvs(const VVCLocalContext *lc, PredictionUnit *pu)
static av_always_inline int compare_mv_ref_idx(const MvField *n, const MvField *o)
static av_always_inline PredMode pred_flag_to_mode(PredFlag pred)
int32_t poc
PicOrderCntVal.
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_update_hmvp(VVCLocalContext *lc, const MotionInfo *mi)
void ff_vvc_set_neighbour_available(VVCLocalContext *lc, const int x0, const int y0, const int w, const int h)
#define TAB_CP_MV(lx, x, y)
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_affine_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift, MotionInfo *mi)
void ff_vvc_clip_mv(Mv *mv)
static const float pred[4]
static int FUNC() sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
uint8_t inter_affine_flag
static void init_subblock_params(SubblockParams *sp, const MotionInfo *mi, const int cb_width, const int cb_height, const int lx)
static float compare(const AVFrame *haystack, const AVFrame *obj, int offx, int offy)
static int derive_cb_prof_flag_lx(const VVCLocalContext *lc, const PredictionUnit *pu, int lx, int is_fallback)
void ff_vvc_round_mv(Mv *mv, const int lshift, const int rshift)
enum PredMode pred_mode
PredMode.
static int affine_merge_const2(const MvField *c0, const MvField *c1, const MvField *c3, MotionInfo *mi)
static int ref[MAX_W *MAX_W]
static void affine_merge_zero_motion(const VVCLocalContext *lc, MotionInfo *mi)
#define AFFINE_MVP_FROM_NBS(nbs)
const int8_t ff_vvc_gpm_distance_lut[VVC_GPM_NUM_ANGLES]
int16_t diff_mv_y[2][AFFINE_MIN_BLOCK_SIZE *AFFINE_MIN_BLOCK_SIZE]
diffMvLX
MvField hmvp_ibc[MAX_NUM_HMVP_CANDS]
HmvpIbcCandList.
int8_t ref_idx[2]
refIdxL0, refIdxL1
static void derive_subblock_diff_mvs(const VVCLocalContext *lc, PredictionUnit *pu, const SubblockParams *sp, const int lx)
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 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)
static int mv_merge_history_candidates(const VVCLocalContext *lc, const int merge_idx, const MvField **nb_list, MvField *cand_list, int *num_cands)
static av_always_inline int compare_pf_ref_idx(const MvField *A, const struct MvField *B, const struct MvField *C, const int lx)
static void store_cp_mv(const VVCLocalContext *lc, const MotionInfo *mi, const int lx)
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)
static int temporal_luma_motion_vector(const VVCLocalContext *lc, const int refIdxLx, Mv *mvLXCol, const int X, int check_center, int sb_flag)
const uint8_t ff_vvc_gpm_distance_idx[VVC_GPM_NUM_PARTITION]
void ff_vvc_store_mvf(const VVCLocalContext *lc, const MvField *mvf)
static int ibc_history_candidates(const VVCLocalContext *lc, const int merge_idx, Mv *cand_list, int *nb_merge_cand)
static int affine_mvp_const1(NeighbourContext *nctx, const int lx, const int8_t ref_idx, const int amvr_shift, Mv *cps, int *available)
static int affine_merge_const5(const MvField *c0, const MvField *c1, MotionInfo *mi)
#define MVP_FROM_NBS(nbs)