Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: Nuo Mi <nuomi2021@gmail.com>
To: ffmpeg-devel@ffmpeg.org
Cc: Nuo Mi <nuomi2021@gmail.com>, Wu Jianhua <toqsxw@outlook.com>
Subject: [FFmpeg-devel] [PATCH 10/11] avcodec/vvcdec: add Intra Block Copy parser
Date: Thu, 22 Feb 2024 15:14:05 +0800
Message-ID: <TYSPR06MB6433688AD5344663BBA14BF1AA562@TYSPR06MB6433.apcprd06.prod.outlook.com> (raw)
In-Reply-To: <20240222071406.5714-1-nuomi2021@gmail.com>

From: Wu Jianhua <toqsxw@outlook.com>

Co-authored-by: Nuo Mi <nuomi2021@gmail.com>
---
 libavcodec/vvc/vvc_ctu.c |  76 +++++++++++++++++++++-----
 libavcodec/vvc/vvc_ctu.h |   1 +
 libavcodec/vvc/vvc_mvs.c | 113 ++++++++++++++++++++++++++++++++++++++-
 libavcodec/vvc/vvc_mvs.h |   2 +
 4 files changed, 177 insertions(+), 15 deletions(-)

diff --git a/libavcodec/vvc/vvc_ctu.c b/libavcodec/vvc/vvc_ctu.c
index 2cf6e82f26..75b9e73ae3 100644
--- a/libavcodec/vvc/vvc_ctu.c
+++ b/libavcodec/vvc/vvc_ctu.c
@@ -1444,6 +1444,22 @@ static void merge_data_block(VVCLocalContext *lc)
     }
 }
 
+static void merge_data_ibc(VVCLocalContext *lc)
+{
+    const VVCFrameContext* fc = lc->fc;
+    const VVCSPS* sps         = fc->ps.sps;
+    MotionInfo *mi            = &lc->cu->pu.mi;
+    int merge_idx             = 0;
+
+    mi->pred_flag = PF_IBC;
+
+    if (sps->max_num_ibc_merge_cand > 1)
+        merge_idx = ff_vvc_merge_idx(lc);
+
+    ff_vvc_luma_mv_merge_ibc(lc, merge_idx, &mi->mv[L0][0]);
+    ff_vvc_store_mv(lc, mi);
+}
+
 static int hls_merge_data(VVCLocalContext *lc)
 {
     const VVCFrameContext *fc   = lc->fc;
@@ -1454,8 +1470,7 @@ static int hls_merge_data(VVCLocalContext *lc)
     pu->merge_gpm_flag = 0;
     pu->mi.num_sb_x = pu->mi.num_sb_y = 1;
     if (cu->pred_mode == MODE_IBC) {
-        avpriv_report_missing_feature(fc->log_ctx, "Intra Block Copy");
-        return AVERROR_PATCHWELCOME;
+        merge_data_ibc(lc);
     } else {
         if (ph->max_num_subblock_merge_cand > 0 && cu->cb_width >= 8 && cu->cb_height >= 8)
             pu->merge_subblock_flag = ff_vvc_merge_subblock_flag(lc);
@@ -1571,6 +1586,33 @@ static void mvp_add_difference(MotionInfo *mi, const int num_cp_mv,
     }
 }
 
+static int mvp_data_ibc(VVCLocalContext *lc)
+{
+    const VVCFrameContext *fc = lc->fc;
+    const CodingUnit *cu      = lc->cu;
+    const PredictionUnit *pu  = &lc->cu->pu;
+    const VVCSPS *sps         = fc->ps.sps;
+    MotionInfo *mi            = &lc->cu->pu.mi;
+    int mvp_l0_flag           = 0;
+    int amvr_shift            = 4;
+    Mv *mv                    = &mi->mv[L0][0];
+
+    mi->pred_flag = PF_IBC;
+    mi->num_sb_x  = 1;
+    mi->num_sb_y  = 1;
+
+    hls_mvd_coding(lc, mv);
+    if (sps->max_num_ibc_merge_cand > 1)
+        mvp_l0_flag = ff_vvc_mvp_lx_flag(lc);
+    if (sps->r->sps_amvr_enabled_flag && (mv->x || mv->y))
+        amvr_shift = ff_vvc_amvr_shift(lc, pu->inter_affine_flag, cu->pred_mode, 1);
+
+    ff_vvc_mvp_ibc(lc, mvp_l0_flag, amvr_shift, mv);
+    ff_vvc_store_mv(lc, mi);
+
+    return 0;
+}
+
 static int mvp_data(VVCLocalContext *lc)
 {
     const VVCFrameContext *fc       = lc->fc;
@@ -1691,17 +1733,24 @@ static void refine_regular_subblock(const VVCLocalContext *lc)
     }
 }
 
