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);
321 const int b = 4 *
sp->d_hor_y;
322 const int c = 4 * (2048 +
sp->d_ver_y);
323 const int d = 4 *
sp->d_ver_x;
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) {
356 sp->d_hor_y = -
sp->d_ver_x;
357 sp->d_ver_y =
sp->d_hor_x;
361 sp->cb_width = cb_width;
362 sp->cb_height = cb_height;
370 const int dmv_limit = 1 << 5;
371 const int pos_offset_x = 6 * (
sp->d_hor_x +
sp->d_hor_y);
372 const int pos_offset_y = 6 * (
sp->d_ver_x +
sp->d_ver_y);
376 diff->x = x * (
sp->d_hor_x * (1 << 2)) + y * (
sp->d_hor_y * (1 << 2)) - pos_offset_x;
377 diff->y = x * (
sp->d_ver_x * (1 << 2)) + y * (
sp->d_ver_y * (1 << 2)) - pos_offset_y;
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);
420 for (
int i = 0;
i < 2;
i++) {
422 if (
mi->pred_flag &
mask) {
430 for (
int sby = 0; sby <
mi->num_sb_y; sby++) {
431 for (
int sbx = 0; sbx <
mi->num_sb_x; sbx++) {
432 const int x0 = cu->
x0 + sbx * sbw;
433 const int y0 = cu->
y0 + sby * sbh;
434 for (
int i = 0;
i < 2;
i++) {
436 if (
mi->pred_flag &
mask) {
442 mv->x =
sp->mv_scale_hor +
sp->d_hor_x * x_pos_cb +
sp->d_hor_y * y_pos_cb;
443 mv->y =
sp->mv_scale_ver +
sp->d_ver_x * x_pos_cb +
sp->d_ver_y * y_pos_cb;
460 const int is_flip = angle_idx >= 13 &&angle_idx <= 27;
461 const int shift_hor = (angle_idx % 16 == 8 || (angle_idx % 16 && cu->
cb_height >= cu->
cb_width)) ? 0 : 1;
462 const int sign = angle_idx < 16 ? 1 : -1;
463 const int block_size = 4;
464 int offset_x = (-cu->
cb_width) >> 1;
468 offset_y += sign * ((distance_idx * cu->
cb_height) >> 3);
470 offset_x += sign * ((distance_idx * cu->
cb_width) >> 3);
472 for (
int y = 0; y < cu->
cb_height; y += block_size) {
473 for (
int x = 0; x < cu->
cb_width; x += block_size) {
474 const int motion_idx = (((x + offset_x) * (1 << 1)) + 5) * displacement_x +
475 (((y + offset_y) * (1 << 1)) + 5) * displacement_y;
476 const int s_type =
FFABS(motion_idx) < 32 ? 2 : (motion_idx <= 0 ? (1 - is_flip) : is_flip);
478 const int x0 = cu->
x0 + x;
479 const int y0 = cu->
y0 + y;
483 else if (s_type == 1 || (s_type == 2 && pred_flag !=
PF_BI))
491 mvf.
mv[lx] = mv1->
mv[lx];
513 for (
int i = 0;
i < 2;
i++) {
553 int cand_bottom_left;
556 cand_bottom_left = 0;
558 const int log2_min_cb_size =
sps->min_cb_log2_size_y;
559 const int min_cb_width =
fc->ps.pps->min_cb_width;
560 const int x = (cu->
x0 - 1) >> log2_min_cb_size;
561 const int y = (cu->
y0 + cu->
cb_height) >> log2_min_cb_size;
562 const int max_y =
FFMIN(
fc->ps.pps->height, ((cu->
y0 >>
sps->ctb_log2_size_y) + 1) <<
sps->ctb_log2_size_y);
564 cand_bottom_left = 0;
566 cand_bottom_left =
SAMPLE_CTB(
fc->tab.cb_width[0], x, y) != 0;
568 return cand_bottom_left;
575 const int x0 = cu->
x0;
576 const int y0 = cu->
y0;
582 { x0 - 1, y0 + cb_height, !a0_available },
583 { x0 - 1, y0 + cb_height - 1, !na->
cand_left },
586 { x0 + cb_width - 1, y0 - 1, !na->
cand_up },
591 memcpy(
ctx->neighbours, neighbours,
sizeof(neighbours));
606 const int min_pu_width =
fc->ps.pps->min_pu_width;
610 n->
available = !
sps->r->sps_entropy_coding_sync_enabled_flag || ((n->
x >>
sps->ctb_log2_size_y) <= (cu->
x0 >>
sps->ctb_log2_size_y));
621 const int min_pu_width =
fc->ps.pps->min_pu_width;
637 #define MV_MERGE_FROM_NB(nb) mv_merge_from_nb(&nctx, nb)
660 cand_list[num_cands] = *cand;
661 if (merge_idx == num_cands)
666 if (num_cands != 4) {
670 cand_list[num_cands] = *cand;
671 if (merge_idx == num_cands)
676 *nb_merge_cand = num_cands;
685 memset(cand, 0,
sizeof(*cand));
690 cand->
pred_flag = available_l0 + (available_l1 << 1);
701 for (
int i = 1;
i <= ep->
num_hmvp && (*num_cands <
sps->max_num_merge_cand - 1);
i++) {
705 cand_list[*num_cands] = *
h;
706 if (merge_idx == *num_cands)
718 const int num_ref_rists = is_b ? 2 : 1;
719 const MvField* p0 = cand_list + 0;
720 const MvField* p1 = cand_list + 1;
721 MvField* cand = cand_list + num_cands;
724 for (
int i = 0;
i < num_ref_rists;
i++) {
755 MvField *cand_list,
int num_cands)
759 const int num_ref_idx =
IS_P(rsh) ?
763 while (num_cands < sps->max_num_merge_cand) {
764 MvField *cand = cand_list + num_cands;
769 cand->
ref_idx[0] = zero_idx < num_ref_idx ? zero_idx : 0;
770 cand->
ref_idx[1] = zero_idx < num_ref_idx ? zero_idx : 0;
773 if (merge_idx == num_cands)
789 if (merge_idx == num_cands)
798 if (merge_idx == num_cands)
814 *
mv = cand_list[merge_idx];
816 mv->ciip_flag = ciip_flag;
825 const int idx[] = { merge_gpm_idx[0], merge_gpm_idx[1] + (merge_gpm_idx[1] >= merge_gpm_idx[0]) };
829 memset(
mv, 0, 2 *
sizeof(*
mv));
830 for (
int i = 0;
i < 2;
i++) {
840 mv[
i].mv[lx] = cand->
mv[lx];
847 const int x_nb,
int y_nb,
const int nbw,
const int nbh,
const int lx,
848 Mv *cps,
int num_cps)
852 const int x0 = cu->
x0;
853 const int y0 = cu->
y0;
857 const int min_cb_log2_size =
fc->ps.sps->min_cb_log2_size_y;
858 const int min_cb_width =
fc->ps.pps->min_cb_width;
860 const int log2_nbw =
ff_log2(nbw);
861 const int log2_nbh =
ff_log2(nbh);
862 const int is_ctb_boundary = !((y_nb + nbh) %
fc->ps.sps->ctb_size_y) && (y_nb + nbh == y0);
864 int mv_scale_hor, mv_scale_ver, d_hor_x, d_ver_x, d_hor_y, d_ver_y, motion_model_idc_nb;
865 if (is_ctb_boundary) {
866 const int min_pu_width =
fc->ps.pps->min_pu_width;
867 l = &
TAB_MVF(x_nb, y_nb + nbh - 1).mv[lx];
868 r = &
TAB_MVF(x_nb + nbw - 1, y_nb + nbh - 1).mv[lx];
870 const int x = x_nb >> min_cb_log2_size;
871 const int y = y_nb >> min_cb_log2_size;
877 mv_scale_hor = l->
x * (1 << 7);
878 mv_scale_ver = l->
y * (1 << 7);
879 d_hor_x = (
r->x - l->
x) * (1 << (7 - log2_nbw));
880 d_ver_x = (
r->y - l->
y) * (1 << (7 - log2_nbw));
882 const Mv* lb = &
TAB_CP_MV(lx, x_nb, y_nb + nbh - 1) + 2;
883 d_hor_y = (lb->
x - l->
x) * (1 << (7 - log2_nbh));
884 d_ver_y = (lb->
y - l->
y) * (1 << (7 - log2_nbh));
890 if (is_ctb_boundary) {
893 cps[0].
x = mv_scale_hor + d_hor_x * (x0 - x_nb) + d_hor_y * (y0 - y_nb);
894 cps[0].
y = mv_scale_ver + d_ver_x * (x0 - x_nb) + d_ver_y * (y0 - y_nb);
895 cps[1].
x = mv_scale_hor + d_hor_x * (x0 + cb_width - x_nb) + d_hor_y * (y0 - y_nb);
896 cps[1].
y = mv_scale_ver + d_ver_x * (x0 + cb_width - x_nb) + d_ver_y * (y0 - y_nb);
898 cps[2].
x = mv_scale_hor + d_hor_x * (x0 - x_nb) + d_hor_y * (y0 + cb_height - y_nb);
899 cps[2].
y = mv_scale_ver + d_ver_x * (x0 - x_nb) + d_ver_y * (y0 + cb_height - y_nb);
901 for (
int i = 0;
i < num_cps;
i++) {
910 const int log2_min_cb_size =
fc->ps.sps->min_cb_log2_size_y;
911 const int min_cb_width =
fc->ps.pps->min_cb_width;
912 const int x = x_nb >> log2_min_cb_size;
913 const int y = y_nb >> log2_min_cb_size;
914 const int motion_model_idc =
SAMPLE_CTB(
fc->tab.mmi, x, y);
915 if (motion_model_idc) {
921 return motion_model_idc;
928 int x, y,
w,
h, motion_model_idc;
931 if (motion_model_idc) {
932 const int min_pu_width =
fc->ps.pps->min_pu_width;
938 for (
int i = 0;
i < 2;
i++) {
940 if (
mi->pred_flag &
mask) {
945 mi->motion_model_idc = motion_model_idc;
947 return motion_model_idc;
953 for (
int i = 0;
i < num_nbs;
i++) {
960 #define AFFINE_MERGE_FROM_NBS(nbs) affine_merge_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), mi)
967 const int min_pu_width =
fc->ps.pps->min_pu_width;
968 for (
int i = 0;
i < num_neighbour;
i++) {
977 #define DERIVE_CORNER_MV(nbs) derive_corner_mvf(nctx, nbs, FF_ARRAY_ELEMS(nbs))
986 if (
A->ref_idx[lx] !=
B->ref_idx[lx])
989 if (!(
C->pred_flag &
mask))
991 if (
A->ref_idx[lx] !=
C->ref_idx[lx])
998 const int x_ctb,
const int y_ctb,
const Mv* temp_mv,
int *x,
int *y)
1002 const int ctb_log2_size =
fc->ps.sps->ctb_log2_size_y;
1004 const int x_end =
pps->subpic_x[subpic_idx] +
pps->subpic_width[subpic_idx];
1005 const int y_end =
pps->subpic_y[subpic_idx] +
pps->subpic_height[subpic_idx];
1007 *x =
av_clip(*x + temp_mv->
x, x_ctb,
FFMIN(x_end - 1, x_ctb + (1 << ctb_log2_size) + 3)) & ~7;
1008 *y =
av_clip(*y + temp_mv->
y, y_ctb,
FFMIN(y_end - 1, y_ctb + (1 << ctb_log2_size) - 1)) & ~7;
1012 const int x_ctb,
const int y_ctb,
const Mv *temp_mv,
1013 int x,
int y, uint8_t *pred_flag,
Mv *
mv)
1017 const int refIdxLx = 0;
1020 const int min_pu_width =
fc->ps.pps->min_pu_width;
1023 int colPic =
ref->poc;
1040 const int x_ctb,
const int y_ctb,
MvField *ctr_mvf,
Mv *temp_mv)
1051 memset(temp_mv, 0,
sizeof(*temp_mv));
1054 memset(ctr_mvf, 0,
sizeof(*ctr_mvf));
1062 *temp_mv =
a1->mv[0];
1064 *temp_mv =
a1->mv[1];
1081 const int ctb_log2_size =
sps->ctb_log2_size_y;
1082 const int x0 = cu->
x0;
1083 const int y0 = cu->
y0;
1088 const int x_ctb = (x0 >> ctb_log2_size) << ctb_log2_size;
1089 const int y_ctb = (y0 >> ctb_log2_size) << ctb_log2_size;
1092 if (!
ph->r->ph_temporal_mvp_enabled_flag ||
1093 !
sps->r->sps_sbtmvp_enabled_flag ||
1105 for (
int sby = 0; sby <
mi->num_sb_y; sby++) {
1106 for (
int sbx = 0; sbx <
mi->num_sb_x; sbx++) {
1107 int x = x0 + sbx * sbw;
1108 int y = y0 + sby * sbh;
1112 memcpy(mvf.
mv, ctr_mvf.
mv,
sizeof(mvf.
mv));
1124 if (c0 &&
c1 &&
c2) {
1126 for (
int i = 0;
i < 2;
i++) {
1131 mi->mv[
i][0] = c0->
mv[
i];
1132 mi->mv[
i][1] =
c1->mv[
i];
1133 mi->mv[
i][2] =
c2->mv[
i];
1136 if (
mi->pred_flag) {
1148 if (c0 &&
c1 && c3) {
1150 for (
int i = 0;
i < 2;
i++) {
1155 mi->mv[
i][0] = c0->
mv[
i];
1156 mi->mv[
i][1] =
c1->mv[
i];
1162 if (
mi->pred_flag) {
1173 if (c0 &&
c2 && c3) {
1175 for (
int i = 0;
i < 2;
i++) {
1180 mi->mv[
i][0] = c0->
mv[
i];
1184 mi->mv[
i][2] =
c2->mv[
i];
1187 if (
mi->pred_flag) {
1198 if (
c1 &&
c2 && c3) {
1200 for (
int i = 0;
i < 2;
i++) {
1204 mi->ref_idx[
i] =
c1->ref_idx[
i];
1208 mi->mv[
i][1] =
c1->mv[
i];
1209 mi->mv[
i][2] =
c2->mv[
i];
1212 if (
mi->pred_flag) {
1213 mi->bcw_idx =
mi->pred_flag ==
PF_BI ?
c1->bcw_idx : 0;
1225 for (
int i = 0;
i < 2;
i++) {
1230 mi->mv[
i][0] = c0->
mv[
i];
1231 mi->mv[
i][1] =
c1->mv[
i];
1234 if (
mi->pred_flag) {
1249 for (
int i = 0;
i < 2;
i++) {
1254 mi->mv[
i][0] = c0->
mv[
i];
1261 if (
mi->pred_flag) {
1275 memset(
mi, 0,
sizeof(*
mi));
1297 if (
fc->ps.sps->r->sps_6param_affine_enabled_flag) {
1301 if (merge_subblock_idx == num_cands)
1306 memset(&corner3, 0,
sizeof(corner3));
1307 if (
fc->ps.ph.r->ph_temporal_mvp_enabled_flag){
1312 corner3.
pred_flag = available_l0 + (available_l1 << 1);
1319 if (merge_subblock_idx == num_cands)
1326 if (merge_subblock_idx == num_cands)
1333 if (merge_subblock_idx == num_cands)
1341 if (merge_subblock_idx == num_cands)
1347 if (merge_subblock_idx == num_cands)
1367 if (merge_subblock_idx == num_cands)
1376 if (
sps->r->sps_affine_enabled_flag) {
1381 if (merge_subblock_idx == num_cands)
1388 if (merge_subblock_idx == num_cands)
1412 const int lx,
const int8_t *ref_idx,
Mv *
mv)
1416 const int min_pu_width =
fc->ps.pps->min_pu_width;
1420 const int poc = rpl[lx].
refs[ref_idx[lx]].
poc;
1439 const int x_cand,
const int y_cand,
const int lx,
const int8_t *ref_idx,
1440 Mv *cps,
const int num_cp)
1443 int x_nb, y_nb, nbw, nbh, motion_model_idc,
available = 0;
1446 if (motion_model_idc) {
1447 const int min_pu_width =
fc->ps.pps->min_pu_width;
1452 const int poc = rpl[lx].
refs[ref_idx[lx]].
poc;
1471 const NeighbourIdx *nbs,
const int num_nbs,
const int lx,
const int8_t *ref_idx,
const int amvr_shift,
1472 Mv *cps,
const int num_cps)
1477 for (
int i = 0;
i < num_nbs;
i++) {
1485 for (
int c = 0;
c < num_cps;
c++)
1495 #define AFFINE_MVP_FROM_NBS(nbs) \
1496 mvp_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), lx, ref_idx, amvr_shift, cps, num_cp) \
1498 #define MVP_FROM_NBS(nbs) \
1499 mvp_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), lx, ref_idx, amvr_shift, mv, 1) \
1502 const int mvp_lx_flag,
const int lx,
const int8_t* ref_idx,
const int amvr_shift,
1503 Mv*
mv,
int *nb_merge_cand)
1508 int available_a, num_cands = 0;
1515 if (mvp_lx_flag == num_cands)
1522 if (mvp_lx_flag == num_cands)
1527 *nb_merge_cand = num_cands;
1532 const int mvp_lx_flag,
const int lx,
const int8_t *ref_idx,
const int amvr_shift,
1533 Mv*
mv,
int *num_cands)
1536 if (mvp_lx_flag == *num_cands) {
1547 const int mvp_lx_flag,
const int lx,
const int8_t ref_idx,
const int amvr_shift,
1548 Mv *
mv,
int num_cands)
1552 const int poc = rpl[lx].
refs[ref_idx].
poc;
1558 for (
int j = 0; j < 2; j++) {
1559 const int ly = (j ? !lx : lx);
1561 if ((
h->pred_flag &
mask) && poc == rpl[ly].
refs[
h->ref_idx[ly]].
poc) {
1562 if (mvp_lx_flag == num_cands) {
1576 const int8_t *ref_idx,
const int amvr_shift,
Mv *
mv)
1589 memset(
mv, 0,
sizeof(*
mv));
1600 mvp(lc, mvp_lx_flag[
L0],
L0,
mi->ref_idx, amvr_shift, &
mi->mv[
L0][0]);
1602 mvp(lc, mvp_lx_flag[
L1],
L1,
mi->ref_idx, amvr_shift, &
mi->mv[
L1][0]);
1609 const int min_pu_width =
fc->ps.pps->min_pu_width;
1627 if (num_cands > merge_idx)
1632 if (!num_cands || !
IS_SAME_MV(&cand_list[0], mvf->
mv)) {
1633 cand_list[num_cands++] = mvf->
mv[
L0];
1634 if (num_cands > merge_idx)
1639 *nb_merge_cand = num_cands;
1644 const int merge_idx,
Mv *cand_list,
int *nb_merge_cand)
1649 int num_cands = *nb_merge_cand;
1652 int same_motion = 0;
1654 for (
int j = 0; j < *nb_merge_cand; j++) {
1655 same_motion = is_gt4by4 &&
i == 1 &&
IS_SAME_MV(&mvf->
mv[
L0], &cand_list[j]);
1660 cand_list[num_cands++] = mvf->
mv[
L0];
1661 if (num_cands > merge_idx)
1666 *nb_merge_cand = num_cands;
1671 #define IBC_SHIFT(v) ((v) >= (1 << (MV_BITS - 1)) ? ((v) - (1 << MV_BITS)) : (v))
1690 *
mv = cand_list[merge_idx];
1695 memset(
mv, 0,
sizeof(*
mv));
1712 const NeighbourIdx *neighbour,
const int num_neighbour,
1713 const int lx,
const int8_t ref_idx,
const int amvr_shift,
Mv *cp)
1718 const int min_pu_width =
fc->ps.pps->min_pu_width;
1722 for (
int i = 0;
i < num_neighbour;
i++) {
1727 const int poc = rpl[lx].
refs[ref_idx].
poc;
1748 #define AFFINE_MVP_CONSTRUCTED_CP(cands, cp) \
1749 affine_mvp_constructed_cp(nctx, cands, FF_ARRAY_ELEMS(cands), lx, ref_idx, \
1754 const int lx,
const int8_t ref_idx,
const int amvr_shift,
1770 const Mv mv = cps[idx];
1771 for (
int j = 0; j < num_cp; j++)
1777 const int mvp_lx_flag,
const int lx,
const int8_t *ref_idx,
const int amvr_shift,
1782 const int num_cp = motion_model_idc + 1;
1790 if (mvp_lx_flag == num_cands)
1796 if (mvp_lx_flag == num_cands)
1804 if (mvp_lx_flag == num_cands)
1811 for (
int i = 2;
i >= 0;
i--) {
1813 if (mvp_lx_flag == num_cands) {
1821 if (mvp_lx_flag == num_cands) {
1823 for (
int i = 1;
i < num_cp;
i++)
1831 memset(cps, 0, num_cp *
sizeof(
Mv));
1852 const int offset = 1 << (rshift - 1);
1853 mv->x = ((
mv->x +
offset - (
mv->x >= 0)) >> rshift) * (1 << lshift);
1854 mv->y = ((
mv->y +
offset - (
mv->y >= 0)) >> rshift) * (1 << lshift);
1856 mv->x =
mv->x * (1 << lshift);
1857 mv->y =
mv->y * (1 << lshift);
1863 mv->x =
av_clip(
mv->x, -(1 << 17), (1 << 17) - 1);
1864 mv->y =
av_clip(
mv->y, -(1 << 17), (1 << 17) - 1);
1870 const uint8_t plevel =
fc->ps.sps->log2_parallel_merge_level;
1872 return x0_br >> plevel > x0 >> plevel &&
1873 y0_br >> plevel > y0 >> plevel;
1880 for (
i = 0;
i < *num_hmvp;
i++) {
1891 memmove(hmvp +
i, hmvp +
i + 1, (*num_hmvp -
i) *
sizeof(
MvField));
1892 hmvp[(*num_hmvp)++] = *mvf;
1906 const int min_pu_width =
fc->ps.pps->min_pu_width;
1923 const int min_pu_width =
fc->ps.pps->min_pu_width;
static int mv_merge_temporal_candidate(const VVCLocalContext *lc, MvField *cand)
static int affine_mvp_constructed_cp(NeighbourContext *ctx, const NeighbourIdx *neighbour, const int num_neighbour, const int lx, const int8_t ref_idx, const int amvr_shift, Mv *cp)
static av_always_inline int is_greater_mer(const VVCFrameContext *fc, const int x0, const int y0, const int x0_br, const int y0_br)
F H1 F F H1 F F F F H1<-F-------F-------F v v v H2 H3 H2 ^ ^ ^ F-------F-------F-> H1<-F-------F-------F|||||||||F H1 F|||||||||F H1 Funavailable fullpel samples(outside the picture for example) shall be equalto the closest available fullpel sampleSmaller pel interpolation:--------------------------if diag_mc is set then points which lie on a line between 2 vertically, horizontally or diagonally adjacent halfpel points shall be interpolatedlinearly with rounding to nearest and halfway values rounded up.points which lie on 2 diagonals at the same time should only use the onediagonal not containing the fullpel point F--> O q O<--h1-> O q O<--F v \/v \/v O O O O O O O|/|\|q q q q q|/|\|O O O O O O O ^/\ ^/\ ^ h2--> O q O<--h3-> O q O<--h2 v \/v \/v O O O O O O O|\|/|q q q q q|\|/|O O O O O O O ^/\ ^/\ ^ F--> O q O<--h1-> O q O<--Fthe remaining points shall be bilinearly interpolated from theup to 4 surrounding halfpel and fullpel points, again rounding should be tonearest and halfway values rounded upcompliant Snow decoders MUST support 1-1/8 pel luma and 1/2-1/16 pel chromainterpolation at leastOverlapped block motion compensation:-------------------------------------FIXMELL band prediction:===================Each sample in the LL0 subband is predicted by the median of the left, top andleft+top-topleft samples, samples outside the subband shall be considered tobe 0. To reverse this prediction in the decoder apply the following.for(y=0;y< height;y++){ for(x=0;x< width;x++){ sample[y][x]+=median(sample[y-1][x], sample[y][x-1], sample[y-1][x]+sample[y][x-1]-sample[y-1][x-1]);}}sample[-1][ *]=sample[ *][-1]=0;width, height here are the width and height of the LL0 subband not of the finalvideoDequantization:===============FIXMEWavelet Transform:==================Snow supports 2 wavelet transforms, the symmetric biorthogonal 5/3 integertransform and an integer approximation of the symmetric biorthogonal 9/7daubechies wavelet.2D IDWT(inverse discrete wavelet transform) --------------------------------------------The 2D IDWT applies a 2D filter recursively, each time combining the4 lowest frequency subbands into a single subband until only 1 subbandremains.The 2D filter is done by first applying a 1D filter in the vertical directionand then applying it in the horizontal one. --------------- --------------- --------------- ---------------|LL0|HL0|||||||||||||---+---|HL1||L0|H0|HL1||LL1|HL1|||||LH0|HH0|||||||||||||-------+-------|-> L1 H1 LH1 HH1 LH1 HH1 LH1 HH1 L1
static int sb_temporal_merge_candidate(const VVCLocalContext *lc, NeighbourContext *nctx, PredictionUnit *pu)
int ff_vvc_no_backward_pred_flag(const VVCLocalContext *lc)
#define MVP_FROM_NBS(nbs)
static int is_fallback_mode(const SubblockParams *sp, const PredFlag pred_flag)
const int8_t ff_vvc_gpm_distance_lut[VVC_GPM_NUM_ANGLES]
const uint8_t ff_vvc_gpm_distance_idx[VVC_GPM_NUM_PARTITION]
static const int8_t mv[256][2]
#define AFFINE_MVP_CONSTRUCTED_CP(cands, cp)
uint8_t gpm_partition_idx
#define AFFINE_MVP_FROM_NBS(nbs)
void ff_vvc_luma_mv_merge_mode(VVCLocalContext *lc, const int merge_idx, const int ciip_flag, MvField *mv)
static int affine_merge_const5(const MvField *c0, const MvField *c1, MotionInfo *mi)
void ff_vvc_store_mv(const VVCLocalContext *lc, const MotionInfo *mi)
static av_always_inline int is_same_mer(const VVCFrameContext *fc, const int xN, const int yN, const int xP, const int yP)
static int FUNC() ph(CodedBitstreamContext *ctx, RWContext *rw, H266RawPH *current)
#define MAX_NUM_HMVP_CANDS
static void affine_merge_zero_motion(const VVCLocalContext *lc, MotionInfo *mi)
int16_t y
vertical component of motion vector
static void affine_cps_from_nb(const VVCLocalContext *lc, const int x_nb, int y_nb, const int nbw, const int nbh, const int lx, Mv *cps, int num_cps)
const H266RawSliceHeader * r
RefStruct reference.
static int affine_merge_const1(const MvField *c0, const MvField *c1, const MvField *c2, MotionInfo *mi)
static int mvp_history_candidates(const VVCLocalContext *lc, const int mvp_lx_flag, const int lx, const int8_t ref_idx, const int amvr_shift, Mv *mv, int num_cands)
#define fc(width, name, range_min, range_max)
static void derive_subblock_diff_mvs(const VVCLocalContext *lc, PredictionUnit *pu, const SubblockParams *sp, const int lx)
static void affine_mvp(const VVCLocalContext *lc, const int mvp_lx_flag, const int lx, const int8_t *ref_idx, const int amvr_shift, MotionModelIdc motion_model_idc, Mv *cps)
static int mvp_from_nbs(NeighbourContext *ctx, const NeighbourIdx *nbs, const int num_nbs, const int lx, const int8_t *ref_idx, const int amvr_shift, Mv *cps, const int num_cps)
static void FUNC() dmvr(int16_t *dst, const uint8_t *_src, const ptrdiff_t _src_stride, const int height, const intptr_t mx, const intptr_t my, const int width)
void ff_vvc_mvp_ibc(VVCLocalContext *lc, const int mvp_l0_flag, const int amvr_shift, Mv *mv)
void ff_vvc_sb_mv_merge_mode(VVCLocalContext *lc, const int merge_subblock_idx, PredictionUnit *pu)
void ff_vvc_clip_mv(Mv *mv)
static void init_subblock_params(SubblockParams *sp, const MotionInfo *mi, const int cb_width, const int cb_height, const int lx)
static void init_neighbour_context(NeighbourContext *ctx, const VVCLocalContext *lc)
const VVCSPS * sps
RefStruct reference.
static int affine_merge_const6(const MvField *c0, const MvField *c2, const int cb_width, const int cb_height, MotionInfo *mi)
static double b1(void *priv, double x, double y)
void ff_vvc_luma_mv_merge_ibc(VVCLocalContext *lc, const int merge_idx, Mv *mv)
static int is_a0_available(const VVCLocalContext *lc, const CodingUnit *cu)
static const MvField * mv_merge_from_nb(NeighbourContext *ctx, const NeighbourIdx nb)
static int mv_merge_history_candidates(const VVCLocalContext *lc, const int merge_idx, const MvField **nb_list, MvField *cand_list, int *num_cands)
static int affine_merge_const2(const MvField *c0, const MvField *c1, const MvField *c3, MotionInfo *mi)
static int affine_mvp_const1(NeighbourContext *nctx, const int lx, const int8_t ref_idx, const int amvr_shift, Mv *cps, int *available)
MvField * ff_vvc_get_mvf(const VVCFrameContext *fc, const int x0, const int y0)
#define MRG_MAX_NUM_CANDS
static void mv_merge_zero_motion_candidate(const VVCLocalContext *lc, const int merge_idx, MvField *cand_list, int num_cands)
static int derive_temporal_colocated_mvs(const VVCLocalContext *lc, MvField temp_col, int refIdxLx, Mv *mvLXCol, int X, int colPic, const RefPicList *refPicList_col, int sb_flag)
s EdgeDetect Foobar g libavfilter vf_edgedetect c libavfilter vf_foobar c edit libavfilter and add an entry for foobar following the pattern of the other filters edit libavfilter allfilters and add an entry for foobar following the pattern of the other filters configure make j< whatever > ffmpeg ffmpeg i you should get a foobar png with Lena edge detected That s your new playground is ready Some little details about what s going which in turn will define variables for the build system and the C
#define FF_ARRAY_ELEMS(a)
VVCRefPic refs[VVC_MAX_REF_ENTRIES]
static const uint16_t mask[17]
static int check_mvset(Mv *mvLXCol, Mv *mvCol, int colPic, int poc, const RefPicList *refPicList, int X, int refIdxLx, const RefPicList *refPicList_col, int listCol, int refidxCol)
#define DERIVE_TEMPORAL_COLOCATED_MVS(sb_flag)
static void ibc_merge_candidates(VVCLocalContext *lc, const int merge_idx, Mv *mv)
static const MvField * derive_corner_mvf(NeighbourContext *ctx, const NeighbourIdx *neighbour, const int num_neighbour)
static void affine_mvp_const2(const int idx, Mv *cps, const int num_cp)
static int derive_cb_prof_flag_lx(const VVCLocalContext *lc, const PredictionUnit *pu, int lx, int is_fallback)
void ff_vvc_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift, MotionInfo *mi)
static av_always_inline void sb_clip_location(const VVCLocalContext *lc, const int x_ctb, const int y_ctb, const Mv *temp_mv, int *x, int *y)
void ff_vvc_store_mvf(const VVCLocalContext *lc, const MvField *mvf)
static av_always_inline int compare_pf_ref_idx(const MvField *A, const struct MvField *B, const struct MvField *C, const int lx)
const uint8_t ff_vvc_gpm_angle_idx[VVC_GPM_NUM_PARTITION]
static int mvp_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand, const int lx, const int8_t *ref_idx, Mv *mv)
static int temporal_luma_motion_vector(const VVCLocalContext *lc, const int refIdxLx, Mv *mvLXCol, const int X, int check_center, int sb_flag)
#define LOCAL_ALIGNED_8(t, v,...)
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
static int compare_l0_mv(const MvField *n, const MvField *o)
void ff_vvc_store_gpm_mvf(const VVCLocalContext *lc, const PredictionUnit *pu)
static int ibc_history_candidates(const VVCLocalContext *lc, const int merge_idx, Mv *cand_list, int *nb_merge_cand)
static av_always_inline void mv_compression(Mv *motion)
static int affine_merge_const4(const MvField *c1, const MvField *c2, const MvField *c3, MotionInfo *mi)
void ff_vvc_update_hmvp(VVCLocalContext *lc, const MotionInfo *mi)
int is_scaled
RprConstraintsActiveFlag.
uint8_t ciip_flag
ciip_flag
int16_t x
horizontal component of motion vector
const H266RawPictureHeader * r
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
#define SAMPLE_CTB(tab, x, y)
Neighbour neighbours[NUM_NBS]
int num_hmvp_ibc
NumHmvpIbcCand.
static int shift(int a, int b)
const VVCLocalContext * lc
static int affine_merge_const_candidates(const VVCLocalContext *lc, MotionInfo *mi, NeighbourContext *nctx, const int merge_subblock_idx, int num_cands)
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)
#define AFFINE_MIN_BLOCK_SIZE
void ff_vvc_round_mv(Mv *mv, const int lshift, const int rshift)
int16_t diff_mv_x[2][AFFINE_MIN_BLOCK_SIZE *AFFINE_MIN_BLOCK_SIZE]
diffMvLX
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
#define MAX_CONTROL_POINTS
static void sb_temproal_luma_motion(const VVCLocalContext *lc, const int x_ctb, const int y_ctb, const Mv *temp_mv, int x, int y, uint8_t *pred_flag, Mv *mv)
static int check_available(Neighbour *n, const VVCLocalContext *lc, const int check_mer)
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
void ff_vvc_store_sb_mvs(const VVCLocalContext *lc, PredictionUnit *pu)
static av_always_inline PredMode pred_flag_to_mode(PredFlag pred)
void ff_vvc_luma_mv_merge_gpm(VVCLocalContext *lc, const int merge_gpm_idx[2], MvField *mv)
uint8_t hpel_if_idx
hpelIfIdx
static void update_hmvp(MvField *hmvp, int *num_hmvp, const MvField *mvf, int(*compare)(const MvField *n, const MvField *o))
static int mvp_temporal_candidates(const VVCLocalContext *lc, const int mvp_lx_flag, const int lx, const int8_t *ref_idx, const int amvr_shift, Mv *mv, int *num_cands)
MvField hmvp[MAX_NUM_HMVP_CANDS]
HmvpCandList.
#define i(width, name, range_min, range_max)
static av_always_inline av_const double round(double x)
static av_always_inline int compare_mv_ref_idx(const MvField *n, const MvField *o)
static int mvp_spatial_candidates(const VVCLocalContext *lc, const int mvp_lx_flag, const int lx, const int8_t *ref_idx, const int amvr_shift, Mv *mv, int *nb_merge_cand)
int32_t poc
PicOrderCntVal.
static int sb_mv_merge_mode(const VVCLocalContext *lc, const int merge_subblock_idx, PredictionUnit *pu)
static int mv_merge_spatial_candidates(const VVCLocalContext *lc, const int merge_idx, const MvField **nb_list, MvField *cand_list, int *nb_merge_cand)
static int affine_merge_from_nbs(NeighbourContext *ctx, const NeighbourIdx *nbs, const int num_nbs, MotionInfo *cand)
static int affine_merge_const3(const MvField *c0, const MvField *c2, const MvField *c3, MotionInfo *mi)
#define TAB_CP_MV(lx, x, y)
static int mv_merge_pairwise_candidate(MvField *cand_list, const int num_cands, const int is_b)
static const float pred[4]
static int FUNC() sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
static void store_cp_mv(const VVCLocalContext *lc, const MotionInfo *mi, const int lx)
uint8_t inter_affine_flag
void ff_vvc_set_neighbour_available(VVCLocalContext *lc, const int x0, const int y0, const int w, const int h)
#define AFFINE_MERGE_FROM_NBS(nbs)
static float compare(const AVFrame *haystack, const AVFrame *obj, int offx, int offy)
void ff_vvc_set_mvf(const VVCLocalContext *lc, const int x0, const int y0, const int w, const int h, const MvField *mvf)
#define DERIVE_CORNER_MV(nbs)
static int sb_temporal_luma_motion_data(const VVCLocalContext *lc, const MvField *a1, const int x_ctb, const int y_ctb, MvField *ctr_mvf, Mv *temp_mv)
enum PredMode pred_mode
PredMode.
static int affine_mvp_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand, const int lx, const int8_t *ref_idx, Mv *cps, const int num_cp)
static int ref[MAX_W *MAX_W]
static void ibc_add_mvp(Mv *mv, Mv *mvp, const int amvr_shift)
int16_t diff_mv_y[2][AFFINE_MIN_BLOCK_SIZE *AFFINE_MIN_BLOCK_SIZE]
diffMvLX
static const MvField * mv_merge_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand)
MvField hmvp_ibc[MAX_NUM_HMVP_CANDS]
HmvpIbcCandList.
int8_t ref_idx[2]
refIdxL0, refIdxL1
static int ibc_spatial_candidates(const VVCLocalContext *lc, const int merge_idx, Mv *const cand_list, int *nb_merge_cand)
void ff_vvc_affine_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift, MotionInfo *mi)
static void mvp(const VVCLocalContext *lc, const int mvp_lx_flag, const int lx, const int8_t *ref_idx, const int amvr_shift, Mv *mv)
static int affine_neighbour_cb(const VVCFrameContext *fc, const int x_nb, const int y_nb, int *x_cb, int *y_cb, int *cbw, int *cbh)
void ff_vvc_set_intra_mvf(const VVCLocalContext *lc, const int dmvr)
static void mv_merge_mode(const VVCLocalContext *lc, const int merge_idx, MvField *cand_list)
#define MV_MERGE_FROM_NB(nb)
static int affine_merge_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand, MotionInfo *mi)
void ff_vvc_mv_scale(Mv *dst, const Mv *src, int td, int tb)