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]];
226 const int bcw_idx = mvf->
bcw_idx;
227 const int weight_flag = (
IS_P(sh->
r) &&
pps->r->pps_weighted_pred_flag) ||
228 (
IS_B(sh->
r) &&
pps->r->pps_weighted_bipred_flag && !dmvr_flag);
229 if ((!weight_flag && !bcw_idx) || (bcw_idx && lc->
cu->
ciip_flag))
241 *denom =
w->log2_denom[c_idx > 0];
250 #define INTER_FILTER(t, frac) (is_chroma ? ff_vvc_inter_chroma_filters[t][frac] : ff_vvc_inter_luma_filters[t][frac])
253 int x_off,
int y_off,
const int block_w,
const int block_h,
const int c_idx)
257 const uint8_t *
src =
ref->frame->data[c_idx];
258 ptrdiff_t src_stride =
ref->frame->linesize[c_idx];
259 const int is_chroma = !!c_idx;
260 const int hs =
fc->ps.sps->hshift[c_idx];
261 const int vs =
fc->ps.sps->vshift[c_idx];
262 const int idx =
av_log2(block_w) - 1;
268 const int wrap_enabled =
fc->ps.pps->r->pps_ref_wraparound_enabled_flag;
270 x_off +=
mv->x >> (4 + hs);
271 y_off +=
mv->y >> (4 + vs);
274 fc->vvcdsp.inter.put[is_chroma][idx][!!
my][!!
mx](
dst,
src, src_stride, block_h,
hf,
vf, block_w);
278 const VVCFrame *
ref,
const MvField *mvf,
int x_off,
int y_off,
const int block_w,
const int block_h,
283 const uint8_t *
src =
ref->frame->data[c_idx];
284 ptrdiff_t src_stride =
ref->frame->linesize[c_idx];
286 const int hs =
fc->ps.sps->hshift[c_idx];
287 const int vs =
fc->ps.sps->vshift[c_idx];
288 const int idx =
av_log2(block_w) - 1;
289 const Mv *
mv = &mvf->
mv[lx];
290 const int is_chroma = !!c_idx;
296 const int wrap_enabled =
fc->ps.pps->r->pps_ref_wraparound_enabled_flag;
299 x_off +=
mv->x >> (4 + hs);
300 y_off +=
mv->y >> (4 + vs);
304 fc->vvcdsp.inter.put_uni_w[is_chroma][idx][!!
my][!!
mx](
dst, dst_stride,
src, src_stride,
305 block_h, denom, wx, ox,
hf,
vf, block_w);
307 fc->vvcdsp.inter.put_uni[is_chroma][idx][!!
my][!!
mx](
dst, dst_stride,
src, src_stride,
308 block_h,
hf,
vf, block_w);
314 const int x_off,
const int y_off,
const int block_w,
const int block_h,
const int c_idx,
315 const int sb_bdof_flag)
319 const int hs =
fc->ps.sps->hshift[c_idx];
320 const int vs =
fc->ps.sps->vshift[c_idx];
321 const int idx =
av_log2(block_w) - 1;
322 const VVCFrame *refs[] = { ref0, ref1 };
324 int denom, w0, w1, o0, o1;
326 const int is_chroma = !!c_idx;
329 for (
int i =
L0;
i <=
L1;
i++) {
333 const int ox = x_off + (
mv->x >> (4 + hs));
334 const int oy = y_off + (
mv->y >> (4 + vs));
336 ptrdiff_t src_stride =
ref->frame->linesize[c_idx];
337 const uint8_t *
src =
ref->frame->data[c_idx];
340 const int wrap_enabled =
fc->ps.pps->r->pps_ref_wraparound_enabled_flag;
343 const int x_sb = x_off + (orig_mv->
mv[
i].
x >> (4 + hs));
344 const int y_sb = y_off + (orig_mv->
mv[
i].
y >> (4 + vs));
350 fc->vvcdsp.inter.put[is_chroma][idx][!!
my][!!
mx](
tmp[
i],
src, src_stride, block_h,
hf,
vf, block_w);
352 fc->vvcdsp.inter.bdof_fetch_samples(
tmp[
i],
src, src_stride,
mx,
my, block_w, block_h);
355 fc->vvcdsp.inter.apply_bdof(
dst, dst_stride,
tmp[
L0],
tmp[
L1], block_w, block_h);
356 else if (weight_flag)
357 fc->vvcdsp.inter.w_avg(
dst, dst_stride,
tmp[
L0],
tmp[
L1], block_w, block_h, denom, w0, w1, o0, o1);
359 fc->vvcdsp.inter.avg(
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 int denom, w0, w1, o0, o1;
475 const VVCRefPic *refps[] = { refp0, refp1 };
478 for (
int i =
L0;
i <=
L1;
i++) {
483 mc_scaled(lc,
tmp[
i], refp,
mv, x_off, y_off, block_w, block_h, c_idx);
485 mc(lc,
tmp[
i], refp->
ref,
mv, x_off, y_off, block_w, block_h, c_idx);
488 fc->vvcdsp.inter.w_avg(
dst, dst_stride,
tmp[
L0],
tmp[
L1], block_w, block_h, denom, w0, w1, o0, o1);
490 fc->vvcdsp.inter.avg(
dst, dst_stride,
tmp[
L0],
tmp[
L1], block_w, block_h);
494 const VVCFrame *
ref,
const MvField *mvf,
int x_off,
int y_off,
const int block_w,
const int block_h,
495 const int cb_prof_flag,
const int16_t *diff_mv_x,
const int16_t *diff_mv_y)
499 ptrdiff_t src_stride =
ref->frame->linesize[
LUMA];
501 const int idx =
av_log2(block_w) - 1;
503 const Mv *
mv = mvf->
mv + lx;
504 const int mx =
mv->x & 0xf;
505 const int my =
mv->y & 0xf;
510 const int wrap_enabled =
fc->ps.pps->r->pps_ref_wraparound_enabled_flag;
511 const int is_chroma = 0;
519 fc->vvcdsp.inter.fetch_samples(prof_tmp,
src, src_stride,
mx,
my);
521 fc->vvcdsp.inter.apply_prof_uni(
dst, dst_stride, prof_tmp, diff_mv_x, diff_mv_y);
523 fc->vvcdsp.inter.apply_prof_uni_w(
dst, dst_stride, prof_tmp, diff_mv_x, diff_mv_y, denom, wx, ox);
526 fc->vvcdsp.inter.put_uni[
LUMA][idx][!!
my][!!
mx](
dst, dst_stride,
src, src_stride, block_h,
hf,
vf, block_w);
528 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);
533 const Mv *
mv ,
const int x_off,
const int y_off,
const int block_w,
const int block_h,
const int lx)
537 const int mx =
mv->x & 0xf;
538 const int my =
mv->y & 0xf;
539 const int ox = x_off + (
mv->x >> 4);
540 const int oy = y_off + (
mv->y >> 4);
541 const int idx =
av_log2(block_w) - 1;
542 const int is_chroma = 0;
544 ptrdiff_t src_stride =
ref->frame->linesize[
LUMA];
548 const int wrap_enabled =
fc->ps.pps->r->pps_ref_wraparound_enabled_flag;
555 fc->vvcdsp.inter.fetch_samples(prof_tmp,
src, src_stride,
mx,
my);
562 const int block_w,
const int block_h)
565 const VVCRefPic *refps[] = { ref0, ref1 };
567 int denom, w0, w1, o0, o1;
568 const int weight_flag =
derive_weight(&denom, &w0, &w1, &o0, &o1, lc, mvf,
LUMA, 0);
570 for (
int i =
L0;
i <=
L1;
i++) {
581 fc->vvcdsp.inter.w_avg(
dst, dst_stride,
tmp[
L0],
tmp[
L1], block_w, block_h, denom, w0, w1, o0, o1);
583 fc->vvcdsp.inter.avg(
dst, dst_stride,
tmp[
L0],
tmp[
L1], block_w, block_h);
591 if (
mv->pred_flag &
mask) {
593 refp[lx] = rpl[lx].
refs +
mv->ref_idx[lx];
601 #define POS(c_idx, x, y) \
602 &fc->frame->data[c_idx][((y) >> fc->ps.sps->vshift[c_idx]) * fc->frame->linesize[c_idx] + \
603 (((x) >> fc->ps.sps->hshift[c_idx]) << fc->ps.sps->pixel_shift)]
620 const int c_end =
fc->ps.sps->r->sps_chroma_format_idc ? 3 : 1;
624 for (
int c_idx = 0; c_idx < c_end; c_idx++) {
625 const int hs =
fc->ps.sps->hshift[c_idx];
626 const int vs =
fc->ps.sps->vshift[c_idx];
627 const int x = lc->
cu->
x0 >> hs;
628 const int y = lc->
cu->
y0 >> vs;
632 ptrdiff_t dst_stride =
fc->frame->linesize[c_idx];
634 int step_x = 1 << hs;
638 }
else if (mirror_type == 1) {
646 for (
int i = 0;
i < 2;
i++) {
648 const int lx =
mv->pred_flag -
PF_L0;
672 const int min_pu_width =
fc->ps.pps->min_pu_width;
685 const int x0,
const int y0,
const int sbw,
const int sbh,
const int sb_bdof_flag,
const int c_start)
688 const int c_end =
fc->ps.sps->r->sps_chroma_format_idc ?
CR :
LUMA;
694 for (
int c_idx = c_start; c_idx <= c_end; c_idx++) {
695 uint8_t *
dst =
POS(c_idx, x0, y0);
696 const ptrdiff_t dst_stride =
fc->frame->linesize[c_idx];
697 const int hs =
fc->ps.sps->hshift[c_idx];
698 const int vs =
fc->ps.sps->vshift[c_idx];
699 const int x = x0 >> hs;
700 const int y = y0 >> vs;
701 const int w = sbw >> hs;
702 const int h = sbh >> vs;
703 const int is_luma = !c_idx;
704 const int do_ciip = lc->
cu->
ciip_flag && (is_luma || (
w > 2));
705 uint8_t *inter = do_ciip ? (uint8_t *)lc->
ciip_tmp :
dst;
706 const ptrdiff_t inter_stride = do_ciip ? (
MAX_PB_SIZE *
sizeof(uint16_t)) : dst_stride;
707 const int do_bdof = is_luma && sb_bdof_flag;
712 if (refp[lx]->is_scaled) {
716 mc_uni(lc, inter, inter_stride, refp[lx]->
ref, mvf,
720 if (refp[
L0]->is_scaled || refp[
L1]->is_scaled) {
724 mc_bi(lc, inter, inter_stride, refp[
L0]->
ref, refp[
L1]->
ref, mvf, orig_mvf,
725 x, y,
w,
h, c_idx, do_bdof);
730 fc->vvcdsp.intra.intra_pred(lc, x0, y0, sbw, sbh, c_idx);
732 fc->vvcdsp.lmcs.filter(inter, inter_stride,
w,
h, &
fc->ps.lmcs.fwd_lut);
733 fc->vvcdsp.inter.put_ciip(
dst, dst_stride,
w,
h, inter, inter_stride, intra_weight);
741 const int sad_minus = sad[-
stride];
742 const int sad_center = sad[0];
743 const int sad_plus = sad[
stride];
745 int denom = (( sad_minus + sad_plus) - (sad_center << 1 ) ) << 3;
749 if (sad_minus == sad_center)
751 else if (sad_plus == sad_center)
754 int num = ( sad_minus - sad_plus ) * (1 << 4);
762 while (counter > 0) {
763 counter = counter - 1;
764 quotient = quotient << 1;
765 if ( num >= denom ) {
767 quotient = quotient + 1;
769 denom = (denom >> 1);
780 #define SAD_ARRAY_SIZE 5
783 const VVCFrame *ref0,
const VVCFrame *ref1,
const int x_off,
const int y_off,
const int block_w,
const int block_h)
786 const int sr_range = 2;
787 const VVCFrame *refs[] = { ref0, ref1 };
790 int min_dx, min_dy, min_sad, dx, dy;
793 min_dx = min_dy = dx = dy = 2;
795 for (
int i =
L0;
i <=
L1;
i++) {
796 const int pred_w = block_w + 2 * sr_range;
797 const int pred_h = block_h + 2 * sr_range;
799 const int mx =
mv->x & 0xf;
800 const int my =
mv->y & 0xf;
801 const int ox = x_off + (
mv->x >> 4) - sr_range;
802 const int oy = y_off + (
mv->y >> 4) - sr_range;
804 ptrdiff_t src_stride =
ref->frame->linesize[
LUMA];
806 const int wrap_enabled =
fc->ps.pps->r->pps_ref_wraparound_enabled_flag;
812 min_sad =
fc->vvcdsp.inter.sad(
tmp[
L0],
tmp[
L1], dx, dy, block_w, block_h);
813 min_sad -= min_sad >> 2;
814 sad[dy][dx] = min_sad;
816 if (min_sad >= block_w * block_h) {
821 if (dx != sr_range || dy != sr_range) {
822 sad[dy][dx] =
fc->vvcdsp.inter.sad(lc->
tmp, lc->
tmp1, dx, dy, block_w, block_h);
823 if (sad[dy][dx] < min_sad) {
824 min_sad = sad[dy][dx];
831 dmv[0] = (min_dx - sr_range) * (1 << 4);
832 dmv[1] = (min_dy - sr_range) * (1 << 4);
833 if (min_dx != 0 && min_dx != 4 && min_dy != 0 && min_dy != 4) {
838 for (
int i =
L0;
i <=
L1;
i++) {
840 mv->x += (1 - 2 *
i) * dmv[0];
841 mv->y += (1 - 2 *
i) * dmv[1];
845 if (min_sad < 2 * block_w * block_h) {
859 fc->ref->tab_dmvr_mvf[idx] = *mvf;
865 const int x0,
const int y0,
const int sbw,
const int sbh)
888 int sbw, sbh, sb_bdof_flag = 0;
896 for (
int sby = 0; sby <
mi->num_sb_y; sby++) {
897 for (
int sbx = 0; sbx <
mi->num_sb_x; sbx++) {
898 const int x0 = cu->
x0 + sbx * sbw;
899 const int y0 = cu->
y0 + sby * sbh;
911 const int x0,
const int y0,
const int sbw,
const int sbh)
913 const int hs =
fc->ps.sps->hshift[1];
914 const int vs =
fc->ps.sps->vshift[1];
920 mvc->
mv[0].
x += (
unsigned int)mv2->
mv[0].
x;
921 mvc->
mv[0].
y += (
unsigned int)mv2->
mv[0].
y;
922 mvc->
mv[1].
x += (
unsigned int)mv2->
mv[1].
x;
923 mvc->
mv[1].
y += (
unsigned int)mv2->
mv[1].
y;
934 const int x0 = cu->
x0;
935 const int y0 = cu->
y0;
938 const int hs =
fc->ps.sps->hshift[1];
939 const int vs =
fc->ps.sps->vshift[1];
940 const int dst_stride =
fc->frame->linesize[
LUMA];
942 for (
int sby = 0; sby <
mi->num_sb_y; sby++) {
943 for (
int sbx = 0; sbx <
mi->num_sb_x; sbx++) {
944 const int x = x0 + sbx * sbw;
945 const int y = y0 + sby * sbh;
947 uint8_t *dst0 =
POS(0, x, y);
955 const int lx =
mi->pred_flag -
PF_L0;
956 if (refp[lx]->is_scaled) {
966 if (
fc->ps.sps->r->sps_chroma_format_idc) {
993 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.
#define fc(width, name, range_min, range_max)
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 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 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 int derive_weight(int *denom, int *w0, int *w1, int *o0, int *o1, const VVCLocalContext *lc, const MvField *mvf, const int c_idx, const int dmvr_flag)
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)
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)