-static void fill_dmvr_info(const VVCFrameContext *fc, const int x0, const int y0,
-    const int width, const int height)
+static void fill_dmvr_info(const VVCLocalContext *lc)
 {
-    const VVCPPS *pps = fc->ps.pps;
-    const int w = width >> MIN_PU_LOG2;
+    const VVCFrameContext *fc = lc->fc;
+    const CodingUnit *cu      = lc->cu;
+
+    if (cu->pred_mode == MODE_IBC) {
+        ff_vvc_set_intra_mvf(lc, 1);
+    } else {
+        const VVCPPS *pps = fc->ps.pps;
+        const int w       = cu->cb_width >> MIN_PU_LOG2;
+
+        for (int y = cu->y0 >> MIN_PU_LOG2; y < (cu->y0 + cu->cb_height) >> MIN_PU_LOG2; y++) {
+            const int idx = pps->min_pu_width * y + (cu->x0 >> MIN_PU_LOG2);
+            const MvField *mvf = fc->tab.mvf + idx;
+            MvField *dmvr_mvf  = fc->ref->tab_dmvr_mvf + idx;
 
-    for (int y = y0 >> MIN_PU_LOG2; y < (y0 + height) >> MIN_PU_LOG2; y++) {
-        const int idx = pps->min_pu_width * y + (x0 >> MIN_PU_LOG2);
-        const MvField *mvf = fc->tab.mvf + idx;
-        MvField *dmvr_mvf  = fc->ref->tab_dmvr_mvf + idx;
-        memcpy(dmvr_mvf, mvf, sizeof(MvField) * w);
+            memcpy(dmvr_mvf, mvf, sizeof(MvField) * w);
+        }
     }
 }
 
@@ -1719,8 +1768,7 @@ static int inter_data(VVCLocalContext *lc)
     if (pu->general_merge_flag) {
         hls_merge_data(lc);
     } else if (cu->pred_mode == MODE_IBC){
-        avpriv_report_missing_feature(lc->fc->log_ctx, "Intra Block Copy");
-        return AVERROR_PATCHWELCOME;
+        ret = mvp_data_ibc(lc);
     } else {
         ret = mvp_data(lc);
     }
@@ -1734,7 +1782,7 @@ static int inter_data(VVCLocalContext *lc)
     }
 
     if (!pu->dmvr_flag)
-        fill_dmvr_info(lc->fc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
+        fill_dmvr_info(lc);
     return ret;
 }
 
