mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-24 13:56:33 +02:00
avcodec/vvcdec: add Intra Block Copy parser
Co-authored-by: Nuo Mi <nuomi2021@gmail.com>
This commit is contained in:
parent
422e8a877b
commit
9481887755
@ -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;
|
||||
|
||||
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);
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user