Go to the documentation of this file.
30 #define PROF_TEMP_OFFSET (MAX_PB_SIZE + 32)
37 const int hs =
sps->hshift[is_chroma];
38 const int vs =
sps->vshift[is_chroma];
40 r->l =
pps->subpic_x[subpic_idx] >> hs;
41 r->t =
pps->subpic_y[subpic_idx] >> vs;
42 r->r =
r->l + (
pps->subpic_width[subpic_idx] >> hs);
43 r->b =
r->t + (
pps->subpic_height[subpic_idx] >> vs);
49 const int l = dmvr_clip ?
FFMIN(
FFMAX(subpic->
l, sb->
l), subpic->
r - 1) : subpic->
l;
50 const int t = dmvr_clip ?
FFMIN(
FFMAX(subpic->
t, sb->
t), subpic->
b - 1) : subpic->
t;
51 const int r = dmvr_clip ?
FFMAX(
FFMIN(subpic->
r, sb->
r), subpic->
l + 1) : subpic->
r;
52 const int b = dmvr_clip ?
FFMAX(
FFMIN(subpic->
b, sb->
b), subpic->
t + 1) : subpic->
b;
61 const uint8_t **
src, ptrdiff_t *src_stride,
62 int x_off,
int y_off,
const int block_w,
const int block_h,
63 const int extra_before,
const int extra_after,
67 const int extra = extra_before + extra_after;
68 int pic_width, pic_height;
70 *
src += y_off * *src_stride + (x_off * (1 <<
fc->ps.sps->pixel_shift));
72 clip_to_subpic(&x_off, &y_off, &pic_width, &pic_height, subpic, sb, dmvr_clip);
74 if (dmvr_clip || x_off < extra_before || y_off < extra_before ||
75 x_off >= pic_width - block_w - extra_after ||
76 y_off >= pic_height - block_h - extra_after) {
77 const int ps =
fc->ps.sps->pixel_shift;
79 const int offset = extra_before * *src_stride + (extra_before << ps);
80 const int buf_offset = extra_before * edge_emu_stride + (extra_before << ps);
82 fc->vdsp.emulated_edge_mc(
dst, *
src -
offset, edge_emu_stride, *src_stride,
83 block_w + extra, block_h + extra, x_off - extra_before, y_off - extra_before,
84 pic_width, pic_height);
87 *src_stride = edge_emu_stride;
92 const uint8_t *
src,
const ptrdiff_t src_stride,
const int ps,
93 int x_off,
int y_off,
const int block_w,
const int block_h,
97 int pic_width, pic_height;
99 src += y_off * src_stride + x_off * (1 << ps);
101 clip_to_subpic(&x_off, &y_off, &pic_width, &pic_height, subpic, half_sb, dmvr_clip);
103 fc->vdsp.emulated_edge_mc(
dst,
src, dst_stride, src_stride,
104 block_w, block_h, x_off, y_off, pic_width, pic_height);
119 const uint8_t **
src, ptrdiff_t *src_stride,
const VVCFrame *src_frame,
120 int x_sb,
int y_sb,
int x_off,
int y_off,
int block_w,
int block_h,
const int wrap_enabled,
121 const int is_chroma,
const int extra_before,
const int extra_after)
125 const int ps =
sps->pixel_shift;
127 const int extra = extra_before + extra_after;
128 const int dmvr_clip = x_sb != x_off || y_sb != y_off;
129 const int dmvr_left =
FFMAX(x_off, x_sb) - extra_before;
130 const int dmvr_right =
FFMIN(x_off, x_sb) + block_w + extra_after;
131 const int left = x_off - extra_before;
132 const int top = y_off - extra_before;
133 const int pic_width =
pps->width >>
sps->hshift[is_chroma];
134 const int wrap =
pps->ref_wraparound_offset << (
sps->min_cb_log2_size_y -
sps->hshift[is_chroma]);
136 VVCRect sb = { x_sb - extra_before, y_sb - extra_before, x_sb + block_w + extra_after, y_sb + block_h + extra_after };
141 if (!wrap_enabled || (dmvr_left >= 0 && dmvr_right <= pic_width)) {
143 x_off, y_off, block_w, block_h, extra_before, extra_after, &subpic, &sb, dmvr_clip);
146 if (dmvr_right <= 0) {
149 x_off +
wrap, y_off, block_w, block_h, extra_before, extra_after, &subpic, &sb, dmvr_clip);
152 if (dmvr_left >= pic_width) {
155 x_off -
wrap, y_off, block_w, block_h, extra_before, extra_after, &subpic, &sb, dmvr_clip);
163 if (dmvr_left < 0 ) {
167 left +
wrap, top,
w, block_h, &subpic, &half_sb, dmvr_clip);
171 0, top, block_w -
w, block_h, &subpic, &half_sb, dmvr_clip);
173 const int w = pic_width -
left;
174 VVCRect half_sb = { sb.
l, sb.
t, pic_width, sb.
b };
176 left, top,
w, block_h, &subpic, &half_sb, dmvr_clip);
180 pic_width -
wrap , top, block_w -
w, block_h, &subpic, &half_sb, dmvr_clip);
183 *
src =
dst + extra_before * dst_stride + (extra_before << ps);
184 *src_stride = dst_stride;
187 #define MC_EMULATED_EDGE(dst, src, src_stride, x_off, y_off) \
188 emulated_edge(lc, dst, src, src_stride, ref, x_off, y_off, x_off, y_off, block_w, block_h, wrap_enabled, is_chroma, \
189 is_chroma ? CHROMA_EXTRA_BEFORE : LUMA_EXTRA_BEFORE, is_chroma ? CHROMA_EXTRA_AFTER : LUMA_EXTRA_AFTER)
191 #define MC_EMULATED_EDGE_DMVR(dst, src, src_stride, x_sb, y_sb, x_off, y_off) \
192 emulated_edge(lc, dst, src, src_stride, ref, x_sb, y_sb, x_off, y_off, block_w, block_h, wrap_enabled, is_chroma, \
193 is_chroma ? CHROMA_EXTRA_BEFORE : LUMA_EXTRA_BEFORE, is_chroma ? CHROMA_EXTRA_AFTER : LUMA_EXTRA_AFTER)
195 #define MC_EMULATED_EDGE_BILINEAR(dst, src, src_stride, x_off, y_off) \
196 emulated_edge(lc, dst, src, src_stride, ref, x_off, y_off, x_off, y_off, pred_w, pred_h, wrap_enabled, 0, \
197 BILINEAR_EXTRA_BEFORE, BILINEAR_EXTRA_AFTER)
206 const int weight_flag = (
IS_P(sh->
r) &&
pps->r->pps_weighted_pred_flag) ||
207 (
IS_B(sh->
r) &&
pps->r->pps_weighted_bipred_flag);
212 *denom =
w->log2_denom[c_idx > 0];
213 *wx =
w->weight[lx][c_idx][mvf->
ref_idx[lx]];
214 *ox =
w->offset[lx][c_idx][mvf->
ref_idx[lx]];
227 const int bcw_idx = mvf->
bcw_idx;
229 const int weight_flag =
pps->r->pps_weighted_bipred_flag && !dmvr_flag;
230 if ((!weight_flag && !bcw_idx) || (bcw_idx && lc->
cu->
ciip_flag)) {
235 int denom, w0, w1, o1, o2;
244 denom =
w->log2_denom[c_idx > 0];
250 fc->vvcdsp.inter.w_avg(
dst, dst_stride,
src0,
src1,
width,
height, denom, w0, w1, o1, o2);
253 #define INTER_FILTER(t, frac) (is_chroma ? ff_vvc_inter_chroma_filters[t][frac] : ff_vvc_inter_luma_filters[t][frac])
256 int x_off,
int y_off,
const int block_w,
const int block_h,
const int c_idx)
260 const uint8_t *
src =
ref->frame->data[c_idx];
261 ptrdiff_t src_stride =
ref->frame->linesize[c_idx];
262 const int is_chroma = !!c_idx;
263 const int hs =
fc->ps.sps->hshift[c_idx];
264 const int vs =
fc->ps.sps->vshift[c_idx];
265 const int idx =
av_log2(block_w) - 1;
271 const int wrap_enabled =
fc->ps.pps->r->pps_ref_wraparound_enabled_flag;
273 x_off +=
mv->x >> (4 + hs);
274 y_off +=
mv->y >> (4 + vs);
277 fc->vvcdsp.inter.put[is_chroma][idx][!!
my][!!
mx](
dst,
src, src_stride, block_h,
hf,
vf, block_w);
281 const VVCFrame *
ref,
const MvField *mvf,
int x_off,
int y_off,
const int block_w,
const int block_h,
286 const uint8_t *
src =
ref->frame->data[c_idx];
287 ptrdiff_t src_stride =
ref->frame->linesize[c_idx];
289 const int hs =
fc->ps.sps->hshift[c_idx];
290 const int vs =
fc->ps.sps->vshift[c_idx];
291 const int idx =
av_log2(block_w) - 1;
292 const Mv *
mv = &mvf->
mv[lx];
293 const int is_chroma = !!c_idx;
299 const int wrap_enabled =
fc->ps.pps->r->pps_ref_wraparound_enabled_flag;
302 x_off +=
mv->x >> (4 + hs);
303 y_off +=
mv->y >> (4 + vs);
307 fc->vvcdsp.inter.put_uni_w[is_chroma][idx][!!
my][!!
mx](
dst, dst_stride,
src, src_stride,
308 block_h, denom, wx, ox,
hf,
vf, block_w);
310 fc->vvcdsp.inter.put_uni[is_chroma][idx][!!
my][!!
mx](
dst, dst_stride,
src, src_stride,
311 block_h,
hf,
vf, block_w);
317 const int x_off,
const int y_off,
const int block_w,
const int block_h,
const int c_idx,
318 const int sb_bdof_flag)
322 const int hs =
fc->ps.sps->hshift[c_idx];
323 const int vs =
fc->ps.sps->vshift[c_idx];
324 const int idx =
av_log2(block_w) - 1;
325 const VVCFrame *refs[] = { ref0, ref1 };
327 const int is_chroma = !!c_idx;
330 for (
int i =
L0;
i <=
L1;
i++) {
334 const int ox = x_off + (
mv->x >> (4 + hs));
335 const int oy = y_off + (
mv->y >> (4 + vs));
337 ptrdiff_t src_stride =
ref->frame->linesize[c_idx];
338 const uint8_t *
src =
ref->frame->data[c_idx];
341 const int wrap_enabled =
fc->ps.pps->r->pps_ref_wraparound_enabled_flag;
344 const int x_sb = x_off + (orig_mv->
mv[
i].
x >> (4 + hs));
345 const int y_sb = y_off + (orig_mv->
mv[
i].
y >> (4 + vs));
351 fc->vvcdsp.inter.put[is_chroma][idx][!!
my][!!
mx](
tmp[
i],
src, src_stride, block_h,
hf,
vf, block_w);
353 fc->vvcdsp.inter.bdof_fetch_samples(
tmp[
i],
src, src_stride,
mx,
my, block_w, block_h);
356 fc->vvcdsp.inter.apply_bdof(
dst, dst_stride,
tmp[
L0],
tmp[
L1], block_w, block_h);
364 #define SCALE_THRESHOLD_1 20480
365 #define SCALE_THRESHOLD_2 28672
377 #define INTER_FILTER_SCALED(scale) inter_filter_scaled(scale, is_chroma, is_affine)
379 #define SCALED_CHROMA_ADDIN(scale, collocated_flag) (is_chroma ? (collocated_flag ? 0 : 8 * (scale - (1 << 14))) : 0)
380 #define SCALED_REF_SB(off, scaling_off, ref_mv, scale, add, shift) ((((off - (scaling_off << shift)) << (4 + shift)) + ref_mv) * scale + add)
381 #define SCALED_REF(ref_sb, offset, shift) (FFSIGN(ref_sb) * ((FFABS(ref_sb) + (128 << is_chroma)) >> (8 + is_chroma)) + (offset << (10 - shift)) + (32 >> is_chroma))
382 #define SCALED_STEP(scale) ((scale + 8) >> 4)
385 int *x,
int *y,
int *dx,
int *dy)
389 const int is_chroma = !!c_idx;
390 const int hs =
sps->hshift[c_idx];
391 const int vs =
sps->vshift[c_idx];
392 const int left_offset =
fc->ref->scaling_win.left_offset;
393 const int top_offset =
fc->ref->scaling_win.top_offset;
406 const VVCFrame *
ref,
const int x,
const int y,
const int dx,
const int dy,
const int w,
const int h,
const int is_chroma)
414 const int block_w = x_end - x_off + (x_end == x_last);
415 const int block_h = *src_height = y_end - y_off + (y_end == y_last);
416 const int wrap_enabled = 0;
422 int x_off,
int y_off,
const int block_w,
const int block_h,
const int c_idx)
429 const int is_chroma = !!c_idx;
430 const int idx =
av_log2(block_w) - 1;
433 int x, y, dx, dy, src_height;
436 emulated_edge_scaled(lc, &
src, &src_stride, &src_height, refp->
ref, x, y, dx, dy, block_w, block_h, is_chroma);
437 fc->vvcdsp.inter.put_scaled[is_chroma][idx](
dst,
src, src_stride, src_height, x, y, dx, dy, block_h,
hf,
vf, block_w);
441 const MvField *mvf,
const int x_off,
const int y_off,
const int block_w,
const int block_h,
const int c_idx)
448 const Mv *
mv = &mvf->
mv[lx];
450 const int is_chroma = !!c_idx;
451 const int idx =
av_log2(block_w) - 1;
454 int denom, wx, ox, x, y, dx, dy, src_height;
457 emulated_edge_scaled(lc, &
src, &src_stride, &src_height, refp->
ref, x, y, dx, dy, block_w, block_h, is_chroma);
460 fc->vvcdsp.inter.put_uni_w_scaled[is_chroma][idx](
dst, dst_stride,
src, src_stride, src_height,
461 x, y, dx, dy, block_h, denom, wx, ox,
hf,
vf, block_w);
463 fc->vvcdsp.inter.put_uni_scaled[is_chroma][idx](
dst, dst_stride,
src, src_stride, src_height,
464 x, y, dx, dy, block_h,
hf,
vf, block_w);
470 const int x_off,
const int y_off,
const int block_w,
const int block_h,
const int c_idx)
472 const VVCRefPic *refps[] = { refp0, refp1 };
475 for (
int i =
L0;
i <=
L1;
i++) {
480 mc_scaled(lc,
tmp[
i], refp,
mv, x_off, y_off, block_w, block_h, c_idx);
482 mc(lc,
tmp[
i], refp->
ref,
mv, x_off, y_off, block_w, block_h, c_idx);
489 const VVCFrame *
ref,
const MvField *mvf,
int x_off,
int y_off,
const int block_w,
const int block_h,
490 const int cb_prof_flag,
const int16_t *diff_mv_x,
const int16_t *diff_mv_y)
494 ptrdiff_t src_stride =
ref->frame->linesize[
LUMA];
496 const int idx =
av_log2(block_w) - 1;
498 const Mv *
mv = mvf->
mv + lx;
499 const int mx =
mv->x & 0xf;
500 const int my =
mv->y & 0xf;
505 const int wrap_enabled =
fc->ps.pps->r->pps_ref_wraparound_enabled_flag;
506 const int is_chroma = 0;
514 fc->vvcdsp.inter.fetch_samples(prof_tmp,
src, src_stride,
mx,
my);
516 fc->vvcdsp.inter.apply_prof_uni(
dst, dst_stride, prof_tmp, diff_mv_x, diff_mv_y);
518 fc->vvcdsp.inter.apply_prof_uni_w(
dst, dst_stride, prof_tmp, diff_mv_x, diff_mv_y, denom, wx, ox);
521 fc->vvcdsp.inter.put_uni[
LUMA][idx][!!
my][!!
mx](
dst, dst_stride,
src, src_stride, block_h,
hf,
vf, block_w);
523 fc->vvcdsp.inter.put_uni_w[
LUMA][idx][!!
my][!!
mx](
dst, dst_stride,
src, src_stride, block_h, denom, wx, ox,
hf,
vf, block_w);
528 const Mv *
mv ,
const int x_off,
const int y_off,
const int block_w,
const int block_h,
const int lx)
532 const int mx =
mv->x & 0xf;
533 const int my =
mv->y & 0xf;
534 const int ox = x_off + (
mv->x >> 4);
535 const int oy = y_off + (
mv->y >> 4);
536 const int idx =
av_log2(block_w) - 1;
537 const int is_chroma = 0;
539 ptrdiff_t src_stride =
ref->frame->linesize[
LUMA];
543 const int wrap_enabled =
fc->ps.pps->r->pps_ref_wraparound_enabled_flag;
550 fc->vvcdsp.inter.fetch_samples(prof_tmp,
src, src_stride,
mx,
my);
557 const int block_w,
const int block_h)
559 const VVCRefPic *refps[] = { ref0, ref1 };
562 for (
int i =
L0;
i <=
L1;
i++) {
580 if (
mv->pred_flag &
mask) {
582 refp[lx] = rpl[lx].
refs +
mv->ref_idx[lx];
590 #define POS(c_idx, x, y) \
591 &fc->frame->data[c_idx][((y) >> fc->ps.sps->vshift[c_idx]) * fc->frame->linesize[c_idx] + \
592 (((x) >> fc->ps.sps->hshift[c_idx]) << fc->ps.sps->pixel_shift)]
609 const int c_end =
fc->ps.sps->r->sps_chroma_format_idc ? 3 : 1;
613 for (
int c_idx = 0; c_idx < c_end; c_idx++) {
614 const int hs =
fc->ps.sps->hshift[c_idx];
615 const int vs =
fc->ps.sps->vshift[c_idx];
616 const int x = lc->
cu->
x0 >> hs;
617 const int y = lc->
cu->
y0 >> vs;
621 ptrdiff_t dst_stride =
fc->frame->linesize[c_idx];
623 int step_x = 1 << hs;
627 }
else if (mirror_type == 1) {
635 for (
int i = 0;
i < 2;
i++) {
637 const int lx =
mv->pred_flag -
PF_L0;
661 const int min_pu_width =
fc->ps.pps->min_pu_width;
674 const int x0,
const int y0,
const int sbw,
const int sbh,
const int sb_bdof_flag,
const int c_start)
677 const int c_end =
fc->ps.sps->r->sps_chroma_format_idc ?
CR :
LUMA;
683 for (
int c_idx = c_start; c_idx <= c_end; c_idx++) {
684 uint8_t *
dst =
POS(c_idx, x0, y0);
685 const ptrdiff_t dst_stride =
fc->frame->linesize[c_idx];
686 const int hs =
fc->ps.sps->hshift[c_idx];
687 const int vs =
fc->ps.sps->vshift[c_idx];
688 const int x = x0 >> hs;
689 const int y = y0 >> vs;
690 const int w = sbw >> hs;
691 const int h = sbh >> vs;
692 const int is_luma = !c_idx;
693 const int do_ciip = lc->
cu->
ciip_flag && (is_luma || (
w > 2));
694 uint8_t *inter = do_ciip ? (uint8_t *)lc->
ciip_tmp :
dst;
695 const ptrdiff_t inter_stride = do_ciip ? (
MAX_PB_SIZE *
sizeof(uint16_t)) : dst_stride;
696 const int do_bdof = is_luma && sb_bdof_flag;
701 if (refp[lx]->is_scaled) {
705 mc_uni(lc, inter, inter_stride, refp[lx]->
ref, mvf,
709 if (refp[
L0]->is_scaled || refp[
L1]->is_scaled) {
713 mc_bi(lc, inter, inter_stride, refp[
L0]->
ref, refp[
L1]->
ref, mvf, orig_mvf,
714 x, y,
w,
h, c_idx, do_bdof);
719 fc->vvcdsp.intra.intra_pred(lc, x0, y0, sbw, sbh, c_idx);
721 fc->vvcdsp.lmcs.filter(inter, inter_stride,
w,
h, &
fc->ps.lmcs.fwd_lut);
722 fc->vvcdsp.inter.put_ciip(
dst, dst_stride,
w,
h, inter, inter_stride, intra_weight);
730 const int sad_minus = sad[-
stride];
731 const int sad_center = sad[0];
732 const int sad_plus = sad[
stride];
734 int denom = (( sad_minus + sad_plus) - (sad_center << 1 ) ) << 3;
738 if (sad_minus == sad_center)
740 else if (sad_plus == sad_center)
743 int num = ( sad_minus - sad_plus ) * (1 << 4);
751 while (counter > 0) {
752 counter = counter - 1;
753 quotient = quotient << 1;
754 if ( num >= denom ) {
756 quotient = quotient + 1;
758 denom = (denom >> 1);
769 #define SAD_ARRAY_SIZE 5
772 const VVCFrame *ref0,
const VVCFrame *ref1,
const int x_off,
const int y_off,
const int block_w,
const int block_h)
775 const int sr_range = 2;
776 const VVCFrame *refs[] = { ref0, ref1 };
779 int min_dx, min_dy, min_sad, dx, dy;
782 min_dx = min_dy = dx = dy = 2;
784 for (
int i =
L0;
i <=
L1;
i++) {
785 const int pred_w = block_w + 2 * sr_range;
786 const int pred_h = block_h + 2 * sr_range;
788 const int mx =
mv->x & 0xf;
789 const int my =
mv->y & 0xf;
790 const int ox = x_off + (
mv->x >> 4) - sr_range;
791 const int oy = y_off + (
mv->y >> 4) - sr_range;
793 ptrdiff_t src_stride =
ref->frame->linesize[
LUMA];
795 const int wrap_enabled =
fc->ps.pps->r->pps_ref_wraparound_enabled_flag;
801 min_sad =
fc->vvcdsp.inter.sad(
tmp[
L0],
tmp[
L1], dx, dy, block_w, block_h);
802 min_sad -= min_sad >> 2;
803 sad[dy][dx] = min_sad;
805 if (min_sad >= block_w * block_h) {
810 if (dx != sr_range || dy != sr_range) {
811 sad[dy][dx] =
fc->vvcdsp.inter.sad(lc->
tmp, lc->
tmp1, dx, dy, block_w, block_h);
812 if (sad[dy][dx] < min_sad) {
813 min_sad = sad[dy][dx];
820 dmv[0] = (min_dx - sr_range) * (1 << 4);
821 dmv[1] = (min_dy - sr_range) * (1 << 4);
822 if (min_dx != 0 && min_dx != 4 && min_dy != 0 && min_dy != 4) {
827 for (
int i =
L0;
i <=
L1;
i++) {
829 mv->x += (1 - 2 *
i) * dmv[0];
830 mv->y += (1 - 2 *
i) * dmv[1];
834 if (min_sad < 2 * block_w * block_h) {
848 fc->ref->tab_dmvr_mvf[idx] = *mvf;
854 const int x0,
const int y0,
const int sbw,
const int sbh)
877 int sbw, sbh, sb_bdof_flag = 0;
885 for (
int sby = 0; sby <
mi->num_sb_y; sby++) {
886 for (
int sbx = 0; sbx <
mi->num_sb_x; sbx++) {
887 const int x0 = cu->
x0 + sbx * sbw;
888 const int y0 = cu->
y0 + sby * sbh;
900 const int x0,
const int y0,
const int sbw,
const int sbh)
902 const int hs =
fc->ps.sps->hshift[1];
903 const int vs =
fc->ps.sps->vshift[1];
909 mvc->
mv[0].
x += (
unsigned int)mv2->
mv[0].
x;
910 mvc->
mv[0].
y += (
unsigned int)mv2->
mv[0].
y;
911 mvc->
mv[1].
x += (
unsigned int)mv2->
mv[1].
x;
912 mvc->
mv[1].
y += (
unsigned int)mv2->
mv[1].
y;
923 const int x0 = cu->
x0;
924 const int y0 = cu->
y0;
927 const int hs =
fc->ps.sps->hshift[1];
928 const int vs =
fc->ps.sps->vshift[1];
929 const int dst_stride =
fc->frame->linesize[
LUMA];
931 for (
int sby = 0; sby <
mi->num_sb_y; sby++) {
932 for (
int sbx = 0; sbx <
mi->num_sb_x; sbx++) {
933 const int x = x0 + sbx * sbw;
934 const int y = y0 + sby * sbh;
936 uint8_t *dst0 =
POS(0, x, y);
944 const int lx =
mi->pred_flag -
PF_L0;
945 if (refp[lx]->is_scaled) {
955 if (
fc->ps.sps->r->sps_chroma_format_idc) {
982 uint8_t* dst0 =
POS(0, cu->
x0, cu->
y0);
static void set_dmvr_info(VVCFrameContext *fc, const int x0, const int y0, const int width, const int height, const MvField *mvf)
const int8_t ff_vvc_inter_chroma_filters[VVC_INTER_CHROMA_FILTER_TYPES][VVC_INTER_CHROMA_FACTS][VVC_INTER_CHROMA_TAPS]
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 void emulated_edge(const VVCLocalContext *lc, uint8_t *dst, const uint8_t **src, ptrdiff_t *src_stride, const VVCFrame *src_frame, int x_sb, int y_sb, int x_off, int y_off, int block_w, int block_h, const int wrap_enabled, const int is_chroma, const int extra_before, const int extra_after)
const uint8_t ff_vvc_gpm_angle_to_mirror[VVC_GPM_NUM_ANGLES]
const VVCPPS * pps
RefStruct reference.
#define SCALE_THRESHOLD_1
static void luma_prof(VVCLocalContext *lc, int16_t *dst, const VVCFrame *ref, const Mv *mv, const int x_off, const int y_off, const int block_w, const int block_h, const int lx)
static const int8_t mv[256][2]
uint8_t gpm_partition_idx
int16_t tmp[MAX_PB_SIZE *MAX_PB_SIZE]
int ff_vvc_predict_inter(VVCLocalContext *lc, const int rs)
Loop entire CTU to predict all inter coding blocks.
uint8_t ciip_tmp[MAX_PB_SIZE *MAX_PB_SIZE *2]
int16_t y
vertical component of motion vector
const H266RawSliceHeader * r
RefStruct reference.
static void derive_sb_mv(VVCLocalContext *lc, MvField *mv, MvField *orig_mv, int *sb_bdof_flag, const int x0, const int y0, const int sbw, const int sbh)
static void subpic_get_rect(VVCRect *r, const VVCFrame *src_frame, const int subpic_idx, const int is_chroma)
#define INTER_FILTER(t, frac)
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t mx
#define MC_EMULATED_EDGE_DMVR(dst, src, src_stride, x_sb, y_sb, x_off, y_off)
int16_t tmp1[MAX_PB_SIZE *MAX_PB_SIZE]
static void apply_averaging(uint8_t *dst, const ptrdiff_t dst_stride, const int16_t *src0, const int16_t *src1, int width, int height, const VVCLocalContext *lc, const MvField *mvf, const int c_idx, const int dmvr_flag)
static int derive_weight_uni(int *denom, int *wx, int *ox, const VVCLocalContext *lc, const MvField *mvf, const int c_idx)
#define SCALED_REF(ref_sb, offset, shift)
static const int bcw_w_lut[]
#define INTER_FILTER_SCALED(scale)
VVCRefPic refs[VVC_MAX_REF_ENTRIES]
void ff_vvc_clip_mv(Mv *mv)
#define SCALED_CHROMA_ADDIN(scale, collocated_flag)
static void emulated_half(const VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride, const uint8_t *src, const ptrdiff_t src_stride, const int ps, int x_off, int y_off, const int block_w, const int block_h, const VVCRect *subpic, const VVCRect *half_sb, const int dmvr_clip)
#define fc(width, name, range_min, range_max)
#define av_assert0(cond)
assert() equivalent, that is always enabled.
uint8_t edge_emu_buffer[EDGE_EMU_BUFFER_STRIDE *EDGE_EMU_BUFFER_STRIDE *2]
const uint8_t ff_vvc_gpm_weights_offset_x[VVC_GPM_NUM_PARTITION][4][4]
static void dmvr_mv_refine(VVCLocalContext *lc, MvField *mvf, MvField *orig_mv, int *sb_bdof_flag, const VVCFrame *ref0, const VVCFrame *ref1, const int x_off, const int y_off, const int block_w, const int block_h)
static int has_inter_luma(const CodingUnit *cu)
#define SCALE_THRESHOLD_2
static void sb_set_lr(VVCRect *sb, const int l, const int r)
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t my
static void mc_scaled(VVCLocalContext *lc, int16_t *dst, const VVCRefPic *refp, const Mv *mv, int x_off, int y_off, const int block_w, const int block_h, const int c_idx)
#define SCALED_STEP(scale)
static void derive_affine_mvc(MvField *mvc, const VVCFrameContext *fc, const MvField *mv, const int x0, const int y0, const int sbw, const int sbh)
static void FUNC() pred_h(uint8_t *_src, const uint8_t *_left, const int w, const int h, const ptrdiff_t stride)
static void mc_bi_scaled(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride, const VVCRefPic *refp0, const VVCRefPic *refp1, const MvField *mvf, const int x_off, const int y_off, const int block_w, const int block_h, const int c_idx)
static void scaled_ref_pos_and_step(const VVCLocalContext *lc, const VVCRefPic *refp, const Mv *mv, const int x_off, const int y_off, const int c_idx, int *x, int *y, int *dx, int *dy)
#define MC_EMULATED_EDGE(dst, src, src_stride, x_off, y_off)
void ff_vvc_round_mv(Mv *mv, const int lshift, const int rshift)
int is_scaled
RprConstraintsActiveFlag.
int16_t x
horizontal component of motion vector
static void predict_inter(VVCLocalContext *lc)
const int8_t ff_vvc_inter_luma_filters[VVC_INTER_LUMA_FILTER_TYPES][VVC_INTER_LUMA_FACTS][VVC_INTER_LUMA_TAPS]
static void clip_to_subpic(int *x_off, int *y_off, int *pic_width, int *pic_height, const VVCRect *subpic, const VVCRect *sb, const int dmvr_clip)
static void pred_affine_blk(VVCLocalContext *lc)
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
uint8_t hpel_if_idx
hpelIfIdx
#define VVC_GPM_WEIGHT_SIZE
static void pred_gpm_blk(VVCLocalContext *lc)
#define AFFINE_MIN_BLOCK_SIZE
static void pred_regular(VVCLocalContext *lc, const MvField *mvf, const MvField *orig_mvf, const int x0, const int y0, const int sbw, const int sbh, const int sb_bdof_flag, const int c_start)
int16_t diff_mv_x[2][AFFINE_MIN_BLOCK_SIZE *AFFINE_MIN_BLOCK_SIZE]
diffMvLX
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_predict_ciip(VVCLocalContext *lc)
CIIP(Combined Inter-Intra Prediction) for a coding block.
#define MC_EMULATED_EDGE_BILINEAR(dst, src, src_stride, x_off, y_off)
static void emulated_edge_no_wrap(const VVCLocalContext *lc, uint8_t *dst, const uint8_t **src, ptrdiff_t *src_stride, int x_off, int y_off, const int block_w, const int block_h, const int extra_before, const int extra_after, const VVCRect *subpic, const VVCRect *sb, const int dmvr_clip)
static void emulated_edge_scaled(VVCLocalContext *lc, const uint8_t **src, ptrdiff_t *src_stride, int *src_height, const VVCFrame *ref, const int x, const int y, const int dx, const int dy, const int w, const int h, const int is_chroma)
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
static int parametric_mv_refine(const int *sad, const int stride)
static void mc_bi(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride, const VVCFrame *ref0, const VVCFrame *ref1, const MvField *mvf, const MvField *orig_mv, const int x_off, const int y_off, const int block_w, const int block_h, const int c_idx, const int sb_bdof_flag)
#define i(width, name, range_min, range_max)
const uint8_t ff_vvc_gpm_angle_idx[VVC_GPM_NUM_PARTITION]
static int pred_get_refs(const VVCLocalContext *lc, VVCRefPic *refp[2], const MvField *mv)
static const int weights[]
static void mc_uni_scaled(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride, const VVCRefPic *refp, const MvField *mvf, const int x_off, const int y_off, const int block_w, const int block_h, const int c_idx)
#define EDGE_EMU_BUFFER_STRIDE
uint8_t ptrdiff_t const uint8_t ptrdiff_t int const int8_t * hf
static const int8_t * inter_filter_scaled(const int scale, const int is_chroma, const int is_affine)
const uint8_t ff_vvc_gpm_weights[6][VVC_GPM_WEIGHT_SIZE *VVC_GPM_WEIGHT_SIZE]
static int FUNC() sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
uint8_t inter_affine_flag
MvField * ff_vvc_get_mvf(const VVCFrameContext *fc, const int x0, const int y0)
Tag MUST be and< 10hcoeff half pel interpolation filter coefficients, hcoeff[0] are the 2 middle coefficients[1] are the next outer ones and so on, resulting in a filter like:...eff[2], hcoeff[1], hcoeff[0], hcoeff[0], hcoeff[1], hcoeff[2] ... the sign of the coefficients is not explicitly stored but alternates after each coeff and coeff[0] is positive, so ...,+,-,+,-,+,+,-,+,-,+,... hcoeff[0] is not explicitly stored but found by subtracting the sum of all stored coefficients with signs from 32 hcoeff[0]=32 - hcoeff[1] - hcoeff[2] - ... a good choice for hcoeff and htaps is htaps=6 hcoeff={40,-10, 2} an alternative which requires more computations at both encoder and decoder side and may or may not be better is htaps=8 hcoeff={42,-14, 6,-2}ref_frames minimum of the number of available reference frames and max_ref_frames for example the first frame after a key frame always has ref_frames=1spatial_decomposition_type wavelet type 0 is a 9/7 symmetric compact integer wavelet 1 is a 5/3 symmetric compact integer wavelet others are reserved stored as delta from last, last is reset to 0 if always_reset||keyframeqlog quality(logarithmic quantizer scale) stored as delta from last, last is reset to 0 if always_reset||keyframemv_scale stored as delta from last, last is reset to 0 if always_reset||keyframe FIXME check that everything works fine if this changes between framesqbias dequantization bias stored as delta from last, last is reset to 0 if always_reset||keyframeblock_max_depth maximum depth of the block tree stored as delta from last, last is reset to 0 if always_reset||keyframequant_table quantization tableHighlevel bitstream structure:==============================--------------------------------------------|Header|--------------------------------------------|------------------------------------|||Block0||||split?||||yes no||||......... intra?||||:Block01 :yes no||||:Block02 :....... ..........||||:Block03 ::y DC ::ref index:||||:Block04 ::cb DC ::motion x :||||......... :cr DC ::motion y :||||....... ..........|||------------------------------------||------------------------------------|||Block1|||...|--------------------------------------------|------------ ------------ ------------|||Y subbands||Cb subbands||Cr subbands||||--- ---||--- ---||--- ---|||||LL0||HL0||||LL0||HL0||||LL0||HL0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||LH0||HH0||||LH0||HH0||||LH0||HH0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HL1||LH1||||HL1||LH1||||HL1||LH1|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HH1||HL2||||HH1||HL2||||HH1||HL2|||||...||...||...|||------------ ------------ ------------|--------------------------------------------Decoding process:=================------------|||Subbands|------------||||------------|Intra DC||||LL0 subband prediction ------------|\ Dequantization ------------------- \||Reference frames|\ IDWT|------- -------|Motion \|||Frame 0||Frame 1||Compensation . OBMC v -------|------- -------|--------------. \------> Frame n output Frame Frame<----------------------------------/|...|------------------- Range Coder:============Binary Range Coder:------------------- The implemented range coder is an adapted version based upon "Range encoding: an algorithm for removing redundancy from a digitised message." by G. N. N. Martin. The symbols encoded by the Snow range coder are bits(0|1). The associated probabilities are not fix but change depending on the symbol mix seen so far. bit seen|new state ---------+----------------------------------------------- 0|256 - state_transition_table[256 - old_state];1|state_transition_table[old_state];state_transition_table={ 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 215, 215, 216, 217, 218, 219, 220, 220, 222, 223, 224, 225, 226, 227, 227, 229, 229, 230, 231, 232, 234, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 0, 0, 0, 0, 0, 0, 0};FIXME Range Coding of integers:------------------------- FIXME Neighboring Blocks:===================left and top are set to the respective blocks unless they are outside of the image in which case they are set to the Null block top-left is set to the top left block unless it is outside of the image in which case it is set to the left block if this block has no larger parent block or it is at the left side of its parent block and the top right block is not outside of the image then the top right block is used for top-right else the top-left block is used Null block y, cb, cr are 128 level, ref, mx and my are 0 Motion Vector Prediction:=========================1. the motion vectors of all the neighboring blocks are scaled to compensate for the difference of reference frames scaled_mv=(mv *(256 *(current_reference+1)/(mv.reference+1))+128)> the median of the scaled left
void ff_vvc_set_neighbour_available(VVCLocalContext *lc, const int x0, const int y0, const int w, const int h)
static int ciip_derive_intra_weight(const VVCLocalContext *lc, const int x0, const int y0, const int width, const int height)
enum PredMode pred_mode
PredMode.
int16_t tmp2[MAX_PB_SIZE *MAX_PB_SIZE]
static int ref[MAX_W *MAX_W]
int16_t diff_mv_y[2][AFFINE_MIN_BLOCK_SIZE *AFFINE_MIN_BLOCK_SIZE]
diffMvLX
static void sb_wrap(VVCRect *sb, const int wrap)
struct CodingUnit * next
RefStruct reference.
int8_t ref_idx[2]
refIdxL0, refIdxL1
static void pred_regular_blk(VVCLocalContext *lc, const int skip_ciip)
static void luma_prof_bi(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride, const VVCRefPic *ref0, const VVCRefPic *ref1, const MvField *mvf, const int x_off, const int y_off, const int block_w, const int block_h)
static void scale(int *out, const int *in, const int w, const int h, const int shift)
const uint8_t ff_vvc_gpm_weights_offset_y[VVC_GPM_NUM_PARTITION][4][4]
#define SCALED_REF_SB(off, scaling_off, ref_mv, scale, add, shift)
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
#define VVC_INTER_LUMA_FILTER_TYPE_AFFINE
uint8_t ptrdiff_t const uint8_t ptrdiff_t int const int8_t const int8_t * vf
const uint8_t ff_vvc_gpm_angle_to_weights_idx[VVC_GPM_NUM_ANGLES]
static void mc_uni(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride, const VVCFrame *ref, const MvField *mvf, int x_off, int y_off, const int block_w, const int block_h, const int c_idx)
const VVCSPS * sps
RefStruct reference.
static void luma_prof_uni(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride, const VVCFrame *ref, const MvField *mvf, int x_off, int y_off, const int block_w, const int block_h, const int cb_prof_flag, const int16_t *diff_mv_x, const int16_t *diff_mv_y)
int scale[2]
RefPicScale[].
static void mc(VVCLocalContext *lc, int16_t *dst, const VVCFrame *ref, const Mv *mv, int x_off, int y_off, const int block_w, const int block_h, const int c_idx)