diff --git a/libavcodec/vvc/vvc_ctu.h b/libavcodec/vvc/vvc_ctu.h
index 5ed331a831..8020e184c5 100644
--- a/libavcodec/vvc/vvc_ctu.h
+++ b/libavcodec/vvc/vvc_ctu.h
@@ -217,6 +217,7 @@ typedef enum PredFlag {
     PF_L0    = 0x1,
     PF_L1    = 0x2,
     PF_BI    = 0x3,
+    PF_IBC   = PF_L0 | 0x4,
 } PredFlag;
 
 typedef enum IntraPredMode {
diff --git a/libavcodec/vvc/vvc_mvs.c b/libavcodec/vvc/vvc_mvs.c
index 56e4009741..6398fd3571 100644
--- a/libavcodec/vvc/vvc_mvs.c
+++ b/libavcodec/vvc/vvc_mvs.c
@@ -589,6 +589,11 @@ static void init_neighbour_context(NeighbourContext *ctx, const VVCLocalContext
     ctx->lc = lc;
 }
 
+static av_always_inline PredMode pred_flag_to_mode(PredFlag pred)
+{
+    return pred == PF_IBC ? MODE_IBC : (pred == PF_INTRA ? MODE_INTRA : MODE_INTER);
+}
+
 static int check_available(Neighbour *n, const VVCLocalContext *lc, const int check_mer)
 {
     const VVCFrameContext *fc   = lc->fc;
@@ -600,7 +605,7 @@ static int check_available(Neighbour *n, const VVCLocalContext *lc, const int ch
     if (!n->checked) {
         n->checked = 1;
         n->available = !sps->r->sps_entropy_coding_sync_enabled_flag || ((n->x >> sps->ctb_log2_size_y) <= (cu->x0 >> sps->ctb_log2_size_y));
-        n->available &= TAB_MVF(n->x, n->y).pred_flag != PF_INTRA;
+        n->available &= cu->pred_mode == pred_flag_to_mode(TAB_MVF(n->x, n->y).pred_flag);
         if (check_mer)
             n->available &= !is_same_mer(fc, n->x, n->y, cu->x0, cu->y0);
     }
@@ -1589,6 +1594,112 @@ void ff_vvc_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shif
         mvp(lc, mvp_lx_flag[L1], L1, mi->ref_idx, amvr_shift, &mi->mv[L1][0]);
 }
 
+static int ibc_spatial_candidates(const VVCLocalContext *lc, const int merge_idx, Mv *const cand_list, int *nb_merge_cand)
+{
+    const CodingUnit *cu      = lc->cu;
+    const VVCFrameContext *fc = lc->fc;
+    const int min_pu_width    = fc->ps.pps->min_pu_width;
+    const MvField *tab_mvf    = fc->tab.mvf;
+    const int is_gt4by4       = (cu->cb_width * cu->cb_height) > 16;
+    int num_cands             = 0;
+
+    NeighbourContext nctx;
+    Neighbour *a1 = &nctx.neighbours[A1];
+    Neighbour *b1 = &nctx.neighbours[B1];
+
+    if (!is_gt4by4) {
+        *nb_merge_cand = 0;
+        return 0;
+    }
+
+    init_neighbour_context(&nctx, lc);
+
+    if (check_available(a1, lc, 1)) {
+        cand_list[num_cands++] = TAB_MVF(a1->x, a1->y).mv[L0];
+        if (num_cands > merge_idx)
+            return 1;
+    }
+    if (check_available(b1, lc, 1)) {
+        const MvField *mvf = &TAB_MVF(b1->x, b1->y);
+        if (!num_cands || !IS_SAME_MV(&cand_list[0], mvf->mv)) {
+            cand_list[num_cands++] = mvf->mv[L0];
+            if (num_cands > merge_idx)
+                return 1;
+        }
+    }
+
+    *nb_merge_cand = num_cands;
+    return 0;
+}
+
+static int ibc_history_candidates(const VVCLocalContext *lc,
+    const int merge_idx, Mv *cand_list, int *nb_merge_cand)
+{
+    const CodingUnit *cu = lc->cu;
+    const EntryPoint *ep = lc->ep;
+    const int is_gt4by4  = (cu->cb_width * cu->cb_height) > 16;
+    int num_cands        = *nb_merge_cand;
+
+    for (int i = 1; i <= ep->num_hmvp_ibc; i++) {
+        int same_motion = 0;
+        const MvField *mvf = &ep->hmvp_ibc[ep->num_hmvp_ibc - i];
+        for (int j = 0; j < *nb_merge_cand; j++) {
+            same_motion = is_gt4by4 && i == 1 && IS_SAME_MV(&mvf->mv[L0], &cand_list[j]);
+            if (same_motion)
+                break;
+        }
+        if (!same_motion) {
+            cand_list[num_cands++] = mvf->mv[L0];
+            if (num_cands > merge_idx)
+                return 1;
+        }
+    }
+
+    *nb_merge_cand = num_cands;
+    return 0;
+}
+
+#define MV_BITS 18
+#define IBC_SHIFT(v) ((v) >= (1 << (MV_BITS - 1)) ? ((v) - (1 << MV_BITS)) : (v))
+
+static inline void ibc_add_mvp(Mv *mv, Mv *mvp, const int amvr_shift)
+{
+    ff_vvc_round_mv(mv, amvr_shift, 0);
+    ff_vvc_round_mv(mvp, amvr_shift, amvr_shift);
+    mv->x = IBC_SHIFT(mv->x + mvp->x);
+    mv->y = IBC_SHIFT(mv->y + mvp->y);
+}
+
+static void ibc_merge_candidates(VVCLocalContext *lc, const int merge_idx, Mv *mv)
+{
+    const CodingUnit *cu = lc->cu;
+    LOCAL_ALIGNED_8(Mv, cand_list, [MRG_MAX_NUM_CANDS]);
+    int nb_cands;
+
+    ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
+    if (ibc_spatial_candidates(lc, merge_idx, cand_list, &nb_cands) ||
+        ibc_history_candidates(lc, merge_idx, cand_list, &nb_cands)) {
+        *mv = cand_list[merge_idx];
+        return;
+    }
+
+    //zero mv
+    memset(mv, 0, sizeof(*mv));
+}
+
+void ff_vvc_mvp_ibc(VVCLocalContext *lc, const int mvp_l0_flag, const int amvr_shift, Mv *mv)
+{
+    LOCAL_ALIGNED_8(Mv, mvp, [1]);
+
+    ibc_merge_candidates(lc, mvp_l0_flag, mvp);
+    ibc_add_mvp(mv, mvp, amvr_shift);
+}
+
+void ff_vvc_luma_mv_merge_ibc(VVCLocalContext *lc, const int merge_idx, Mv *mv)
+{
+    ibc_merge_candidates(lc, merge_idx, mv);
+}
+
 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)
diff --git a/libavcodec/vvc/vvc_mvs.h b/libavcodec/vvc/vvc_mvs.h
index 358de5ec45..a546a324c2 100644
--- a/libavcodec/vvc/vvc_mvs.h
+++ b/libavcodec/vvc/vvc_mvs.h
@@ -30,7 +30,9 @@ void ff_vvc_clip_mv(Mv *mv);
 void ff_vvc_mv_scale(Mv *dst, const Mv *src, int td, int tb);
 void ff_vvc_luma_mv_merge_mode(VVCLocalContext *lc, int merge_idx, int ciip_flag, MvField *mv);
 void ff_vvc_luma_mv_merge_gpm(VVCLocalContext *lc, const int merge_gpm_idx[2], MvField *mv);
+void ff_vvc_luma_mv_merge_ibc(VVCLocalContext *lc, int merge_idx, Mv *mv);
 void ff_vvc_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift,  MotionInfo *mi);
