[FFmpeg-devel] [PATCH] lavc/vvc: Remove left shifts of negative values
post at frankplowman.com
post at frankplowman.com
Sat Jan 20 16:51:04 EET 2024
From: Frank Plowman <post at frankplowman.com>
VVC specifies << as arithmetic left shift, i.e. x << y is equivalent to
x * pow2(y). C's << on the other hand has UB if x is negative. This
patch removes all UB resulting from this, mostly by replacing x << y
with x * (1 << y), but there are also a couple places where the OOP was
changed instead.
Signed-off-by: Frank Plowman <post at frankplowman.com>
---
libavcodec/vvc/vvc_ctu.c | 4 +--
libavcodec/vvc/vvc_filter.c | 4 +--
libavcodec/vvc/vvc_inter.c | 24 +++++++--------
libavcodec/vvc/vvc_inter_template.c | 4 +--
libavcodec/vvc/vvc_mvs.c | 46 ++++++++++++++---------------
5 files changed, 41 insertions(+), 41 deletions(-)
diff --git a/libavcodec/vvc/vvc_ctu.c b/libavcodec/vvc/vvc_ctu.c
index dd3c8884cb..307bc3490e 100644
--- a/libavcodec/vvc/vvc_ctu.c
+++ b/libavcodec/vvc/vvc_ctu.c
@@ -1554,8 +1554,8 @@ static void mvp_add_difference(MotionInfo *mi, const int num_cp_mv,
if (mi->pred_flag & mask) {
for (int j = 0; j < num_cp_mv; j++) {
const Mv *mvd = &mvds[i][j];
- mi->mv[i][j].x += mvd->x << amvr_shift;
- mi->mv[i][j].y += mvd->y << amvr_shift;
+ mi->mv[i][j].x += mvd->x * (1 << amvr_shift);
+ mi->mv[i][j].y += mvd->y * (1 << amvr_shift);
}
}
}
diff --git a/libavcodec/vvc/vvc_filter.c b/libavcodec/vvc/vvc_filter.c
index e5cd89b8a3..cebc02fd9f 100644
--- a/libavcodec/vvc/vvc_filter.c
+++ b/libavcodec/vvc/vvc_filter.c
@@ -1115,12 +1115,12 @@ static void alf_prepare_buffer(VVCFrameContext *fc, uint8_t *_dst, const uint8_t
copy_ctb(_dst, _src, width << ps, height, dst_stride, src_stride);
//top
- src = fc->tab.alf_pixel_buffer_h[c_idx][1] + (((border_pixels * (y_ctb - 1)) * w + x) << ps);
+ src = fc->tab.alf_pixel_buffer_h[c_idx][1] + (((border_pixels * w) << ps) * (y_ctb - 1) + (x << ps));
dst = _dst - border_pixels * dst_stride;
alf_fill_border_h(dst, dst_stride, src, w << ps, _dst, width, border_pixels, ps, edges[TOP]);
//bottom
- src = fc->tab.alf_pixel_buffer_h[c_idx][0] + ((border_pixels * (y_ctb + 1) * w + x) << ps);
+ src = fc->tab.alf_pixel_buffer_h[c_idx][0] + (((border_pixels * w) << ps) * (y_ctb + 1) + (x << ps));
dst = _dst + height * dst_stride;
alf_fill_border_h(dst, dst_stride, src, w << ps, _dst + (height - 1) * dst_stride, width, border_pixels, ps, edges[BOTTOM]);
diff --git a/libavcodec/vvc/vvc_inter.c b/libavcodec/vvc/vvc_inter.c
index 9b2925f60c..e05f3db93e 100644
--- a/libavcodec/vvc/vvc_inter.c
+++ b/libavcodec/vvc/vvc_inter.c
@@ -190,7 +190,7 @@ static void luma_mc(VVCLocalContext *lc, int16_t *dst, const AVFrame *ref, const
x_off += mv->x >> 4;
y_off += mv->y >> 4;
- src += y_off * src_stride + (x_off << fc->ps.sps->pixel_shift);
+ src += y_off * src_stride + (x_off * (1 << fc->ps.sps->pixel_shift));
EMULATED_EDGE_LUMA(lc->edge_emu_buffer, &src, &src_stride, x_off, y_off);
@@ -213,7 +213,7 @@ static void chroma_mc(VVCLocalContext *lc, int16_t *dst, const AVFrame *ref, con
x_off += mv->x >> (4 + hs);
y_off += mv->y >> (4 + vs);
- src += y_off * src_stride + (x_off << fc->ps.sps->pixel_shift);
+ src += y_off * src_stride + (x_off * (1 << fc->ps.sps->pixel_shift));
EMULATED_EDGE_CHROMA(lc->edge_emu_buffer, &src, &src_stride, x_off, y_off);
fc->vvcdsp.inter.put[CHROMA][idx][!!my][!!mx](dst, src, src_stride, block_h, hf, vf, block_w);
@@ -237,7 +237,7 @@ static void luma_mc_uni(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_s
x_off += mv->x >> 4;
y_off += mv->y >> 4;
- src += y_off * src_stride + (x_off << fc->ps.sps->pixel_shift);
+ src += y_off * src_stride + (x_off * (1 << fc->ps.sps->pixel_shift));
EMULATED_EDGE_LUMA(lc->edge_emu_buffer, &src, &src_stride, x_off, y_off);
@@ -270,7 +270,7 @@ static void luma_mc_bi(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_st
const int ox = x_off + (mv->x >> 4);
const int oy = y_off + (mv->y >> 4);
ptrdiff_t src_stride = ref[i]->linesize[0];
- const uint8_t *src = ref[i]->data[0] + oy * src_stride + (ox << fc->ps.sps->pixel_shift);
+ const uint8_t *src = ref[i]->data[0] + oy * src_stride + (ox * (1 << fc->ps.sps->pixel_shift));
const int8_t *hf = ff_vvc_inter_luma_filters[hf_idx][mx];
const int8_t *vf = ff_vvc_inter_luma_filters[vf_idx][my];
@@ -314,7 +314,7 @@ static void chroma_mc_uni(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst
x_off += mv->x >> (4 + hs);
y_off += mv->y >> (4 + vs);
- src += y_off * src_stride + (x_off << fc->ps.sps->pixel_shift);
+ src += y_off * src_stride + (x_off * (1 << fc->ps.sps->pixel_shift));
EMULATED_EDGE_CHROMA(lc->edge_emu_buffer, &src, &src_stride, x_off, y_off);
@@ -348,7 +348,7 @@ static void chroma_mc_bi(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_
const int ox = x_off + (mv->x >> (4 + hs));
const int oy = y_off + (mv->y >> (4 + vs));
ptrdiff_t src_stride = ref[i]->linesize[c_idx];
- const uint8_t *src = ref[i]->data[c_idx] + oy * src_stride + (ox << fc->ps.sps->pixel_shift);
+ const uint8_t *src = ref[i]->data[c_idx] + oy * src_stride + (ox * (1 << fc->ps.sps->pixel_shift));
const int8_t *hf = ff_vvc_inter_chroma_filters[hf_idx][mx];
const int8_t *vf = ff_vvc_inter_chroma_filters[vf_idx][my];
if (dmvr_flag) {
@@ -386,7 +386,7 @@ static void luma_prof_uni(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst
x_off += mv->x >> 4;
y_off += mv->y >> 4;
- src += y_off * src_stride + (x_off << fc->ps.sps->pixel_shift);
+ src += y_off * src_stride + (x_off * (1 << fc->ps.sps->pixel_shift));
EMULATED_EDGE_LUMA(lc->edge_emu_buffer, &src, &src_stride, x_off, y_off);
if (cb_prof_flag) {
@@ -424,7 +424,7 @@ static void luma_prof_bi(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_
const int ox = x_off + (mv->x >> 4);
const int oy = y_off + (mv->y >> 4);
ptrdiff_t src_stride = ref[i]->linesize[0];
- const uint8_t *src = ref[i]->data[0] + oy * src_stride + (ox << fc->ps.sps->pixel_shift);
+ const uint8_t *src = ref[i]->data[0] + oy * src_stride + (ox * (1 << fc->ps.sps->pixel_shift));
const int8_t *hf = ff_vvc_inter_luma_filters[2][mx];
const int8_t *vf = ff_vvc_inter_luma_filters[2][my];
@@ -654,7 +654,7 @@ static int parametric_mv_refine(const int *sad, const int stride)
else if (sad_plus == sad_center)
dmvc = 8;
else {
- int num = ( sad_minus - sad_plus ) << 4;
+ int num = ( sad_minus - sad_plus ) * (1 << 4);
int sign_num = 0;
int quotient = 0;
int counter = 3;
@@ -704,7 +704,7 @@ static void dmvr_mv_refine(VVCLocalContext *lc, MvField *mvf, MvField *orig_mv,
const int ox = x_off + (mv->x >> 4) - sr_range;
const int oy = y_off + (mv->y >> 4) - sr_range;
ptrdiff_t src_stride = ref[i]->linesize[LUMA];
- const uint8_t *src = ref[i]->data[LUMA] + oy * src_stride + (ox << fc->ps.sps->pixel_shift);
+ const uint8_t *src = ref[i]->data[LUMA] + oy * src_stride + (ox * (1 << fc->ps.sps->pixel_shift));
EMULATED_EDGE_BILINEAR(lc->edge_emu_buffer, &src, &src_stride, ox, oy);
fc->vvcdsp.inter.dmvr[!!my][!!mx](tmp[i], src, src_stride, pred_h, mx, my, pred_w);
}
@@ -728,8 +728,8 @@ static void dmvr_mv_refine(VVCLocalContext *lc, MvField *mvf, MvField *orig_mv,
}
}
}
- dmv[0] = (min_dx - sr_range) << 4;
- dmv[1] = (min_dy - sr_range) << 4;
+ dmv[0] = (min_dx - sr_range) * (1 << 4);
+ dmv[1] = (min_dy - sr_range) * (1 << 4);
if (min_dx != 0 && min_dx != 4 && min_dy != 0 && min_dy != 4) {
dmv[0] += parametric_mv_refine(&sad[min_dy][min_dx], 1);
dmv[1] += parametric_mv_refine(&sad[min_dy][min_dx], SAD_ARRAY_SIZE);
diff --git a/libavcodec/vvc/vvc_inter_template.c b/libavcodec/vvc/vvc_inter_template.c
index b67b66a2dc..7160907778 100644
--- a/libavcodec/vvc/vvc_inter_template.c
+++ b/libavcodec/vvc/vvc_inter_template.c
@@ -817,8 +817,8 @@ static void FUNC(derive_bdof_vx_vy)(const int16_t *_src0, const int16_t *_src1,
src0 += MAX_PB_SIZE;
src1 += MAX_PB_SIZE;
}
- *vx = sgx2 > 0 ? av_clip((sgxdi << 2) >> av_log2(sgx2) , -thres + 1, thres - 1) : 0;
- *vy = sgy2 > 0 ? av_clip(((sgydi << 2) - ((*vx * sgxgy) >> 1)) >> av_log2(sgy2), -thres + 1, thres - 1) : 0;
+ *vx = sgx2 > 0 ? av_clip((sgxdi * (1 << 2)) >> av_log2(sgx2) , -thres + 1, thres - 1) : 0;
+ *vy = sgy2 > 0 ? av_clip(((sgydi * (1 << 2)) - ((*vx * sgxgy) >> 1)) >> av_log2(sgy2), -thres + 1, thres - 1) : 0;
}
static void FUNC(apply_bdof_min_block)(pixel* dst, const ptrdiff_t dst_stride, const int16_t *src0, const int16_t *src1,
diff --git a/libavcodec/vvc/vvc_mvs.c b/libavcodec/vvc/vvc_mvs.c
index 81e73fe746..a3861b5b1a 100644
--- a/libavcodec/vvc/vvc_mvs.c
+++ b/libavcodec/vvc/vvc_mvs.c
@@ -60,7 +60,7 @@ static av_always_inline void mv_compression(Mv *motion)
for (int i = 0; i < 2; i++) {
const int s = mv[i] >> 17;
const int f = av_log2((mv[i] ^ s) | 31) - 4;
- const int mask = (-1 << f) >> 1;
+ const int mask = (-1 * (1 << f)) >> 1;
const int round = (1 << f) >> 2;
mv[i] = (mv[i] + round) & mask;
}
@@ -342,17 +342,17 @@ static void init_subblock_params(SubblockParams *sp, const MotionInfo* mi,
const int log2_cbh = av_log2(cb_height);
const Mv* cp_mv = mi->mv[lx];
const int num_cp_mv = mi->motion_model_idc + 1;
- sp->d_hor_x = (cp_mv[1].x - cp_mv[0].x) << (MAX_CU_DEPTH - log2_cbw);
- sp->d_ver_x = (cp_mv[1].y - cp_mv[0].y) << (MAX_CU_DEPTH - log2_cbw);
+ sp->d_hor_x = (cp_mv[1].x - cp_mv[0].x) * (1 << (MAX_CU_DEPTH - log2_cbw));
+ sp->d_ver_x = (cp_mv[1].y - cp_mv[0].y) * (1 << (MAX_CU_DEPTH - log2_cbw));
if (num_cp_mv == 3) {
- sp->d_hor_y = (cp_mv[2].x - cp_mv[0].x) << (MAX_CU_DEPTH - log2_cbh);
- sp->d_ver_y = (cp_mv[2].y - cp_mv[0].y) << (MAX_CU_DEPTH - log2_cbh);
+ sp->d_hor_y = (cp_mv[2].x - cp_mv[0].x) * (1 << (MAX_CU_DEPTH - log2_cbh));
+ sp->d_ver_y = (cp_mv[2].y - cp_mv[0].y) * (1 << (MAX_CU_DEPTH - log2_cbh));
} else {
sp->d_hor_y = -sp->d_ver_x;
sp->d_ver_y = sp->d_hor_x;
}
- sp->mv_scale_hor = (cp_mv[0].x) << MAX_CU_DEPTH;
- sp->mv_scale_ver = (cp_mv[0].y) << MAX_CU_DEPTH;
+ sp->mv_scale_hor = (cp_mv[0].x) * (1 << MAX_CU_DEPTH);
+ sp->mv_scale_ver = (cp_mv[0].y) * (1 << MAX_CU_DEPTH);
sp->cb_width = cb_width;
sp->cb_height = cb_height;
sp->is_fallback = is_fallback_mode(sp, mi->pred_flag);
@@ -368,8 +368,8 @@ static void derive_subblock_diff_mvs(const VVCLocalContext *lc, PredictionUnit*
for (int x = 0; x < AFFINE_MIN_BLOCK_SIZE; x++) {
for (int y = 0; y < AFFINE_MIN_BLOCK_SIZE; y++) {
Mv diff;
- diff.x = x * (sp->d_hor_x << 2) + y * (sp->d_hor_y << 2) - pos_offset_x;
- diff.y = x * (sp->d_ver_x << 2) + y * (sp->d_ver_y << 2) - pos_offset_y;
+ diff.x = x * (sp->d_hor_x * (1 << 2)) + y * (sp->d_hor_y * (1 << 2)) - pos_offset_x;
+ diff.y = x * (sp->d_ver_x * (1 << 2)) + y * (sp->d_ver_y * (1 << 2)) - pos_offset_y;
ff_vvc_round_mv(&diff, 0, 8);
pu->diff_mv_x[lx][AFFINE_MIN_BLOCK_SIZE * y + x] = av_clip(diff.x, -dmv_limit + 1, dmv_limit - 1);
pu->diff_mv_y[lx][AFFINE_MIN_BLOCK_SIZE * y + x] = av_clip(diff.y, -dmv_limit + 1, dmv_limit - 1);
@@ -467,8 +467,8 @@ void ff_vvc_store_gpm_mvf(const VVCLocalContext *lc, const PredictionUnit *pu)
for (int y = 0; y < cu->cb_height; y += block_size) {
for (int x = 0; x < cu->cb_width; x += block_size) {
- const int motion_idx = (((x + offset_x) << 1) + 5) * displacement_x +
- (((y + offset_y) << 1) + 5) * displacement_y;
+ const int motion_idx = (((x + offset_x) * (1 << 1)) + 5) * displacement_x +
+ (((y + offset_y) * (1 << 1)) + 5) * displacement_y;
const int s_type = FFABS(motion_idx) < 32 ? 2 : (motion_idx <= 0 ? (1 - is_flip) : is_flip);
const int pred_flag = pu->gpm_mv[0].pred_flag | pu->gpm_mv[1].pred_flag;
const int x0 = cu->x0 + x;
@@ -867,14 +867,14 @@ static void affine_cps_from_nb(const VVCLocalContext *lc,
l = &TAB_CP_MV(lx, x_nb, y_nb);
r = &TAB_CP_MV(lx, x_nb + nbw - 1, y_nb) + 1;
}
- mv_scale_hor = l->x << 7;
- mv_scale_ver = l->y << 7;
- d_hor_x = (r->x - l->x) << (7 - log2_nbw);
- d_ver_x = (r->y - l->y) << (7 - log2_nbw);
+ mv_scale_hor = l->x * (1 << 7);
+ mv_scale_ver = l->y * (1 << 7);
+ d_hor_x = (r->x - l->x) * (1 << (7 - log2_nbw));
+ d_ver_x = (r->y - l->y) * (1 << (7 - log2_nbw));
if (!is_ctb_boundary && motion_model_idc_nb == MOTION_6_PARAMS_AFFINE) {
const Mv* lb = &TAB_CP_MV(lx, x_nb, y_nb + nbh - 1) + 2;
- d_hor_y = (lb->x - l->x) << (7 - log2_nbh);
- d_ver_y = (lb->y - l->y) << (7 - log2_nbh);
+ d_hor_y = (lb->x - l->x) * (1 << (7 - log2_nbh));
+ d_ver_y = (lb->y - l->y) * (1 << (7 - log2_nbh));
} else {
d_hor_y = -d_ver_x;
d_ver_y = d_hor_x;
@@ -1242,8 +1242,8 @@ static int affine_merge_const6(const MvField* c0, const MvField* c2, const int c
mi->pred_flag |= mask;
mi->ref_idx[i] = c0->ref_idx[i];
mi->mv[i][0] = c0->mv[i];
- mi->mv[i][1].x = (c0->mv[i].x << 7) + ((c2->mv[i].y - c0->mv[i].y) << shift);
- mi->mv[i][1].y = (c0->mv[i].y << 7) - ((c2->mv[i].x - c0->mv[i].x) << shift);
+ mi->mv[i][1].x = (c0->mv[i].x * (1 << 7)) + ((c2->mv[i].y - c0->mv[i].y) * (1 << shift));
+ mi->mv[i][1].y = (c0->mv[i].y * (1 << 7)) - ((c2->mv[i].x - c0->mv[i].x) * (1 << shift));
ff_vvc_round_mv(&mi->mv[i][1], 0, 7);
ff_vvc_clip_mv(&mi->mv[i][1]);
}
@@ -1736,11 +1736,11 @@ void ff_vvc_round_mv(Mv *mv, const int lshift, const int rshift)
{
if (rshift) {
const int offset = 1 << (rshift - 1);
- mv->x = ((mv->x + offset - (mv->x >= 0)) >> rshift) << lshift;
- mv->y = ((mv->y + offset - (mv->y >= 0)) >> rshift) << lshift;
+ mv->x = ((mv->x + offset - (mv->x >= 0)) >> rshift) * (1 << lshift);
+ mv->y = ((mv->y + offset - (mv->y >= 0)) >> rshift) * (1 << lshift);
} else {
- mv->x = mv->x << lshift;
- mv->y = mv->y << lshift;
+ mv->x = mv->x * (1 << lshift);
+ mv->y = mv->y * (1 << lshift);
}
}
--
2.43.0
More information about the ffmpeg-devel
mailing list