[FFmpeg-devel] [PATCH 18/18] avcodec/vvcdec: alf, support virtual boundaries
Nuo Mi
nuomi2021 at gmail.com
Sat Jun 22 09:24:05 EEST 2024
see https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=9503377
passed files:
GDR_A_ERICSSON_2.bit
GDR_B_NOKIA_2.bit
GDR_C_NOKIA_2.bit
VIRTUAL_A_MediaTek_3.bit
VIRTUAL_B_MediaTek_3.bit
---
libavcodec/vvc/ctu.h | 7 +++
libavcodec/vvc/filter.c | 134 ++++++++++++++++++++++++++++------------
libavcodec/vvc/inter.c | 7 ---
3 files changed, 100 insertions(+), 48 deletions(-)
diff --git a/libavcodec/vvc/ctu.h b/libavcodec/vvc/ctu.h
index 432dbc5ade..d5c3e8d96f 100644
--- a/libavcodec/vvc/ctu.h
+++ b/libavcodec/vvc/ctu.h
@@ -463,6 +463,13 @@ typedef struct ALFParams {
uint8_t ctb_cc_idc[2]; ///< alf_ctb_cc_cb_idc, alf_ctb_cc_cr_idc
} ALFParams;
+typedef struct VVCRect {
+ int l; // left
+ int t; // top
+ int r; // right
+ int b; // bottom
+} VVCRect;
+
/**
* parse a CTU
* @param lc local context for CTU
diff --git a/libavcodec/vvc/filter.c b/libavcodec/vvc/filter.c
index 44dd895d7d..19b69f078e 100644
--- a/libavcodec/vvc/filter.c
+++ b/libavcodec/vvc/filter.c
@@ -56,6 +56,9 @@ static const uint8_t betatable[64] = {
58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88,
};
+// One vertical and one horizontal virtual boundary in a CTU at most. The CTU will be divided into 4 subblocks.
+#define MAX_VBBS 4
+
static int get_virtual_boundary(const VVCFrameContext *fc, const int ctu_pos, const int vertical)
{
const VVCSPS *sps = fc->ps.sps;
@@ -1127,58 +1130,107 @@ static void alf_get_edges(const VVCLocalContext *lc, int edges[MAX_EDGES], const
edges[RIGHT] |= fc->ps.sps->r->sps_subpic_ctu_top_left_x[subpic_idx] + fc->ps.sps->r->sps_subpic_width_minus1[subpic_idx] == rx;
edges[BOTTOM] |= fc->ps.sps->r->sps_subpic_ctu_top_left_y[subpic_idx] + fc->ps.sps->r->sps_subpic_height_minus1[subpic_idx] == ry;
}
+
+ if (sps->r->sps_virtual_boundaries_enabled_flag) {
+ edges[LEFT] |= is_virtual_boundary(fc, rx << sps->ctb_log2_size_y, 1);
+ edges[TOP] |= is_virtual_boundary(fc, ry << sps->ctb_log2_size_y, 0);
+ edges[RIGHT] |= is_virtual_boundary(fc, (rx + 1) << sps->ctb_log2_size_y, 1);
+ edges[BOTTOM] |= is_virtual_boundary(fc, (ry + 1) << sps->ctb_log2_size_y, 0);
+ }
+}
+
+static void alf_init_subblock(VVCRect *sb, int sb_edges[MAX_EDGES], const VVCRect *b, const int edges[MAX_EDGES])
+{
+ *sb = *b;
+ memcpy(sb_edges, edges, sizeof(int) * MAX_EDGES);
+}
+
+static void alf_get_subblock(VVCRect *sb, int edges[MAX_EDGES], const int bx, const int by, const int vb_pos[2], const int has_vb[2])
+{
+ int *pos[] = { &sb->l, &sb->t, &sb->r, &sb->b };
+
+ for (int vertical = 0; vertical <= 1; vertical++) {
+ if (has_vb[vertical]) {
+ const int c = vertical ? (bx ? LEFT : RIGHT) : (by ? TOP : BOTTOM);
+ *pos[c] = vb_pos[vertical];
+ edges[c] = 1;
+ }
+ }
+}
+
+static void alf_get_subblocks(const VVCLocalContext *lc, VVCRect sbs[MAX_VBBS], int sb_edges[MAX_VBBS][MAX_EDGES], int *nb_sbs,
+ const int x0, const int y0, const int rx, const int ry)
+{
+ VVCFrameContext *fc = lc->fc;
+ const VVCSPS *sps = fc->ps.sps;
+ const VVCPPS *pps = fc->ps.pps;
+ const int ctu_size_y = sps->ctb_size_y;
+ const int vb_pos[] = { get_virtual_boundary(fc, ry, 0), get_virtual_boundary(fc, rx, 1) };
+ const int has_vb[] = { vb_pos[0] > y0, vb_pos[1] > x0 };
+ const VVCRect b = { x0, y0, FFMIN(x0 + ctu_size_y, pps->width), FFMIN(y0 + ctu_size_y, pps->height) };
+ int edges[MAX_EDGES] = { !rx, !ry, rx == pps->ctb_width - 1, ry == pps->ctb_height - 1 };
+ int i = 0;
+
+ alf_get_edges(lc, edges, rx, ry);
+
+ for (int by = 0; by <= has_vb[0]; by++) {
+ for (int bx = 0; bx <= has_vb[1]; bx++, i++) {
+ alf_init_subblock(sbs + i, sb_edges[i], &b, edges);
+ alf_get_subblock(sbs + i, sb_edges[i], bx, by, vb_pos, has_vb);
+ }
+ }
+ *nb_sbs = i;
}
void ff_vvc_alf_filter(VVCLocalContext *lc, const int x0, const int y0)
{
VVCFrameContext *fc = lc->fc;
const VVCSPS *sps = fc->ps.sps;
- const VVCPPS *pps = fc->ps.pps;
- const int rx = x0 >> fc->ps.sps->ctb_log2_size_y;
- const int ry = y0 >> fc->ps.sps->ctb_log2_size_y;
- const int ctb_size_y = fc->ps.sps->ctb_size_y;
- const int ps = fc->ps.sps->pixel_shift;
+ const int rx = x0 >> sps->ctb_log2_size_y;
+ const int ry = y0 >> sps->ctb_log2_size_y;
+ const int ps = sps->pixel_shift;
const int padded_stride = EDGE_EMU_BUFFER_STRIDE << ps;
const int padded_offset = padded_stride * ALF_PADDING_SIZE + (ALF_PADDING_SIZE << ps);
const int c_end = sps->r->sps_chroma_format_idc ? VVC_MAX_SAMPLE_ARRAYS : 1;
+ const int ctu_end = y0 + sps->ctb_size_y;
const ALFParams *alf = &CTB(fc->tab.alf, rx, ry);
- int edges[MAX_EDGES] = { rx == 0, ry == 0, rx == pps->ctb_width - 1, ry == pps->ctb_height - 1 };
-
- alf_get_edges(lc, edges, rx, ry);
-
- for (int c_idx = 0; c_idx < c_end; c_idx++) {
- const int hs = fc->ps.sps->hshift[c_idx];
- const int vs = fc->ps.sps->vshift[c_idx];
- const int ctb_size_h = ctb_size_y >> hs;
- const int ctb_size_v = ctb_size_y >> vs;
- const int x = x0 >> hs;
- const int y = y0 >> vs;
- const int pic_width = fc->ps.pps->width >> hs;
- const int pic_height = fc->ps.pps->height >> vs;
- const int width = FFMIN(pic_width - x, ctb_size_h);
- const int height = FFMIN(pic_height - y, ctb_size_v);
- const int src_stride = fc->frame->linesize[c_idx];
- uint8_t *src = POS(c_idx, x0, y0);
- uint8_t *padded;
-
- if (alf->ctb_flag[c_idx] || (!c_idx && (alf->ctb_cc_idc[0] || alf->ctb_cc_idc[1]))) {
- padded = (c_idx ? lc->alf_buffer_chroma : lc->alf_buffer_luma) + padded_offset;
- alf_prepare_buffer(fc, padded, src, x, y, rx, ry, width, height,
- padded_stride, src_stride, c_idx, edges);
- }
- if (alf->ctb_flag[c_idx]) {
- if (!c_idx) {
- alf_filter_luma(lc, src, padded, src_stride, padded_stride, x, y,
- width, height, y + ctb_size_v - ALF_VB_POS_ABOVE_LUMA, alf);
- } else {
- alf_filter_chroma(lc, src, padded, src_stride, padded_stride, c_idx,
- width, height, ctb_size_v - ALF_VB_POS_ABOVE_CHROMA, alf);
+ int sb_edges[MAX_VBBS][MAX_EDGES], nb_sbs;
+ VVCRect sbs[MAX_VBBS];
+
+ alf_get_subblocks(lc, sbs, sb_edges, &nb_sbs, x0, y0, rx, ry);
+
+ for (int i = 0; i < nb_sbs; i++) {
+ const VVCRect *sb = sbs + i;
+ for (int c_idx = 0; c_idx < c_end; c_idx++) {
+ const int hs = fc->ps.sps->hshift[c_idx];
+ const int vs = fc->ps.sps->vshift[c_idx];
+ const int x = sb->l >> hs;
+ const int y = sb->t >> vs;
+ const int width = (sb->r - sb->l) >> hs;
+ const int height = (sb->b - sb->t) >> vs;
+ const int src_stride = fc->frame->linesize[c_idx];
+ uint8_t *src = POS(c_idx, sb->l, sb->t);
+ uint8_t *padded;
+
+ if (alf->ctb_flag[c_idx] || (!c_idx && (alf->ctb_cc_idc[0] || alf->ctb_cc_idc[1]))) {
+ padded = (c_idx ? lc->alf_buffer_chroma : lc->alf_buffer_luma) + padded_offset;
+ alf_prepare_buffer(fc, padded, src, x, y, rx, ry, width, height,
+ padded_stride, src_stride, c_idx, sb_edges[i]);
+ }
+ if (alf->ctb_flag[c_idx]) {
+ if (!c_idx) {
+ alf_filter_luma(lc, src, padded, src_stride, padded_stride, x, y,
+ width, height, ctu_end - ALF_VB_POS_ABOVE_LUMA, alf);
+ } else {
+ alf_filter_chroma(lc, src, padded, src_stride, padded_stride, c_idx,
+ width, height, ((ctu_end - sb->t) >> vs) - ALF_VB_POS_ABOVE_CHROMA, alf);
+ }
+ }
+ if (c_idx && alf->ctb_cc_idc[c_idx - 1]) {
+ padded = lc->alf_buffer_luma + padded_offset;
+ alf_filter_cc(lc, src, padded, src_stride, padded_stride, c_idx,
+ width, height, hs, vs, ctu_end - sb->t - ALF_VB_POS_ABOVE_LUMA, alf);
}
- }
- if (c_idx && alf->ctb_cc_idc[c_idx - 1]) {
- padded = lc->alf_buffer_luma + padded_offset;
- alf_filter_cc(lc, src, padded, src_stride, padded_stride, c_idx,
- width, height, hs, vs, (ctb_size_v << vs) - ALF_VB_POS_ABOVE_LUMA, alf);
}
}
}
diff --git a/libavcodec/vvc/inter.c b/libavcodec/vvc/inter.c
index 344a0a8c13..9578fd8de4 100644
--- a/libavcodec/vvc/inter.c
+++ b/libavcodec/vvc/inter.c
@@ -30,13 +30,6 @@
#define PROF_TEMP_OFFSET (MAX_PB_SIZE + 32)
static const int bcw_w_lut[] = {4, 5, 3, 10, -2};
-typedef struct VVCRect {
- int l; // left
- int t; // top
- int r; // right
- int b; // bottom
-} VVCRect;
-
static void subpic_get_rect(VVCRect *r, const VVCFrame *src_frame, const int subpic_idx, const int is_chroma)
{
const VVCSPS *sps = src_frame->sps;
--
2.34.1
More information about the ffmpeg-devel
mailing list