+void ff_vvc_mvp_ibc(VVCLocalContext *lc, int mvp_l0_flag, int amvr_shift, Mv *mv);
 void ff_vvc_sb_mv_merge_mode(VVCLocalContext *lc, int merge_subblock_idx, PredictionUnit *pu);
 void ff_vvc_affine_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift, MotionInfo* mi);
 void ff_vvc_store_sb_mvs(const VVCLocalContext *lc, PredictionUnit *pu);
-- 
2.25.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

  parent reply	other threads:[~2024-02-22  7:15 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20240222071406.5714-1-nuomi2021@gmail.com>
2024-02-22  7:13 ` [FFmpeg-devel] [PATCH 01/11] avcodec/vvcdec: refact out deblock_bs to reduce duplicate code Nuo Mi
2024-02-22  7:13 ` [FFmpeg-devel] [PATCH 02/11] avcodec/vvcdec: set CuPredMode table for chroma Nuo Mi
2024-02-22  7:13 ` [FFmpeg-devel] [PATCH 03/11] avcodec/vvcdec: deblock_bs, fix intra check for IBC Nuo Mi
2024-02-22  7:13 ` [FFmpeg-devel] [PATCH 04/11] avcodec/vvcdec: cabac, fix non_inter_flag, pred_mode_flag, amvr_shift " Nuo Mi
2024-02-22  7:14 ` [FFmpeg-devel] [PATCH 05/11] avcodec/vvcdec: implement update_hmvp " Nuo Mi
2024-02-22  7:14 ` [FFmpeg-devel] [PATCH 06/11] avcodec/vvcdec: skip inter prediction for IBC blocks Nuo Mi
2024-02-22  7:14 ` [FFmpeg-devel] [PATCH 07/11] avcodec/vvcdec: ff_vvc_set_intra_mvf, refact to support dmvr tab Nuo Mi
2024-02-22  7:14 ` [FFmpeg-devel] [PATCH 08/11] avcodec/vvcdec: fix dual tree for skipped transform tree/unit Nuo Mi
2024-02-22  7:14 ` [FFmpeg-devel] [PATCH 09/11] avcodec/vvcdec: refact, rename !is_mvp to check_mer Nuo Mi
2024-02-22  7:14 ` Nuo Mi [this message]
2024-02-22  7:14 ` [FFmpeg-devel] [PATCH 11/11] avcodec/vvcdec: add Intra Block Copy decoder Nuo Mi
2024-02-23 13:03   ` Nuo Mi
2024-02-24 12:33     ` Nuo Mi
2024-02-24 13:20   ` Ronald S. Bultje
2024-02-25  3:07     ` Nuo Mi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=TYSPR06MB6433688AD5344663BBA14BF1AA562@TYSPR06MB6433.apcprd06.prod.outlook.com \
    --to=nuomi2021@gmail.com \
    --cc=ffmpeg-devel@ffmpeg.org \
    --cc=toqsxw@outlook.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git