Files
Frank Plowman cce879874c lavc/vvc: Use correct wrapping arithmetic for MVs
In the VVC spec, MVs are computed using 18-bit signed arithmetic with
normative wrapping.  In H.266(V3), the wrapping behaviour is defined
in Eqs. (465)--(468) for block-wide MVs, Eqs. (658)--(661) for affine
CPMVs and (1086)--(1089) for IBC BVs.  This wrapping was only
partially implemented in the VVC decoder before this patch.
Specifically, only eqs. (1087) and (1089) were implemented. This patch
implements the full wrapping as its own function `ff_vvc_wrap_mv`, and
uses it for all sorts of MVs.

Fixes mismatches and signed integer overflows in bitstreams with
unusually large MVs.

Signed-off-by: Frank Plowman <post@frankplowman.com>
2026-10-04 20:27:30 +01:00

50 lines
2.4 KiB
C

/*
* VVC motion vector decoder
*
* Copyright (C) 2023 Nuo Mi
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVCODEC_VVC_MVS_H
#define AVCODEC_VVC_MVS_H
#include "ctu.h"
void ff_vvc_round_mv(Mv *mv, int lshift, int rshift);
void ff_vvc_clip_mv(Mv *mv);
void ff_vvc_wrap_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);
int 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);
int 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);
void ff_vvc_store_mv(const VVCLocalContext *lc, const MotionInfo *mi);
void ff_vvc_store_mvf(const VVCLocalContext *lc, const MvField *mvf);
void ff_vvc_store_gpm_mvf(const VVCLocalContext *lc, const PredictionUnit* pu);
void ff_vvc_update_hmvp(VVCLocalContext *lc, const MotionInfo *mi);
int ff_vvc_no_backward_pred_flag(const VVCLocalContext *lc);
MvField* ff_vvc_get_mvf(const VVCFrameContext *fc, const int x0, const int y0);
void ff_vvc_set_mvf(const VVCLocalContext *lc, const int x0, const int y0, const int w, const int h, const MvField *mvf);
void ff_vvc_set_intra_mvf(const VVCLocalContext *lc, bool dmvr, PredFlag pf, bool ciip_flag);
#endif //AVCODEC_VVC_MVS_H