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);
415 for (
int i = 0;
i < 2;
i++) {
417 if (
mi->pred_flag &
mask) {
425 for (
int sby = 0; sby <
mi->num_sb_y; sby++) {
426 for (
int sbx = 0; sbx <
mi->num_sb_x; sbx++) {
427 const int x0 = cu->
x0 + sbx * sbw;
428 const int y0 = cu->
y0 + sby * sbh;
429 for (
int i = 0;
i < 2;
i++) {
431 if (
mi->pred_flag &
mask) {
437 mv->x =
sp->mv_scale_hor +
sp->d_hor_x * x_pos_cb +
sp->d_hor_y * y_pos_cb;
438 mv->y =
sp->mv_scale_ver +
sp->d_ver_x * x_pos_cb +
sp->d_ver_y * y_pos_cb;
455 const int is_flip = angle_idx >= 13 &&angle_idx <= 27;
456 const int shift_hor = (angle_idx % 16 == 8 || (angle_idx % 16 && cu->
cb_height >= cu->
cb_width)) ? 0 : 1;
457 const int sign = angle_idx < 16 ? 1 : -1;
458 const int block_size = 4;
459 int offset_x = (-cu->
cb_width) >> 1;
463 offset_y += sign * ((distance_idx * cu->
cb_height) >> 3);
465 offset_x += sign * ((distance_idx * cu->
cb_width) >> 3);
467 for (
int y = 0; y < cu->
cb_height; y += block_size) {
468 for (
int x = 0; x < cu->
cb_width; x += block_size) {
469 const int motion_idx = (((x + offset_x) * (1 << 1)) + 5) * displacement_x +
470 (((y + offset_y) * (1 << 1)) + 5) * displacement_y;
471 const int s_type =
FFABS(motion_idx) < 32 ? 2 : (motion_idx <= 0 ? (1 - is_flip) : is_flip);
473 const int x0 = cu->
x0 + x;
474 const int y0 = cu->
y0 + y;
478 else if (s_type == 1 || (s_type == 2 && pred_flag !=
PF_BI))
486 mvf.
mv[lx] = mv1->
mv[lx];
508 for (
int i = 0;
i < 2;
i++) {
548 int cand_bottom_left;
551 cand_bottom_left = 0;
553 const int log2_min_cb_size =
sps->min_cb_log2_size_y;
554 const int min_cb_width =
fc->ps.pps->min_cb_width;
555 const int x = (cu->
x0 - 1) >> log2_min_cb_size;
556 const int y = (cu->
y0 + cu->
cb_height) >> log2_min_cb_size;
557 const int max_y =
FFMIN(
fc->ps.pps->height, ((cu->
y0 >>
sps->ctb_log2_size_y) + 1) <<
sps->ctb_log2_size_y);
559 cand_bottom_left = 0;
561 cand_bottom_left =
SAMPLE_CTB(
fc->tab.cb_width[0], x, y) != 0;
563 return cand_bottom_left;
570 const int x0 = cu->
x0;
571 const int y0 = cu->
y0;
577 { x0 - 1, y0 + cb_height, !a0_available },
578 { x0 - 1, y0 + cb_height - 1, !na->
cand_left },
581 { x0 + cb_width - 1, y0 - 1, !na->
cand_up },
586 memcpy(
ctx->neighbours, neighbours,
sizeof(neighbours));
601 const int min_pu_width =
fc->ps.pps->min_pu_width;
605 n->
available = !
sps->r->sps_entropy_coding_sync_enabled_flag || ((n->
x >>
sps->ctb_log2_size_y) <= (cu->
x0 >>
sps->ctb_log2_size_y));
616 const int min_pu_width =
fc->ps.pps->min_pu_width;
632 #define MV_MERGE_FROM_NB(nb) mv_merge_from_nb(&nctx, nb)
655 cand_list[num_cands] = *cand;
656 if (merge_idx == num_cands)
661 if (num_cands != 4) {
665 cand_list[num_cands] = *cand;
666 if (merge_idx == num_cands)
671 *nb_merge_cand = num_cands;
680 memset(cand, 0,
sizeof(*cand));
685 cand->
pred_flag = available_l0 + (available_l1 << 1);
696 for (
int i = 1;
i <= ep->
num_hmvp && (*num_cands <
sps->max_num_merge_cand - 1);
i++) {
700 cand_list[*num_cands] = *
h;
701 if (merge_idx == *num_cands)
713 const int num_ref_rists = is_b ? 2 : 1;
714 const MvField* p0 = cand_list + 0;
715 const MvField* p1 = cand_list + 1;
716 MvField* cand = cand_list + num_cands;
719 for (
int i = 0;
i < num_ref_rists;
i++) {
750 MvField *cand_list,
int num_cands)
754 const int num_ref_idx =
IS_P(rsh) ?
758 while (num_cands < sps->max_num_merge_cand) {
759 MvField *cand = cand_list + num_cands;
764 cand->
ref_idx[0] = zero_idx < num_ref_idx ? zero_idx : 0;
765 cand->
ref_idx[1] = zero_idx < num_ref_idx ? zero_idx : 0;
768 if (merge_idx == num_cands)
784 if (merge_idx == num_cands)
793 if (merge_idx == num_cands)
809 *
mv = cand_list[merge_idx];
811 mv->ciip_flag = ciip_flag;
820 const int idx[] = { merge_gpm_idx[0], merge_gpm_idx[1] + (merge_gpm_idx[1] >= merge_gpm_idx[0]) };
824 memset(
mv, 0, 2 *
sizeof(*
mv));
825 for (
int i = 0;
i < 2;
i++) {
835 mv[
i].mv[lx] = cand->
mv[lx];
842 const int x_nb,
int y_nb,
const int nbw,
const int nbh,
const int lx,
843 Mv *cps,
int num_cps)
847 const int x0 = cu->
x0;
848 const int y0 = cu->
y0;
852 const int min_cb_log2_size =
fc->ps.sps->min_cb_log2_size_y;
853 const int min_cb_width =
fc->ps.pps->min_cb_width;
855 const int log2_nbw =
ff_log2(nbw);
856 const int log2_nbh =
ff_log2(nbh);
857 const int is_ctb_boundary = !((y_nb + nbh) %
fc->ps.sps->ctb_size_y) && (y_nb + nbh == y0);
859 int mv_scale_hor, mv_scale_ver, d_hor_x, d_ver_x, d_hor_y, d_ver_y, motion_model_idc_nb;
860 if (is_ctb_boundary) {
861 const int min_pu_width =
fc->ps.pps->min_pu_width;
862 l = &
TAB_MVF(x_nb, y_nb + nbh - 1).mv[lx];
863 r = &
TAB_MVF(x_nb + nbw - 1, y_nb + nbh - 1).mv[lx];
865 const int x = x_nb >> min_cb_log2_size;
866 const int y = y_nb >> min_cb_log2_size;
872 mv_scale_hor = l->
x * (1 << 7);
873 mv_scale_ver = l->
y * (1 << 7);
874 d_hor_x = (
r->x - l->
x) * (1 << (7 - log2_nbw));
875 d_ver_x = (
r->y - l->
y) * (1 << (7 - log2_nbw));
877 const Mv* lb = &
TAB_CP_MV(lx, x_nb, y_nb + nbh - 1) + 2;
878 d_hor_y = (lb->
x - l->
x) * (1 << (7 - log2_nbh));
879 d_ver_y = (lb->
y - l->
y) * (1 << (7 - log2_nbh));
885 if (is_ctb_boundary) {
888 cps[0].
x = mv_scale_hor + d_hor_x * (x0 - x_nb) + d_hor_y * (y0 - y_nb);
889 cps[0].
y = mv_scale_ver + d_ver_x * (x0 - x_nb) + d_ver_y * (y0 - y_nb);
890 cps[1].
x = mv_scale_hor + d_hor_x * (x0 + cb_width - x_nb) + d_hor_y * (y0 - y_nb);
891 cps[1].
y = mv_scale_ver + d_ver_x * (x0 + cb_width - x_nb) + d_ver_y * (y0 - y_nb);
893 cps[2].
x = mv_scale_hor + d_hor_x * (x0 - x_nb) + d_hor_y * (y0 + cb_height - y_nb);
894 cps[2].
y = mv_scale_ver + d_ver_x * (x0 - x_nb) + d_ver_y * (y0 + cb_height - y_nb);
896 for (
int i = 0;
i < num_cps;
i++) {
905 const int log2_min_cb_size =
fc->ps.sps->min_cb_log2_size_y;
906 const int min_cb_width =
fc->ps.pps->min_cb_width;
907 const int x = x_nb >> log2_min_cb_size;
908 const int y = y_nb >> log2_min_cb_size;
909 const int motion_model_idc =
SAMPLE_CTB(
fc->tab.mmi, x, y);
910 if (motion_model_idc) {
916 return motion_model_idc;
923 int x, y,
w,
h, motion_model_idc;
926 if (motion_model_idc) {
927 const int min_pu_width =
fc->ps.pps->min_pu_width;
933 for (
int i = 0;
i < 2;
i++) {
935 if (
mi->pred_flag &
mask) {
940 mi->motion_model_idc = motion_model_idc;
942 return motion_model_idc;
948 for (
int i = 0;
i < num_nbs;
i++) {
955 #define AFFINE_MERGE_FROM_NBS(nbs) affine_merge_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), mi)
962 const int min_pu_width =
fc->ps.pps->min_pu_width;
963 for (
int i = 0;
i < num_neighbour;
i++) {
972 #define DERIVE_CORNER_MV(nbs) derive_corner_mvf(nctx, nbs, FF_ARRAY_ELEMS(nbs))
981 if (
A->ref_idx[lx] !=
B->ref_idx[lx])
984 if (!(
C->pred_flag &
mask))
986 if (
A->ref_idx[lx] !=
C->ref_idx[lx])
993 const int x_ctb,
const int y_ctb,
const Mv* temp_mv,
int *x,
int *y)
996 const int ctb_log2_size =
fc->ps.sps->ctb_log2_size_y;
997 *y =
av_clip(*y + temp_mv->
y, y_ctb,
FFMIN(
pps->height - 1, y_ctb + (1 << ctb_log2_size) - 1)) & ~7;
998 *x =
av_clip(*x + temp_mv->
x, x_ctb,
FFMIN(
pps->width - 1, x_ctb + (1 << ctb_log2_size) + 3)) & ~7;
1002 const int x_ctb,
const int y_ctb,
const Mv *temp_mv,
1003 int x,
int y, uint8_t *pred_flag,
Mv *
mv)
1007 const int refIdxLx = 0;
1010 const int min_pu_width =
fc->ps.pps->min_pu_width;
1013 int colPic =
ref->poc;
1030 const int x_ctb,
const int y_ctb,
MvField *ctr_mvf,
Mv *temp_mv)
1041 memset(temp_mv, 0,
sizeof(*temp_mv));
1044 memset(ctr_mvf, 0,
sizeof(*ctr_mvf));
1051 if ((
a1->pred_flag &
PF_L0) && colPic == rpl[0].
list[
a1->ref_idx[0]])
1052 *temp_mv =
a1->mv[0];
1053 else if ((
a1->pred_flag &
PF_L1) && colPic == rpl[1].
list[
a1->ref_idx[1]])
1054 *temp_mv =
a1->mv[1];
1071 const int ctb_log2_size =
sps->ctb_log2_size_y;
1072 const int x0 = cu->
x0;
1073 const int y0 = cu->
y0;
1078 const int x_ctb = (x0 >> ctb_log2_size) << ctb_log2_size;
1079 const int y_ctb = (y0 >> ctb_log2_size) << ctb_log2_size;
1082 if (!
ph->r->ph_temporal_mvp_enabled_flag ||
1083 !
sps->r->sps_sbtmvp_enabled_flag ||
1095 for (
int sby = 0; sby <
mi->num_sb_y; sby++) {
1096 for (
int sbx = 0; sbx <
mi->num_sb_x; sbx++) {
1097 int x = x0 + sbx * sbw;
1098 int y = y0 + sby * sbh;
1102 memcpy(mvf.
mv, ctr_mvf.
mv,
sizeof(mvf.
mv));
1114 if (c0 &&
c1 &&
c2) {
1116 for (
int i = 0;
i < 2;
i++) {
1121 mi->mv[
i][0] = c0->
mv[
i];
1122 mi->mv[
i][1] =
c1->mv[
i];
1123 mi->mv[
i][2] =
c2->mv[
i];
1126 if (
mi->pred_flag) {
1138 if (c0 &&
c1 && c3) {
1140 for (
int i = 0;
i < 2;
i++) {
1145 mi->mv[
i][0] = c0->
mv[
i];
1146 mi->mv[
i][1] =
c1->mv[
i];
1152 if (
mi->pred_flag) {
1163 if (c0 &&
c2 && c3) {
1165 for (
int i = 0;
i < 2;
i++) {
1170 mi->mv[
i][0] = c0->
mv[
i];
1174 mi->mv[
i][2] =
c2->mv[
i];
1177 if (
mi->pred_flag) {
1188 if (
c1 &&
c2 && c3) {
1190 for (
int i = 0;
i < 2;
i++) {
1194 mi->ref_idx[
i] =
c1->ref_idx[
i];
1198 mi->mv[
i][1] =
c1->mv[
i];
1199 mi->mv[
i][2] =
c2->mv[
i];
1202 if (
mi->pred_flag) {
1203 mi->bcw_idx =
mi->pred_flag ==
PF_BI ?
c1->bcw_idx : 0;
1215 for (
int i = 0;
i < 2;
i++) {
1220 mi->mv[
i][0] = c0->
mv[
i];
1221 mi->mv[
i][1] =
c1->mv[
i];
1224 if (
mi->pred_flag) {
1239 for (
int i = 0;
i < 2;
i++) {
1244 mi->mv[
i][0] = c0->
mv[
i];
1251 if (
mi->pred_flag) {
1265 memset(
mi, 0,
sizeof(*
mi));
1287 if (
fc->ps.sps->r->sps_6param_affine_enabled_flag) {
1291 if (merge_subblock_idx == num_cands)
1296 memset(&corner3, 0,
sizeof(corner3));
1297 if (
fc->ps.ph.r->ph_temporal_mvp_enabled_flag){
1302 corner3.
pred_flag = available_l0 + (available_l1 << 1);
1309 if (merge_subblock_idx == num_cands)
1316 if (merge_subblock_idx == num_cands)
1323 if (merge_subblock_idx == num_cands)
1331 if (merge_subblock_idx == num_cands)
1337 if (merge_subblock_idx == num_cands)
1357 if (merge_subblock_idx == num_cands)
1366 if (
sps->r->sps_affine_enabled_flag) {
1371 if (merge_subblock_idx == num_cands)
1378 if (merge_subblock_idx == num_cands)
1402 const int lx,
const int8_t *ref_idx,
Mv *
mv)
1406 const int min_pu_width =
fc->ps.pps->min_pu_width;
1410 const int poc = rpl[lx].
list[ref_idx[lx]];
1429 const int x_cand,
const int y_cand,
const int lx,
const int8_t *ref_idx,
1430 Mv *cps,
const int num_cp)
1433 int x_nb, y_nb, nbw, nbh, motion_model_idc,
available = 0;
1436 if (motion_model_idc) {
1437 const int min_pu_width =
fc->ps.pps->min_pu_width;
1442 const int poc = rpl[lx].
list[ref_idx[lx]];
1461 const NeighbourIdx *nbs,
const int num_nbs,
const int lx,
const int8_t *ref_idx,
const int amvr_shift,
1462 Mv *cps,
const int num_cps)
1467 for (
int i = 0;
i < num_nbs;
i++) {
1475 for (
int c = 0;
c < num_cps;
c++)
1485 #define AFFINE_MVP_FROM_NBS(nbs) \
1486 mvp_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), lx, ref_idx, amvr_shift, cps, num_cp) \
1488 #define MVP_FROM_NBS(nbs) \
1489 mvp_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), lx, ref_idx, amvr_shift, mv, 1) \
1492 const int mvp_lx_flag,
const int lx,
const int8_t* ref_idx,
const int amvr_shift,
1493 Mv*
mv,
int *nb_merge_cand)
1498 int available_a, num_cands = 0;
1505 if (mvp_lx_flag == num_cands)
1512 if (mvp_lx_flag == num_cands)
1517 *nb_merge_cand = num_cands;
1522 const int mvp_lx_flag,
const int lx,
const int8_t *ref_idx,
const int amvr_shift,
1523 Mv*
mv,
int *num_cands)
1526 if (mvp_lx_flag == *num_cands) {
1537 const int mvp_lx_flag,
const int lx,
const int8_t ref_idx,
const int amvr_shift,
1538 Mv *
mv,
int num_cands)
1542 const int poc = rpl[lx].
list[ref_idx];
1548 for (
int j = 0; j < 2; j++) {
1549 const int ly = (j ? !lx : lx);
1551 if ((
h->pred_flag &
mask) && poc == rpl[ly].
list[
h->ref_idx[ly]]) {
1552 if (mvp_lx_flag == num_cands) {
1566 const int8_t *ref_idx,
const int amvr_shift,
Mv *
mv)
1579 memset(
mv, 0,
sizeof(*
mv));
1590 mvp(lc, mvp_lx_flag[
L0],
L0,
mi->ref_idx, amvr_shift, &
mi->mv[
L0][0]);
1592 mvp(lc, mvp_lx_flag[
L1],
L1,
mi->ref_idx, amvr_shift, &
mi->mv[
L1][0]);
1599 const int min_pu_width =
fc->ps.pps->min_pu_width;
1617 if (num_cands > merge_idx)
1622 if (!num_cands || !
IS_SAME_MV(&cand_list[0], mvf->
mv)) {
1623 cand_list[num_cands++] = mvf->
mv[
L0];
1624 if (num_cands > merge_idx)
1629 *nb_merge_cand = num_cands;
1634 const int merge_idx,
Mv *cand_list,
int *nb_merge_cand)
1639 int num_cands = *nb_merge_cand;
1642 int same_motion = 0;
1644 for (
int j = 0; j < *nb_merge_cand; j++) {
1645 same_motion = is_gt4by4 &&
i == 1 &&
IS_SAME_MV(&mvf->
mv[
L0], &cand_list[j]);
1650 cand_list[num_cands++] = mvf->
mv[
L0];
1651 if (num_cands > merge_idx)
1656 *nb_merge_cand = num_cands;
1661 #define IBC_SHIFT(v) ((v) >= (1 << (MV_BITS - 1)) ? ((v) - (1 << MV_BITS)) : (v))
1680 *
mv = cand_list[merge_idx];
1685 memset(
mv, 0,
sizeof(*
mv));
1702 const NeighbourIdx *neighbour,
const int num_neighbour,
1703 const int lx,
const int8_t ref_idx,
const int amvr_shift,
Mv *cp)
1708 const int min_pu_width =
fc->ps.pps->min_pu_width;
1712 for (
int i = 0;
i < num_neighbour;
i++) {
1717 const int poc = rpl[lx].
list[ref_idx];
1738 #define AFFINE_MVP_CONSTRUCTED_CP(cands, cp) \
1739 affine_mvp_constructed_cp(nctx, cands, FF_ARRAY_ELEMS(cands), lx, ref_idx, \
1744 const int lx,
const int8_t ref_idx,
const int amvr_shift,
1760 const Mv mv = cps[idx];
1761 for (
int j = 0; j < num_cp; j++)
1767 const int mvp_lx_flag,
const int lx,
const int8_t *ref_idx,
const int amvr_shift,
1772 const int num_cp = motion_model_idc + 1;
1780 if (mvp_lx_flag == num_cands)
1786 if (mvp_lx_flag == num_cands)
1794 if (mvp_lx_flag == num_cands)
1801 for (
int i = 2;
i >= 0;
i--) {
1803 if (mvp_lx_flag == num_cands) {
1811 if (mvp_lx_flag == num_cands) {
1813 for (
int i = 1;
i < num_cp;
i++)
1821 memset(cps, 0, num_cp *
sizeof(
Mv));
1842 const int offset = 1 << (rshift - 1);
1843 mv->x = ((
mv->x +
offset - (
mv->x >= 0)) >> rshift) * (1 << lshift);
1844 mv->y = ((
mv->y +
offset - (
mv->y >= 0)) >> rshift) * (1 << lshift);
1846 mv->x =
mv->x * (1 << lshift);
1847 mv->y =
mv->y * (1 << lshift);
1853 mv->x =
av_clip(
mv->x, -(1 << 17), (1 << 17) - 1);
1854 mv->y =
av_clip(
mv->y, -(1 << 17), (1 << 17) - 1);
1860 const uint8_t plevel =
fc->ps.sps->log2_parallel_merge_level;
1862 return x0_br >> plevel > x0 >> plevel &&
1863 y0_br >> plevel > y0 >> plevel;
1870 for (
i = 0;
i < *num_hmvp;
i++) {
1881 memmove(hmvp +
i, hmvp +
i + 1, (*num_hmvp -
i) *
sizeof(
MvField));
1882 hmvp[(*num_hmvp)++] = *mvf;
1896 const int min_pu_width =
fc->ps.pps->min_pu_width;
1913 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)