diff mbox series

[FFmpeg-devel,18/18] avcodec/vvcdec: alf, support virtual boundaries

Message ID TYSPR06MB643305BA35F25E3F01CF0763AACA2@TYSPR06MB6433.apcprd06.prod.outlook.com
State New
Headers show
Series [FFmpeg-devel,01/18] avcodec/vvcdec: refact, unify vvc_deblock_subblock_bs_{horizontal, vertical} | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Nuo Mi June 22, 2024, 6:24 a.m. UTC
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(-)

Comments

Nuo Mi June 25, 2024, 11:53 a.m. UTC | #1
On Sat, Jun 22, 2024 at 2:24 PM Nuo Mi <nuomi2021@gmail.com> wrote:

> 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
>

Applied.
thank you

> --
> 2.34.1
>
>
James Almer June 25, 2024, 12:48 p.m. UTC | #2
On 6/25/2024 8:53 AM, Nuo Mi wrote:
> On Sat, Jun 22, 2024 at 2:24 PM Nuo Mi <nuomi2021@gmail.com> wrote:
> 
>> 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
>>
> 
> Applied.
> thank you

Can you add a test for this? Just one of those samples (the that covers 
the most decoder logic).
And in general, try to add tests for at least one of the samples that 
exercise new feature support you add.
Nuo Mi June 25, 2024, 2:29 p.m. UTC | #3
On Tue, Jun 25, 2024 at 8:48 PM James Almer <jamrial@gmail.com> wrote:

> On 6/25/2024 8:53 AM, Nuo Mi wrote:
> > On Sat, Jun 22, 2024 at 2:24 PM Nuo Mi <nuomi2021@gmail.com> wrote:
> >
> >> 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
> >>
> >
> > Applied.
> > thank you
>
> Can you add a test for this? Just one of those samples (the that covers
> the most decoder logic).
> And in general, try to add tests for at least one of the samples that
> exercise new feature support you add.
>
Hi James,
Thank you for the reminder.
Yes, we will do that. Once it is merged, it will trigger some gcov tests on
Frank's machine.
He will help select some clips to get the largest coverage and send a FATE
test like before.

BTW: We have a ci to cover conformance and fuzz test at
https://github.com/ffvvc/FFmpeg/actions/runs/9626631693/job/26559410841?pr=235#step:10:665

Thank you
diff mbox series

Patch

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;