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)
186 #define TAB_MVF(x, y) \
187 tab_mvf[((y) >> MIN_PU_LOG2) * min_pu_width + ((x) >> MIN_PU_LOG2)]
189 #define TAB_MVF_PU(v) \
190 TAB_MVF(x ## v, y ## v)
192 #define TAB_CP_MV(lx, x, y) \
193 fc->tab.cp_mv[lx][((((y) >> min_cb_log2_size) * min_cb_width + ((x) >> min_cb_log2_size)) ) * MAX_CONTROL_POINTS]
196 #define DERIVE_TEMPORAL_COLOCATED_MVS(sb_flag) \
197 derive_temporal_colocated_mvs(lc, temp_col, \
198 refIdxLx, mvLXCol, X, colPic, \
199 ff_vvc_get_ref_list(fc, ref, x, y), sb_flag)
203 const int refIdxLx,
Mv *mvLXCol,
const int X,
int check_center,
int sb_flag)
210 int x, y, x_end, y_end, colPic, availableFlagLXCol = 0;
211 int min_pu_width =
fc->ps.pps->min_pu_width;
217 memset(mvLXCol, 0,
sizeof(*mvLXCol));
224 tab_mvf =
ref->tab_dmvr_mvf;
231 x_end =
pps->subpic_x[subpic_idx] +
pps->subpic_width[subpic_idx];
232 y_end =
pps->subpic_y[subpic_idx] +
pps->subpic_height[subpic_idx];
235 (cu->
y0 >>
sps->ctb_log2_size_y) == (y >>
sps->ctb_log2_size_y) &&
236 x < x_end && y < y_end) {
244 if (tab_mvf && !availableFlagLXCol) {
253 return availableFlagLXCol;
260 const int min_pu_width =
fc->ps.pps->min_pu_width;
262 for (
int dy = 0; dy <
h; dy += min_pu_size) {
263 for (
int dx = 0; dx <
w; dx += min_pu_size) {
264 const int x = x0 + dx;
265 const int y = y0 + dy;
276 const int min_pu_width =
fc->ps.pps->min_pu_width;
278 for (
int dy = 0; dy < cu->
cb_height; dy += min_pu_size) {
279 for (
int dx = 0; dx < cu->
cb_width; dx += min_pu_size) {
280 const int x = cu->
x0 + dx;
281 const int y = cu->
y0 + dy;
285 mv->ciip_flag = ciip_flag;
294 const Mv* cp_mv = &
mi->mv[lx][0];
325 const int a = 4 * (2048 + sp->
d_hor_x);
327 const int c = 4 * (2048 + sp->
d_ver_y);
329 if (pred_flag ==
PF_BI) {
334 const int bx_wx4 = ((max_w4 - min_w4) >> 11) + 9;
335 const int bx_hx4 = ((max_h4 - min_h4) >> 11) + 9;
336 return bx_wx4 * bx_hx4 > 225;
338 const int bx_wxh = (
FFABS(
a) >> 11) + 9;
339 const int bx_hxh = (
FFABS(d) >> 11) + 9;
340 const int bx_wxv = (
FFABS(
b) >> 11) + 9;
341 const int bx_hxv = (
FFABS(
c) >> 11) + 9;
342 if (bx_wxh * bx_hxh <= 165 && bx_wxv * bx_hxv <= 165)
349 const int cb_width,
const int cb_height,
const int lx)
351 const int log2_cbw =
av_log2(cb_width);
352 const int log2_cbh =
av_log2(cb_height);
353 const Mv* cp_mv =
mi->mv[lx];
354 const int num_cp_mv =
mi->motion_model_idc + 1;
357 if (num_cp_mv == 3) {
375 const int dmv_limit = 1 << 5;
395 const int log2_min_cb_size =
fc->ps.sps->min_cb_log2_size_y;
396 const int min_cb_size =
fc->ps.sps->min_cb_size_y;
397 const int min_cb_width =
fc->ps.pps->min_cb_width;
398 const int num_cp_mv =
mi->motion_model_idc + 1;
400 for (
int dy = 0; dy < cu->
cb_height; dy += min_cb_size) {
401 for (
int dx = 0; dx < cu->
cb_width; dx += min_cb_size) {
402 const int x_cb = (cu->
x0 + dx) >> log2_min_cb_size;
403 const int y_cb = (cu->
y0 + dy) >> log2_min_cb_size;
406 memcpy(&
fc->tab.cp_mv[lx][
offset],
mi->mv[lx],
sizeof(
Mv) * num_cp_mv);
424 for (
int i = 0;
i < 2;
i++) {
426 if (
mi->pred_flag &
mask) {
434 for (
int sby = 0; sby <
mi->num_sb_y; sby++) {
435 for (
int sbx = 0; sbx <
mi->num_sb_x; sbx++) {
436 const int x0 = cu->
x0 + sbx * sbw;
437 const int y0 = cu->
y0 + sby * sbh;
438 for (
int i = 0;
i < 2;
i++) {
440 if (
mi->pred_flag &
mask) {
464 const int is_flip = angle_idx >= 13 &&angle_idx <= 27;
465 const int shift_hor = (angle_idx % 16 == 8 || (angle_idx % 16 && cu->
cb_height >= cu->
cb_width)) ? 0 : 1;
466 const int sign = angle_idx < 16 ? 1 : -1;
467 const int block_size = 4;
468 int offset_x = (-cu->
cb_width) >> 1;
472 offset_y += sign * ((distance_idx * cu->
cb_height) >> 3);
474 offset_x += sign * ((distance_idx * cu->
cb_width) >> 3);
476 for (
int y = 0; y < cu->
cb_height; y += block_size) {
477 for (
int x = 0; x < cu->
cb_width; x += block_size) {
478 const int motion_idx = (((x + offset_x) * (1 << 1)) + 5) * displacement_x +
479 (((y + offset_y) * (1 << 1)) + 5) * displacement_y;
480 const int s_type =
FFABS(motion_idx) < 32 ? 2 : (motion_idx <= 0 ? (1 - is_flip) : is_flip);
482 const int x0 = cu->
x0 + x;
483 const int y0 = cu->
y0 + y;
487 else if (s_type == 1 || (s_type == 2 && pred_flag !=
PF_BI))
495 mvf.
mv[lx] = mv1->
mv[lx];
517 for (
int i = 0;
i < 2;
i++) {
555 const int x = x0 >>
sps->min_cb_log2_size_y;
556 const int y = y0 >>
sps->min_cb_log2_size_y;
557 const int min_cb_width =
fc->ps.pps->min_cb_width;
567 int cand_bottom_left;
570 cand_bottom_left = 0;
572 const int max_y =
FFMIN(
fc->ps.pps->height, ((cu->
y0 >>
sps->ctb_log2_size_y) + 1) <<
sps->ctb_log2_size_y);
574 cand_bottom_left = 0;
578 return cand_bottom_left;
585 const int x0 = cu->
x0;
586 const int y0 = cu->
y0;
592 { x0 - 1, y0 + cb_height, !a0_available },
593 { x0 - 1, y0 + cb_height - 1, !na->
cand_left },
596 { x0 + cb_width - 1, y0 - 1, !na->
cand_up },
601 memcpy(
ctx->neighbours, neighbours,
sizeof(neighbours));
628 const int min_pu_width =
fc->ps.pps->min_pu_width;
632 n->
available = !
sps->r->sps_entropy_coding_sync_enabled_flag || ((n->
x >>
sps->ctb_log2_size_y) <= (cu->
x0 >>
sps->ctb_log2_size_y));
643 const int min_pu_width =
fc->ps.pps->min_pu_width;
659 #define MV_MERGE_FROM_NB(nb) mv_merge_from_nb(&nctx, nb)
682 cand_list[num_cands] = *cand;
683 if (merge_idx == num_cands)
688 if (num_cands != 4) {
692 cand_list[num_cands] = *cand;
693 if (merge_idx == num_cands)
698 *nb_merge_cand = num_cands;
707 memset(cand, 0,
sizeof(*cand));
712 cand->
pred_flag = available_l0 + (available_l1 << 1);
723 for (
int i = 1;
i <= ep->
num_hmvp && (*num_cands <
sps->max_num_merge_cand - 1);
i++) {
727 cand_list[*num_cands] = *
h;
728 if (merge_idx == *num_cands)
740 const int num_ref_rists = is_b ? 2 : 1;
741 const MvField* p0 = cand_list + 0;
742 const MvField* p1 = cand_list + 1;
743 MvField* cand = cand_list + num_cands;
746 for (
int i = 0;
i < num_ref_rists;
i++) {
777 MvField *cand_list,
int num_cands)
781 const int num_ref_idx =
IS_P(rsh) ?
785 while (num_cands < sps->max_num_merge_cand) {
786 MvField *cand = cand_list + num_cands;
791 cand->
ref_idx[0] = zero_idx < num_ref_idx ? zero_idx : 0;
792 cand->
ref_idx[1] = zero_idx < num_ref_idx ? zero_idx : 0;
795 if (merge_idx == num_cands)
811 if (merge_idx == num_cands)
820 if (merge_idx == num_cands)
836 *
mv = cand_list[merge_idx];
838 mv->ciip_flag = ciip_flag;
847 const int idx[] = { merge_gpm_idx[0], merge_gpm_idx[1] + (merge_gpm_idx[1] >= merge_gpm_idx[0]) };
851 memset(
mv, 0, 2 *
sizeof(*
mv));
852 for (
int i = 0;
i < 2;
i++) {
862 mv[
i].mv[lx] = cand->
mv[lx];
869 const int x_nb,
int y_nb,
const int nbw,
const int nbh,
const int lx,
870 Mv *cps,
int num_cps)
874 const int x0 = cu->
x0;
875 const int y0 = cu->
y0;
879 const int min_cb_log2_size =
fc->ps.sps->min_cb_log2_size_y;
880 const int min_cb_width =
fc->ps.pps->min_cb_width;
882 const int log2_nbw =
ff_log2(nbw);
883 const int log2_nbh =
ff_log2(nbh);
884 const int is_ctb_boundary = !((y_nb + nbh) %
fc->ps.sps->ctb_size_y) && (y_nb + nbh == y0);
886 int mv_scale_hor, mv_scale_ver, d_hor_x, d_ver_x, d_hor_y, d_ver_y, motion_model_idc_nb;
887 if (is_ctb_boundary) {
888 const int min_pu_width =
fc->ps.pps->min_pu_width;
889 l = &
TAB_MVF(x_nb, y_nb + nbh - 1).mv[lx];
890 r = &
TAB_MVF(x_nb + nbw - 1, y_nb + nbh - 1).mv[lx];
892 const int x = x_nb >> min_cb_log2_size;
893 const int y = y_nb >> min_cb_log2_size;
899 mv_scale_hor = l->
x * (1 << 7);
900 mv_scale_ver = l->
y * (1 << 7);
901 d_hor_x = (
r->x - l->
x) * (1 << (7 - log2_nbw));
902 d_ver_x = (
r->y - l->
y) * (1 << (7 - log2_nbw));
904 const Mv* lb = &
TAB_CP_MV(lx, x_nb, y_nb + nbh - 1) + 2;
905 d_hor_y = (lb->
x - l->
x) * (1 << (7 - log2_nbh));
906 d_ver_y = (lb->
y - l->
y) * (1 << (7 - log2_nbh));
912 if (is_ctb_boundary) {
915 cps[0].
x = mv_scale_hor + d_hor_x * (x0 - x_nb) + d_hor_y * (y0 - y_nb);
916 cps[0].
y = mv_scale_ver + d_ver_x * (x0 - x_nb) + d_ver_y * (y0 - y_nb);
917 cps[1].
x = mv_scale_hor + d_hor_x * (x0 + cb_width - x_nb) + d_hor_y * (y0 - y_nb);
918 cps[1].
y = mv_scale_ver + d_ver_x * (x0 + cb_width - x_nb) + d_ver_y * (y0 - y_nb);
920 cps[2].
x = mv_scale_hor + d_hor_x * (x0 - x_nb) + d_hor_y * (y0 + cb_height - y_nb);
921 cps[2].
y = mv_scale_ver + d_ver_x * (x0 - x_nb) + d_ver_y * (y0 + cb_height - y_nb);
923 for (
int i = 0;
i < num_cps;
i++) {
932 const int log2_min_cb_size =
fc->ps.sps->min_cb_log2_size_y;
933 const int min_cb_width =
fc->ps.pps->min_cb_width;
934 const int x = x_nb >> log2_min_cb_size;
935 const int y = y_nb >> log2_min_cb_size;
936 const int motion_model_idc =
SAMPLE_CTB(
fc->tab.mmi, x, y);
937 if (motion_model_idc) {
943 return motion_model_idc;
950 int x, y,
w,
h, motion_model_idc;
953 if (motion_model_idc) {
954 const int min_pu_width =
fc->ps.pps->min_pu_width;
960 for (
int i = 0;
i < 2;
i++) {
962 if (
mi->pred_flag &
mask) {
967 mi->motion_model_idc = motion_model_idc;
969 return motion_model_idc;
975 for (
int i = 0;
i < num_nbs;
i++) {
982 #define AFFINE_MERGE_FROM_NBS(nbs) affine_merge_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), mi)
989 const int min_pu_width =
fc->ps.pps->min_pu_width;
990 for (
int i = 0;
i < num_neighbour;
i++) {
999 #define DERIVE_CORNER_MV(nbs) derive_corner_mvf(nctx, nbs, FF_ARRAY_ELEMS(nbs))
1008 if (
A->ref_idx[lx] !=
B->ref_idx[lx])
1011 if (!(
C->pred_flag &
mask))
1013 if (
A->ref_idx[lx] !=
C->ref_idx[lx])
1020 const int x_ctb,
const int y_ctb,
const Mv* temp_mv,
int *x,
int *y)
1024 const int ctb_log2_size =
fc->ps.sps->ctb_log2_size_y;
1026 const int x_end =
pps->subpic_x[subpic_idx] +
pps->subpic_width[subpic_idx];
1027 const int y_end =
pps->subpic_y[subpic_idx] +
pps->subpic_height[subpic_idx];
1029 *x =
av_clip(*x + temp_mv->
x, x_ctb,
FFMIN(x_end - 1, x_ctb + (1 << ctb_log2_size) + 3)) & ~7;
1030 *y =
av_clip(*y + temp_mv->
y, y_ctb,
FFMIN(y_end - 1, y_ctb + (1 << ctb_log2_size) - 1)) & ~7;
1034 const int x_ctb,
const int y_ctb,
const Mv *temp_mv,
1035 int x,
int y, uint8_t *pred_flag,
Mv *
mv)
1039 const int refIdxLx = 0;
1042 const int min_pu_width =
fc->ps.pps->min_pu_width;
1045 int colPic =
ref->poc;
1062 const int x_ctb,
const int y_ctb,
MvField *ctr_mvf,
Mv *temp_mv)
1073 memset(temp_mv, 0,
sizeof(*temp_mv));
1076 memset(ctr_mvf, 0,
sizeof(*ctr_mvf));
1084 *temp_mv =
a1->mv[0];
1086 *temp_mv =
a1->mv[1];
1103 const int ctb_log2_size =
sps->ctb_log2_size_y;
1104 const int x0 = cu->
x0;
1105 const int y0 = cu->
y0;
1110 const int x_ctb = (x0 >> ctb_log2_size) << ctb_log2_size;
1111 const int y_ctb = (y0 >> ctb_log2_size) << ctb_log2_size;
1114 if (!
ph->r->ph_temporal_mvp_enabled_flag ||
1115 !
sps->r->sps_sbtmvp_enabled_flag ||
1127 for (
int sby = 0; sby <
mi->num_sb_y; sby++) {
1128 for (
int sbx = 0; sbx <
mi->num_sb_x; sbx++) {
1129 int x = x0 + sbx * sbw;
1130 int y = y0 + sby * sbh;
1134 memcpy(mvf.
mv, ctr_mvf.
mv,
sizeof(mvf.
mv));
1146 if (c0 &&
c1 &&
c2) {
1148 for (
int i = 0;
i < 2;
i++) {
1153 mi->mv[
i][0] = c0->
mv[
i];
1154 mi->mv[
i][1] =
c1->mv[
i];
1155 mi->mv[
i][2] =
c2->mv[
i];
1158 if (
mi->pred_flag) {
1170 if (c0 &&
c1 && c3) {
1172 for (
int i = 0;
i < 2;
i++) {
1177 mi->mv[
i][0] = c0->
mv[
i];
1178 mi->mv[
i][1] =
c1->mv[
i];
1184 if (
mi->pred_flag) {
1195 if (c0 &&
c2 && c3) {
1197 for (
int i = 0;
i < 2;
i++) {
1202 mi->mv[
i][0] = c0->
mv[
i];
1206 mi->mv[
i][2] =
c2->mv[
i];
1209 if (
mi->pred_flag) {
1220 if (
c1 &&
c2 && c3) {
1222 for (
int i = 0;
i < 2;
i++) {
1226 mi->ref_idx[
i] =
c1->ref_idx[
i];
1230 mi->mv[
i][1] =
c1->mv[
i];
1231 mi->mv[
i][2] =
c2->mv[
i];
1234 if (
mi->pred_flag) {
1235 mi->bcw_idx =
mi->pred_flag ==
PF_BI ?
c1->bcw_idx : 0;
1247 for (
int i = 0;
i < 2;
i++) {
1252 mi->mv[
i][0] = c0->
mv[
i];
1253 mi->mv[
i][1] =
c1->mv[
i];
1256 if (
mi->pred_flag) {
1271 for (
int i = 0;
i < 2;
i++) {
1276 mi->mv[
i][0] = c0->
mv[
i];
1283 if (
mi->pred_flag) {
1297 memset(
mi, 0,
sizeof(*
mi));
1319 if (
fc->ps.sps->r->sps_6param_affine_enabled_flag) {
1323 if (merge_subblock_idx == num_cands)
1328 memset(&corner3, 0,
sizeof(corner3));
1329 if (
fc->ps.ph.r->ph_temporal_mvp_enabled_flag){
1334 corner3.
pred_flag = available_l0 + (available_l1 << 1);
1341 if (merge_subblock_idx == num_cands)
1348 if (merge_subblock_idx == num_cands)
1355 if (merge_subblock_idx == num_cands)
1363 if (merge_subblock_idx == num_cands)
1369 if (merge_subblock_idx == num_cands)
1389 if (merge_subblock_idx == num_cands)
1398 if (
sps->r->sps_affine_enabled_flag) {
1403 if (merge_subblock_idx == num_cands)
1410 if (merge_subblock_idx == num_cands)
1434 const int lx,
const int8_t *ref_idx,
Mv *
mv)
1438 const int min_pu_width =
fc->ps.pps->min_pu_width;
1442 const int poc = rpl[lx].
refs[ref_idx[lx]].
poc;
1461 const int x_cand,
const int y_cand,
const int lx,
const int8_t *ref_idx,
1462 Mv *cps,
const int num_cp)
1465 int x_nb, y_nb, nbw, nbh, motion_model_idc,
available = 0;
1468 if (motion_model_idc) {
1469 const int min_pu_width =
fc->ps.pps->min_pu_width;
1474 const int poc = rpl[lx].
refs[ref_idx[lx]].
poc;
1493 const NeighbourIdx *nbs,
const int num_nbs,
const int lx,
const int8_t *ref_idx,
const int amvr_shift,
1494 Mv *cps,
const int num_cps)
1499 for (
int i = 0;
i < num_nbs;
i++) {
1507 for (
int c = 0;
c < num_cps;
c++)
1517 #define AFFINE_MVP_FROM_NBS(nbs) \
1518 mvp_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), lx, ref_idx, amvr_shift, cps, num_cp) \
1520 #define MVP_FROM_NBS(nbs) \
1521 mvp_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), lx, ref_idx, amvr_shift, mv, 1) \
1524 const int mvp_lx_flag,
const int lx,
const int8_t* ref_idx,
const int amvr_shift,
1525 Mv*
mv,
int *nb_merge_cand)
1530 int available_a, num_cands = 0;
1537 if (mvp_lx_flag == num_cands)
1544 if (mvp_lx_flag == num_cands)
1549 *nb_merge_cand = num_cands;
1554 const int mvp_lx_flag,
const int lx,
const int8_t *ref_idx,
const int amvr_shift,
1555 Mv*
mv,
int *num_cands)
1558 if (mvp_lx_flag == *num_cands) {
1569 const int mvp_lx_flag,
const int lx,
const int8_t ref_idx,
const int amvr_shift,
1570 Mv *
mv,
int num_cands)
1574 const int poc = rpl[lx].
refs[ref_idx].
poc;
1580 for (
int j = 0; j < 2; j++) {
1581 const int ly = (j ? !lx : lx);
1583 if ((
h->pred_flag &
mask) && poc == rpl[ly].
refs[
h->ref_idx[ly]].
poc) {
1584 if (mvp_lx_flag == num_cands) {
1598 const int8_t *ref_idx,
const int amvr_shift,
Mv *
mv)
1611 memset(
mv, 0,
sizeof(*
mv));
1622 mvp(lc, mvp_lx_flag[
L0],
L0,
mi->ref_idx, amvr_shift, &
mi->mv[
L0][0]);
1624 mvp(lc, mvp_lx_flag[
L1],
L1,
mi->ref_idx, amvr_shift, &
mi->mv[
L1][0]);
1631 const int min_pu_width =
fc->ps.pps->min_pu_width;
1649 if (num_cands > merge_idx)
1654 if (!num_cands || !
IS_SAME_MV(&cand_list[0], mvf->
mv)) {
1655 cand_list[num_cands++] = mvf->
mv[
L0];
1656 if (num_cands > merge_idx)
1661 *nb_merge_cand = num_cands;
1666 const int merge_idx,
Mv *cand_list,
int *nb_merge_cand)
1671 int num_cands = *nb_merge_cand;
1674 int same_motion = 0;
1676 for (
int j = 0; j < *nb_merge_cand; j++) {
1677 same_motion = is_gt4by4 &&
i == 1 &&
IS_SAME_MV(&mvf->
mv[
L0], &cand_list[j]);
1682 cand_list[num_cands++] = mvf->
mv[
L0];
1683 if (num_cands > merge_idx)
1688 *nb_merge_cand = num_cands;
1693 #define IBC_SHIFT(v) ((v) >= (1 << (MV_BITS - 1)) ? ((v) - (1 << MV_BITS)) : (v))
1712 *
mv = cand_list[merge_idx];
1717 memset(
mv, 0,
sizeof(*
mv));
1727 if (
sps->ctb_size_y < ((cu->
y0 + (bv->
y >> 4)) & (
sps->ctb_size_y - 1)) + cu->
cb_height) {
1751 const NeighbourIdx *neighbour,
const int num_neighbour,
1752 const int lx,
const int8_t ref_idx,
const int amvr_shift,
Mv *cp)
1757 const int min_pu_width =
fc->ps.pps->min_pu_width;
1761 for (
int i = 0;
i < num_neighbour;
i++) {
1766 const int poc = rpl[lx].
refs[ref_idx].
poc;
1787 #define AFFINE_MVP_CONSTRUCTED_CP(cands, cp) \
1788 affine_mvp_constructed_cp(nctx, cands, FF_ARRAY_ELEMS(cands), lx, ref_idx, \
1793 const int lx,
const int8_t ref_idx,
const int amvr_shift,
1809 const Mv mv = cps[idx];
1810 for (
int j = 0; j < num_cp; j++)
1816 const int mvp_lx_flag,
const int lx,
const int8_t *ref_idx,
const int amvr_shift,
1821 const int num_cp = motion_model_idc + 1;
1829 if (mvp_lx_flag == num_cands)
1835 if (mvp_lx_flag == num_cands)
1843 if (mvp_lx_flag == num_cands)
1850 for (
int i = 2;
i >= 0;
i--) {
1852 if (mvp_lx_flag == num_cands) {
1860 if (mvp_lx_flag == num_cands) {
1862 for (
int i = 1;
i < num_cp;
i++)
1870 memset(cps, 0, num_cp *
sizeof(
Mv));
1891 const int offset = 1 << (rshift - 1);
1892 mv->x = ((
mv->x +
offset - (
mv->x >= 0)) >> rshift) * (1 << lshift);
1893 mv->y = ((
mv->y +
offset - (
mv->y >= 0)) >> rshift) * (1 << lshift);
1895 mv->x =
mv->x * (1 << lshift);
1896 mv->y =
mv->y * (1 << lshift);
1902 mv->x =
av_clip(
mv->x, -(1 << 17), (1 << 17) - 1);
1903 mv->y =
av_clip(
mv->y, -(1 << 17), (1 << 17) - 1);
1909 const uint8_t plevel =
fc->ps.sps->log2_parallel_merge_level;
1911 return x0_br >> plevel > x0 >> plevel &&
1912 y0_br >> plevel > y0 >> plevel;
1919 for (
i = 0;
i < *num_hmvp;
i++) {
1930 memmove(hmvp +
i, hmvp +
i + 1, (*num_hmvp -
i) *
sizeof(
MvField));
1931 hmvp[(*num_hmvp)++] = *mvf;
1945 const int min_pu_width =
fc->ps.pps->min_pu_width;
1962 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 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)
#define fc(width, name, range_min, range_max)
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)
void ff_vvc_set_intra_mvf(const VVCLocalContext *lc, const bool dmvr, const PredFlag pf, const bool ciip_flag)
#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_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)