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)
91 int cur_lt = refPicList[
X].
refs[refIdxLx].
is_lt;
92 int col_lt = refPicList_col[listCol].
refs[refidxCol].
is_lt;
93 int col_poc_diff, cur_poc_diff;
95 if (cur_lt != col_lt) {
101 col_poc_diff = colPic - refPicList_col[listCol].
refs[refidxCol].
poc;
102 cur_poc_diff = poc - refPicList[
X].
refs[refIdxLx].
poc;
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];
320 const int a = 4 * (2048 + sp->
d_hor_x);
322 const int c = 4 * (2048 + sp->
d_ver_y);
324 if (pred_flag ==
PF_BI) {
329 const int bx_wx4 = ((max_w4 - min_w4) >> 11) + 9;
330 const int bx_hx4 = ((max_h4 - min_h4) >> 11) + 9;
331 return bx_wx4 * bx_hx4 > 225;
333 const int bx_wxh = (
FFABS(
a) >> 11) + 9;
334 const int bx_hxh = (
FFABS(d) >> 11) + 9;
335 const int bx_wxv = (
FFABS(
b) >> 11) + 9;
336 const int bx_hxv = (
FFABS(
c) >> 11) + 9;
337 if (bx_wxh * bx_hxh <= 165 && bx_wxv * bx_hxv <= 165)
344 const int cb_width,
const int cb_height,
const int lx)
346 const int log2_cbw =
av_log2(cb_width);
347 const int log2_cbh =
av_log2(cb_height);
348 const Mv* cp_mv =
mi->mv[lx];
349 const int num_cp_mv =
mi->motion_model_idc + 1;
352 if (num_cp_mv == 3) {
370 const int dmv_limit = 1 << 5;
390 const int log2_min_cb_size =
fc->ps.sps->min_cb_log2_size_y;
391 const int min_cb_size =
fc->ps.sps->min_cb_size_y;
392 const int min_cb_width =
fc->ps.pps->min_cb_width;
393 const int num_cp_mv =
mi->motion_model_idc + 1;
395 for (
int dy = 0; dy < cu->
cb_height; dy += min_cb_size) {
396 for (
int dx = 0; dx < cu->
cb_width; dx += min_cb_size) {
397 const int x_cb = (cu->
x0 + dx) >> log2_min_cb_size;
398 const int y_cb = (cu->
y0 + dy) >> log2_min_cb_size;
401 memcpy(&
fc->tab.cp_mv[lx][
offset],
mi->mv[lx],
sizeof(
Mv) * num_cp_mv);
419 for (
int i = 0;
i < 2;
i++) {
421 if (
mi->pred_flag &
mask) {
429 for (
int sby = 0; sby <
mi->num_sb_y; sby++) {
430 for (
int sbx = 0; sbx <
mi->num_sb_x; sbx++) {
431 const int x0 = cu->
x0 + sbx * sbw;
432 const int y0 = cu->
y0 + sby * sbh;
433 for (
int i = 0;
i < 2;
i++) {
435 if (
mi->pred_flag &
mask) {
459 const int is_flip = angle_idx >= 13 &&angle_idx <= 27;
460 const int shift_hor = (angle_idx % 16 == 8 || (angle_idx % 16 && cu->
cb_height >= cu->
cb_width)) ? 0 : 1;
461 const int sign = angle_idx < 16 ? 1 : -1;
462 const int block_size = 4;
463 int offset_x = (-cu->
cb_width) >> 1;
467 offset_y += sign * ((distance_idx * cu->
cb_height) >> 3);
469 offset_x += sign * ((distance_idx * cu->
cb_width) >> 3);
471 for (
int y = 0; y < cu->
cb_height; y += block_size) {
472 for (
int x = 0; x < cu->
cb_width; x += block_size) {
473 const int motion_idx = (((x + offset_x) * (1 << 1)) + 5) * displacement_x +
474 (((y + offset_y) * (1 << 1)) + 5) * displacement_y;
475 const int s_type =
FFABS(motion_idx) < 32 ? 2 : (motion_idx <= 0 ? (1 - is_flip) : is_flip);
477 const int x0 = cu->
x0 + x;
478 const int y0 = cu->
y0 + y;
482 else if (s_type == 1 || (s_type == 2 && pred_flag !=
PF_BI))
490 mvf.
mv[lx] = mv1->
mv[lx];
512 for (
int i = 0;
i < 2;
i++) {
550 const int x = x0 >>
sps->min_cb_log2_size_y;
551 const int y = y0 >>
sps->min_cb_log2_size_y;
552 const int min_cb_width =
fc->ps.pps->min_cb_width;
562 int cand_bottom_left;
565 cand_bottom_left = 0;
567 const int max_y =
FFMIN(
fc->ps.pps->height, ((cu->
y0 >>
sps->ctb_log2_size_y) + 1) <<
sps->ctb_log2_size_y);
569 cand_bottom_left = 0;
573 return cand_bottom_left;
580 const int x0 = cu->
x0;
581 const int y0 = cu->
y0;
587 { x0 - 1, y0 + cb_height, !a0_available },
588 { x0 - 1, y0 + cb_height - 1, !na->
cand_left },
591 { x0 + cb_width - 1, y0 - 1, !na->
cand_up },
596 memcpy(
ctx->neighbours, neighbours,
sizeof(neighbours));
611 const int min_pu_width =
fc->ps.pps->min_pu_width;
615 n->
available = !
sps->r->sps_entropy_coding_sync_enabled_flag || ((n->
x >>
sps->ctb_log2_size_y) <= (cu->
x0 >>
sps->ctb_log2_size_y));
626 const int min_pu_width =
fc->ps.pps->min_pu_width;
642 #define MV_MERGE_FROM_NB(nb) mv_merge_from_nb(&nctx, nb)
665 cand_list[num_cands] = *cand;
666 if (merge_idx == num_cands)
671 if (num_cands != 4) {
675 cand_list[num_cands] = *cand;
676 if (merge_idx == num_cands)
681 *nb_merge_cand = num_cands;
690 memset(cand, 0,
sizeof(*cand));
695 cand->
pred_flag = available_l0 + (available_l1 << 1);
706 for (
int i = 1;
i <= ep->
num_hmvp && (*num_cands <
sps->max_num_merge_cand - 1);
i++) {
710 cand_list[*num_cands] = *
h;
711 if (merge_idx == *num_cands)
723 const int num_ref_rists = is_b ? 2 : 1;
724 const MvField* p0 = cand_list + 0;
725 const MvField* p1 = cand_list + 1;
726 MvField* cand = cand_list + num_cands;
729 for (
int i = 0;
i < num_ref_rists;
i++) {
760 MvField *cand_list,
int num_cands)
764 const int num_ref_idx =
IS_P(rsh) ?
768 while (num_cands < sps->max_num_merge_cand) {
769 MvField *cand = cand_list + num_cands;
774 cand->
ref_idx[0] = zero_idx < num_ref_idx ? zero_idx : 0;
775 cand->
ref_idx[1] = zero_idx < num_ref_idx ? zero_idx : 0;
778 if (merge_idx == num_cands)
794 if (merge_idx == num_cands)
803 if (merge_idx == num_cands)
819 *
mv = cand_list[merge_idx];
821 mv->ciip_flag = ciip_flag;
830 const int idx[] = { merge_gpm_idx[0], merge_gpm_idx[1] + (merge_gpm_idx[1] >= merge_gpm_idx[0]) };
834 memset(
mv, 0, 2 *
sizeof(*
mv));
835 for (
int i = 0;
i < 2;
i++) {
845 mv[
i].mv[lx] = cand->
mv[lx];
852 const int x_nb,
int y_nb,
const int nbw,
const int nbh,
const int lx,
853 Mv *cps,
int num_cps)
857 const int x0 = cu->
x0;
858 const int y0 = cu->
y0;
862 const int min_cb_log2_size =
fc->ps.sps->min_cb_log2_size_y;
863 const int min_cb_width =
fc->ps.pps->min_cb_width;
865 const int log2_nbw =
ff_log2(nbw);
866 const int log2_nbh =
ff_log2(nbh);
867 const int is_ctb_boundary = !((y_nb + nbh) %
fc->ps.sps->ctb_size_y) && (y_nb + nbh == y0);
869 int mv_scale_hor, mv_scale_ver, d_hor_x, d_ver_x, d_hor_y, d_ver_y, motion_model_idc_nb;
870 if (is_ctb_boundary) {
871 const int min_pu_width =
fc->ps.pps->min_pu_width;
872 l = &
TAB_MVF(x_nb, y_nb + nbh - 1).mv[lx];
873 r = &
TAB_MVF(x_nb + nbw - 1, y_nb + nbh - 1).mv[lx];
875 const int x = x_nb >> min_cb_log2_size;
876 const int y = y_nb >> min_cb_log2_size;
882 mv_scale_hor = l->
x * (1 << 7);
883 mv_scale_ver = l->
y * (1 << 7);
884 d_hor_x = (
r->x - l->
x) * (1 << (7 - log2_nbw));
885 d_ver_x = (
r->y - l->
y) * (1 << (7 - log2_nbw));
887 const Mv* lb = &
TAB_CP_MV(lx, x_nb, y_nb + nbh - 1) + 2;
888 d_hor_y = (lb->
x - l->
x) * (1 << (7 - log2_nbh));
889 d_ver_y = (lb->
y - l->
y) * (1 << (7 - log2_nbh));
895 if (is_ctb_boundary) {
898 cps[0].
x = mv_scale_hor + d_hor_x * (x0 - x_nb) + d_hor_y * (y0 - y_nb);
899 cps[0].
y = mv_scale_ver + d_ver_x * (x0 - x_nb) + d_ver_y * (y0 - y_nb);
900 cps[1].
x = mv_scale_hor + d_hor_x * (x0 + cb_width - x_nb) + d_hor_y * (y0 - y_nb);
901 cps[1].
y = mv_scale_ver + d_ver_x * (x0 + cb_width - x_nb) + d_ver_y * (y0 - y_nb);
903 cps[2].
x = mv_scale_hor + d_hor_x * (x0 - x_nb) + d_hor_y * (y0 + cb_height - y_nb);
904 cps[2].
y = mv_scale_ver + d_ver_x * (x0 - x_nb) + d_ver_y * (y0 + cb_height - y_nb);
906 for (
int i = 0;
i < num_cps;
i++) {
915 const int log2_min_cb_size =
fc->ps.sps->min_cb_log2_size_y;
916 const int min_cb_width =
fc->ps.pps->min_cb_width;
917 const int x = x_nb >> log2_min_cb_size;
918 const int y = y_nb >> log2_min_cb_size;
919 const int motion_model_idc =
SAMPLE_CTB(
fc->tab.mmi, x, y);
920 if (motion_model_idc) {
926 return motion_model_idc;
933 int x, y,
w,
h, motion_model_idc;
936 if (motion_model_idc) {
937 const int min_pu_width =
fc->ps.pps->min_pu_width;
943 for (
int i = 0;
i < 2;
i++) {
945 if (
mi->pred_flag &
mask) {
950 mi->motion_model_idc = motion_model_idc;
952 return motion_model_idc;
958 for (
int i = 0;
i < num_nbs;
i++) {
965 #define AFFINE_MERGE_FROM_NBS(nbs) affine_merge_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), mi)
972 const int min_pu_width =
fc->ps.pps->min_pu_width;
973 for (
int i = 0;
i < num_neighbour;
i++) {
982 #define DERIVE_CORNER_MV(nbs) derive_corner_mvf(nctx, nbs, FF_ARRAY_ELEMS(nbs))
991 if (
A->ref_idx[lx] !=
B->ref_idx[lx])
994 if (!(
C->pred_flag &
mask))
996 if (
A->ref_idx[lx] !=
C->ref_idx[lx])
1003 const int x_ctb,
const int y_ctb,
const Mv* temp_mv,
int *x,
int *y)
1007 const int ctb_log2_size =
fc->ps.sps->ctb_log2_size_y;
1009 const int x_end =
pps->subpic_x[subpic_idx] +
pps->subpic_width[subpic_idx];
1010 const int y_end =
pps->subpic_y[subpic_idx] +
pps->subpic_height[subpic_idx];
1012 *x =
av_clip(*x + temp_mv->
x, x_ctb,
FFMIN(x_end - 1, x_ctb + (1 << ctb_log2_size) + 3)) & ~7;
1013 *y =
av_clip(*y + temp_mv->
y, y_ctb,
FFMIN(y_end - 1, y_ctb + (1 << ctb_log2_size) - 1)) & ~7;
1017 const int x_ctb,
const int y_ctb,
const Mv *temp_mv,
1018 int x,
int y, uint8_t *pred_flag,
Mv *
mv)
1022 const int refIdxLx = 0;
1025 const int min_pu_width =
fc->ps.pps->min_pu_width;
1028 int colPic =
ref->poc;
1045 const int x_ctb,
const int y_ctb,
MvField *ctr_mvf,
Mv *temp_mv)
1056 memset(temp_mv, 0,
sizeof(*temp_mv));
1059 memset(ctr_mvf, 0,
sizeof(*ctr_mvf));
1067 *temp_mv =
a1->mv[0];
1069 *temp_mv =
a1->mv[1];
1086 const int ctb_log2_size =
sps->ctb_log2_size_y;
1087 const int x0 = cu->
x0;
1088 const int y0 = cu->
y0;
1093 const int x_ctb = (x0 >> ctb_log2_size) << ctb_log2_size;
1094 const int y_ctb = (y0 >> ctb_log2_size) << ctb_log2_size;
1097 if (!
ph->r->ph_temporal_mvp_enabled_flag ||
1098 !
sps->r->sps_sbtmvp_enabled_flag ||
1110 for (
int sby = 0; sby <
mi->num_sb_y; sby++) {
1111 for (
int sbx = 0; sbx <
mi->num_sb_x; sbx++) {
1112 int x = x0 + sbx * sbw;
1113 int y = y0 + sby * sbh;
1117 memcpy(mvf.
mv, ctr_mvf.
mv,
sizeof(mvf.
mv));
1129 if (c0 &&
c1 &&
c2) {
1131 for (
int i = 0;
i < 2;
i++) {
1136 mi->mv[
i][0] = c0->
mv[
i];
1137 mi->mv[
i][1] =
c1->mv[
i];
1138 mi->mv[
i][2] =
c2->mv[
i];
1141 if (
mi->pred_flag) {
1153 if (c0 &&
c1 && c3) {
1155 for (
int i = 0;
i < 2;
i++) {
1160 mi->mv[
i][0] = c0->
mv[
i];
1161 mi->mv[
i][1] =
c1->mv[
i];
1167 if (
mi->pred_flag) {
1178 if (c0 &&
c2 && c3) {
1180 for (
int i = 0;
i < 2;
i++) {
1185 mi->mv[
i][0] = c0->
mv[
i];
1189 mi->mv[
i][2] =
c2->mv[
i];
1192 if (
mi->pred_flag) {
1203 if (
c1 &&
c2 && c3) {
1205 for (
int i = 0;
i < 2;
i++) {
1209 mi->ref_idx[
i] =
c1->ref_idx[
i];
1213 mi->mv[
i][1] =
c1->mv[
i];
1214 mi->mv[
i][2] =
c2->mv[
i];
1217 if (
mi->pred_flag) {
1218 mi->bcw_idx =
mi->pred_flag ==
PF_BI ?
c1->bcw_idx : 0;
1230 for (
int i = 0;
i < 2;
i++) {
1235 mi->mv[
i][0] = c0->
mv[
i];
1236 mi->mv[
i][1] =
c1->mv[
i];
1239 if (
mi->pred_flag) {
1254 for (
int i = 0;
i < 2;
i++) {
1259 mi->mv[
i][0] = c0->
mv[
i];
1266 if (
mi->pred_flag) {
1280 memset(
mi, 0,
sizeof(*
mi));
1302 if (
fc->ps.sps->r->sps_6param_affine_enabled_flag) {
1306 if (merge_subblock_idx == num_cands)
1311 memset(&corner3, 0,
sizeof(corner3));
1312 if (
fc->ps.ph.r->ph_temporal_mvp_enabled_flag){
1317 corner3.
pred_flag = available_l0 + (available_l1 << 1);
1324 if (merge_subblock_idx == num_cands)
1331 if (merge_subblock_idx == num_cands)
1338 if (merge_subblock_idx == num_cands)
1346 if (merge_subblock_idx == num_cands)
1352 if (merge_subblock_idx == num_cands)
1372 if (merge_subblock_idx == num_cands)
1381 if (
sps->r->sps_affine_enabled_flag) {
1386 if (merge_subblock_idx == num_cands)
1393 if (merge_subblock_idx == num_cands)
1417 const int lx,
const int8_t *ref_idx,
Mv *
mv)
1421 const int min_pu_width =
fc->ps.pps->min_pu_width;
1425 const int poc = rpl[lx].
refs[ref_idx[lx]].
poc;
1444 const int x_cand,
const int y_cand,
const int lx,
const int8_t *ref_idx,
1445 Mv *cps,
const int num_cp)
1448 int x_nb, y_nb, nbw, nbh, motion_model_idc,
available = 0;
1451 if (motion_model_idc) {
1452 const int min_pu_width =
fc->ps.pps->min_pu_width;
1457 const int poc = rpl[lx].
refs[ref_idx[lx]].
poc;
1476 const NeighbourIdx *nbs,
const int num_nbs,
const int lx,
const int8_t *ref_idx,
const int amvr_shift,
1477 Mv *cps,
const int num_cps)
1482 for (
int i = 0;
i < num_nbs;
i++) {
1490 for (
int c = 0;
c < num_cps;
c++)
1500 #define AFFINE_MVP_FROM_NBS(nbs) \
1501 mvp_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), lx, ref_idx, amvr_shift, cps, num_cp) \
1503 #define MVP_FROM_NBS(nbs) \
1504 mvp_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), lx, ref_idx, amvr_shift, mv, 1) \
1507 const int mvp_lx_flag,
const int lx,
const int8_t* ref_idx,
const int amvr_shift,
1508 Mv*
mv,
int *nb_merge_cand)
1513 int available_a, num_cands = 0;
1520 if (mvp_lx_flag == num_cands)
1527 if (mvp_lx_flag == num_cands)
1532 *nb_merge_cand = 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)
1541 if (mvp_lx_flag == *num_cands) {
1552 const int mvp_lx_flag,
const int lx,
const int8_t ref_idx,
const int amvr_shift,
1553 Mv *
mv,
int num_cands)
1557 const int poc = rpl[lx].
refs[ref_idx].
poc;
1563 for (
int j = 0; j < 2; j++) {
1564 const int ly = (j ? !lx : lx);
1566 if ((
h->pred_flag &
mask) && poc == rpl[ly].
refs[
h->ref_idx[ly]].
poc) {
1567 if (mvp_lx_flag == num_cands) {
1581 const int8_t *ref_idx,
const int amvr_shift,
Mv *
mv)
1594 memset(
mv, 0,
sizeof(*
mv));
1605 mvp(lc, mvp_lx_flag[
L0],
L0,
mi->ref_idx, amvr_shift, &
mi->mv[
L0][0]);
1607 mvp(lc, mvp_lx_flag[
L1],
L1,
mi->ref_idx, amvr_shift, &
mi->mv[
L1][0]);
1614 const int min_pu_width =
fc->ps.pps->min_pu_width;
1632 if (num_cands > merge_idx)
1637 if (!num_cands || !
IS_SAME_MV(&cand_list[0], mvf->
mv)) {
1638 cand_list[num_cands++] = mvf->
mv[
L0];
1639 if (num_cands > merge_idx)
1644 *nb_merge_cand = num_cands;
1649 const int merge_idx,
Mv *cand_list,
int *nb_merge_cand)
1654 int num_cands = *nb_merge_cand;
1657 int same_motion = 0;
1659 for (
int j = 0; j < *nb_merge_cand; j++) {
1660 same_motion = is_gt4by4 &&
i == 1 &&
IS_SAME_MV(&mvf->
mv[
L0], &cand_list[j]);
1665 cand_list[num_cands++] = mvf->
mv[
L0];
1666 if (num_cands > merge_idx)
1671 *nb_merge_cand = num_cands;
1676 #define IBC_SHIFT(v) ((v) >= (1 << (MV_BITS - 1)) ? ((v) - (1 << MV_BITS)) : (v))
1695 *
mv = cand_list[merge_idx];
1700 memset(
mv, 0,
sizeof(*
mv));
1710 if (
sps->ctb_size_y < ((cu->
y0 + (bv->
y >> 4)) & (
sps->ctb_size_y - 1)) + cu->
cb_height) {
1734 const NeighbourIdx *neighbour,
const int num_neighbour,
1735 const int lx,
const int8_t ref_idx,
const int amvr_shift,
Mv *cp)
1740 const int min_pu_width =
fc->ps.pps->min_pu_width;
1744 for (
int i = 0;
i < num_neighbour;
i++) {
1749 const int poc = rpl[lx].
refs[ref_idx].
poc;
1770 #define AFFINE_MVP_CONSTRUCTED_CP(cands, cp) \
1771 affine_mvp_constructed_cp(nctx, cands, FF_ARRAY_ELEMS(cands), lx, ref_idx, \
1776 const int lx,
const int8_t ref_idx,
const int amvr_shift,
1792 const Mv mv = cps[idx];
1793 for (
int j = 0; j < num_cp; j++)
1799 const int mvp_lx_flag,
const int lx,
const int8_t *ref_idx,
const int amvr_shift,
1804 const int num_cp = motion_model_idc + 1;
1812 if (mvp_lx_flag == num_cands)
1818 if (mvp_lx_flag == num_cands)
1826 if (mvp_lx_flag == num_cands)
1833 for (
int i = 2;
i >= 0;
i--) {
1835 if (mvp_lx_flag == num_cands) {
1843 if (mvp_lx_flag == num_cands) {
1845 for (
int i = 1;
i < num_cp;
i++)
1853 memset(cps, 0, num_cp *
sizeof(
Mv));
1874 const int offset = 1 << (rshift - 1);
1875 mv->x = ((
mv->x +
offset - (
mv->x >= 0)) >> rshift) * (1 << lshift);
1876 mv->y = ((
mv->y +
offset - (
mv->y >= 0)) >> rshift) * (1 << lshift);
1878 mv->x =
mv->x * (1 << lshift);
1879 mv->y =
mv->y * (1 << lshift);
1885 mv->x =
av_clip(
mv->x, -(1 << 17), (1 << 17) - 1);
1886 mv->y =
av_clip(
mv->y, -(1 << 17), (1 << 17) - 1);
1892 const uint8_t plevel =
fc->ps.sps->log2_parallel_merge_level;
1894 return x0_br >> plevel > x0 >> plevel &&
1895 y0_br >> plevel > y0 >> plevel;
1902 for (
i = 0;
i < *num_hmvp;
i++) {
1913 memmove(hmvp +
i, hmvp +
i + 1, (*num_hmvp -
i) *
sizeof(
MvField));
1914 hmvp[(*num_hmvp)++] = *mvf;
1928 const int min_pu_width =
fc->ps.pps->min_pu_width;
1945 const int min_pu_width =
fc->ps.pps->min_pu_width;
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)
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
void ff_vvc_update_hmvp(VVCLocalContext *lc, const MotionInfo *mi)
Mv mv[2][MAX_CONTROL_POINTS]
static int mv_merge_temporal_candidate(const VVCLocalContext *lc, MvField *cand)
void ff_vvc_affine_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift, MotionInfo *mi)
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 av_always_inline int is_same_mer(const VVCFrameContext *fc, const int xN, const int yN, const int xP, const int yP)
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 const int8_t mv[256][2]
uint8_t gpm_partition_idx
static int FUNC() ph(CodedBitstreamContext *ctx, RWContext *rw, H266RawPH *current)
#define MV_MERGE_FROM_NB(nb)
#define MAX_NUM_HMVP_CANDS
static int is_available(const VVCFrameContext *fc, const int x0, const int y0)
static int temporal_luma_motion_vector(const VVCLocalContext *lc, const int refIdxLx, Mv *mvLXCol, const int X, int check_center, int sb_flag)
int16_t y
vertical component of motion vector
static int sb_mv_merge_mode(const VVCLocalContext *lc, const int merge_subblock_idx, PredictionUnit *pu)
const H266RawSliceHeader * r
RefStruct reference.
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 int is_fallback_mode(const SubblockParams *sp, const PredFlag pred_flag)
#define fc(width, name, range_min, range_max)
#define DERIVE_CORNER_MV(nbs)
static int sb_temporal_merge_candidate(const VVCLocalContext *lc, NeighbourContext *nctx, PredictionUnit *pu)
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)
const int8_t ff_vvc_gpm_distance_lut[VVC_GPM_NUM_ANGLES]
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_distance_idx[VVC_GPM_NUM_PARTITION]
void ff_vvc_sb_mv_merge_mode(VVCLocalContext *lc, const int merge_subblock_idx, PredictionUnit *pu)
static void mv_merge_mode(const VVCLocalContext *lc, const int merge_idx, MvField *cand_list)
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 derive_cb_prof_flag_lx(const VVCLocalContext *lc, const PredictionUnit *pu, int lx, int is_fallback)
const VVCSPS * sps
RefStruct reference.
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 double b1(void *priv, double x, double y)
static int affine_merge_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand, MotionInfo *mi)
static const MvField * mv_merge_from_nb(NeighbourContext *ctx, const NeighbourIdx nb)
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_const4(const MvField *c1, const MvField *c2, const MvField *c3, MotionInfo *mi)
static int affine_merge_const_candidates(const VVCLocalContext *lc, MotionInfo *mi, NeighbourContext *nctx, const int merge_subblock_idx, int num_cands)
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)
#define MRG_MAX_NUM_CANDS
#define AFFINE_MERGE_FROM_NBS(nbs)
static int affine_merge_const6(const MvField *c0, const MvField *c2, const int cb_width, const int cb_height, MotionInfo *mi)
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
static av_always_inline int compare_mv_ref_idx(const MvField *n, const MvField *o)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
#define FF_ARRAY_ELEMS(a)
static void affine_merge_zero_motion(const VVCLocalContext *lc, MotionInfo *mi)
void ff_vvc_store_gpm_mvf(const VVCLocalContext *lc, const PredictionUnit *pu)
VVCRefPic refs[VVC_MAX_REF_ENTRIES]
void ff_vvc_clip_mv(Mv *mv)
void ff_vvc_store_mv(const VVCLocalContext *lc, const MotionInfo *mi)
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 mv_merge_pairwise_candidate(MvField *cand_list, const int num_cands, const int is_b)
static int ibc_history_candidates(const VVCLocalContext *lc, const int merge_idx, Mv *cand_list, int *nb_merge_cand)
#define MVP_FROM_NBS(nbs)
static const MvField * mv_merge_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand)
static av_always_inline PredMode pred_flag_to_mode(PredFlag pred)
#define LOCAL_ALIGNED_8(t, v,...)
static int ibc_check_mv(VVCLocalContext *lc, Mv *mv)
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
void ff_vvc_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift, 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)
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 void store_cp_mv(const VVCLocalContext *lc, const MotionInfo *mi, const int lx)
static int ibc_spatial_candidates(const VVCLocalContext *lc, const int merge_idx, Mv *const cand_list, int *nb_merge_cand)
void ff_vvc_round_mv(Mv *mv, const int lshift, const int rshift)
int is_scaled
RprConstraintsActiveFlag.
uint8_t ciip_flag
ciip_flag
int16_t x
horizontal component of motion vector
const H266RawPictureHeader * r
static void mv_merge_zero_motion_candidate(const VVCLocalContext *lc, const int merge_idx, MvField *cand_list, int num_cands)
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_mode(VVCLocalContext *lc, const int merge_idx, const int ciip_flag, MvField *mv)
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)
Neighbour neighbours[NUM_NBS]
static void init_neighbour_context(NeighbourContext *ctx, const VVCLocalContext *lc)
static const MvField * derive_corner_mvf(NeighbourContext *ctx, const NeighbourIdx *neighbour, const int num_neighbour)
int num_hmvp_ibc
NumHmvpIbcCand.
static int shift(int a, int b)
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
const VVCLocalContext * lc
static void init_subblock_params(SubblockParams *sp, const MotionInfo *mi, const int cb_width, const int cb_height, const int lx)
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 is_greater_mer(const VVCFrameContext *fc, const int x0, const int y0, const int x0_br, const int y0_br)
static void ibc_add_mvp(Mv *mv, Mv *mvp, const int amvr_shift)
void ff_vvc_luma_mv_merge_gpm(VVCLocalContext *lc, const int merge_gpm_idx[2], MvField *mv)
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
int16_t diff_mv_x[2][AFFINE_MIN_BLOCK_SIZE *AFFINE_MIN_BLOCK_SIZE]
diffMvLX
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)
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
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 is_a0_available(const VVCLocalContext *lc, const CodingUnit *cu)
uint8_t hpel_if_idx
hpelIfIdx
static int check_available(Neighbour *n, const VVCLocalContext *lc, const int check_mer)
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)
MvField hmvp[MAX_NUM_HMVP_CANDS]
HmvpCandList.
static int affine_merge_const5(const MvField *c0, const MvField *c1, MotionInfo *mi)
#define i(width, name, range_min, range_max)
static av_always_inline av_const double round(double x)
const uint8_t ff_vvc_gpm_angle_idx[VVC_GPM_NUM_PARTITION]
static void ibc_merge_candidates(VVCLocalContext *lc, const int merge_idx, Mv *mv)
#define TAB_CP_MV(lx, x, y)
static void affine_mvp_const2(const int idx, Mv *cps, const int num_cp)
int32_t poc
PicOrderCntVal.
void ff_vvc_store_sb_mvs(const VVCLocalContext *lc, PredictionUnit *pu)
int ff_vvc_no_backward_pred_flag(const VVCLocalContext *lc)
static void derive_subblock_diff_mvs(const VVCLocalContext *lc, PredictionUnit *pu, const SubblockParams *sp, const int lx)
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)
static const float pred[4]
static int FUNC() sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
int ff_vvc_mvp_ibc(VVCLocalContext *lc, const int mvp_l0_flag, const int amvr_shift, Mv *mv)
uint8_t inter_affine_flag
MvField * ff_vvc_get_mvf(const VVCFrameContext *fc, const int x0, const int y0)
void ff_vvc_set_neighbour_available(VVCLocalContext *lc, const int x0, const int y0, const int w, const int h)
static void update_hmvp(MvField *hmvp, int *num_hmvp, const MvField *mvf, int(*compare)(const MvField *n, const MvField *o))
static float compare(const AVFrame *haystack, const AVFrame *obj, int offx, int offy)
static int affine_merge_const2(const MvField *c0, const MvField *c1, const MvField *c3, MotionInfo *mi)
int ff_vvc_luma_mv_merge_ibc(VVCLocalContext *lc, const int merge_idx, Mv *mv)
enum PredMode pred_mode
PredMode.
static int ref[MAX_W *MAX_W]
static int affine_merge_const3(const MvField *c0, const MvField *c2, 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)
int16_t diff_mv_y[2][AFFINE_MIN_BLOCK_SIZE *AFFINE_MIN_BLOCK_SIZE]
diffMvLX
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)
MvField hmvp_ibc[MAX_NUM_HMVP_CANDS]
HmvpIbcCandList.
int8_t ref_idx[2]
refIdxL0, refIdxL1
#define AFFINE_MVP_FROM_NBS(nbs)
#define DERIVE_TEMPORAL_COLOCATED_MVS(sb_flag)
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)
void ff_vvc_store_mvf(const VVCLocalContext *lc, const MvField *mvf)
static int affine_merge_from_nbs(NeighbourContext *ctx, const NeighbourIdx *nbs, const int num_nbs, MotionInfo *cand)
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
static int compare_l0_mv(const MvField *n, const MvField *o)
static double a1(void *priv, double x, double y)
static av_always_inline void mv_compression(Mv *motion)
#define AFFINE_MVP_CONSTRUCTED_CP(cands, cp)
void ff_vvc_set_intra_mvf(const VVCLocalContext *lc, const int dmvr)
void ff_vvc_mv_scale(Mv *dst, const Mv *src, int td, int tb)
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)