ffmpeg-devel
Threads by month
- ----- 2026 -----
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
June 2026
- 13 participants
- 113 discussions
[PR] avfilter: avoid signed overflow in slice boundary calculation (PR #23399)
by michaelni 08 Jun '26
by michaelni 08 Jun '26
08 Jun '26
PR #23399 opened by michaelni
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23399
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23399.patch
The height*jobnr computations can overflow, this PR fixes that
From a99f6176b05ccc37a9b1177bc6167dcc23711f0c Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <michael(a)niedermayer.cc>
Date: Sat, 6 Jun 2026 21:02:16 +0200
Subject: [PATCH 1/3] avfilter/estdif: avoid signed overflow in slice boundary
calculation
deinterlace_slice() computed per-thread row boundaries with int
multiplication height * (jobnr + 1). With a tall frame and many filter
threads the product overflows signed int before the division by nb_jobs.
Use int64_t for the intermediate product before converting back to int
row indices.
Found-by: Kery (Qi Kery <qikeyu2001(a)outlook.com>)
Signed-off-by: Michael Niedermayer <michael(a)niedermayer.cc>
---
libavfilter/vf_estdif.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libavfilter/vf_estdif.c b/libavfilter/vf_estdif.c
index b8289a6e96..6fdfe19e7e 100644
--- a/libavfilter/vf_estdif.c
+++ b/libavfilter/vf_estdif.c
@@ -354,8 +354,8 @@ static int deinterlace_slice(AVFilterContext *ctx, void *arg,
const int height = s->planeheight[plane];
const int src_linesize = in->linesize[plane];
const int dst_linesize = out->linesize[plane];
- const int start = (height * jobnr) / nb_jobs;
- const int end = (height * (jobnr+1)) / nb_jobs;
+ const int start = (int)((int64_t)height * jobnr / nb_jobs);
+ const int end = (int)((int64_t)height * (jobnr + 1) / nb_jobs);
const uint8_t *prev_line, *prev2_line, *next_line, *next2_line, *in_line;
const uint8_t *prev3_line, *next3_line;
uint8_t *out_line;
--
2.52.0
From 92fffa264be4aef8c0a1c0f3b211ec11a9945c4f Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <michael(a)niedermayer.cc>
Date: Sun, 7 Jun 2026 21:38:20 +0200
Subject: [PATCH 2/3] avfilter: add ff_slice_pos() helper for slice boundaries
Slice based filter workers compute their per-thread row/sample/channel
boundaries as total * jobnr / nb_jobs. The total * jobnr product is
evaluated in int and overflows signed int for large dimensions and many
slice threads, before the division by nb_jobs brings it back in range.
---
libavfilter/filters.h | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/libavfilter/filters.h b/libavfilter/filters.h
index a152be4d47..57540d7698 100644
--- a/libavfilter/filters.h
+++ b/libavfilter/filters.h
@@ -750,6 +750,21 @@ int ff_filter_process_command(AVFilterContext *ctx, const char *cmd,
*/
int ff_filter_get_nb_threads(AVFilterContext *ctx) av_pure;
+/**
+ * Compute the boundary index for a slice when work of size total is split
+ * into nb_jobs slices. Returns the first index of slice jobnr, so the slice
+ * jobnr covers [ff_slice_pos(total, jobnr, nb_jobs),
+ * ff_slice_pos(total, jobnr + 1, nb_jobs)).
+ *
+ * The multiplication is performed in 64bit to avoid signed overflow of the
+ * total * jobnr intermediate that would occur for large dimensions and many
+ * slice threads.
+ */
+static inline int ff_slice_pos(int total, int jobnr, int nb_jobs)
+{
+ return (int)((int64_t)total * jobnr / nb_jobs);
+}
+
/**
* Send a frame of data to the next filter.
*
--
2.52.0
From 38aea1750ae69d971d1ce5a72bd626fe02cb0eb0 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <michael(a)niedermayer.cc>
Date: Sun, 7 Jun 2026 21:38:26 +0200
Subject: [PATCH 3/3] avfilter: use ff_slice_pos() for per-slice boundary
computation
This is a behavior preserving change for all non-overflowing cases.
Signed-off-by: Michael Niedermayer <michael(a)niedermayer.cc>
---
libavfilter/aap_template.c | 4 +-
libavfilter/adynamicequalizer_template.c | 4 +-
libavfilter/af_acrossover.c | 4 +-
libavfilter/af_adecorrelate.c | 4 +-
libavfilter/af_adenorm.c | 4 +-
libavfilter/af_adrc.c | 4 +-
libavfilter/af_aemphasis.c | 4 +-
libavfilter/af_afftdn.c | 4 +-
libavfilter/af_afftfilt.c | 8 +-
libavfilter/af_afir.c | 4 +-
libavfilter/af_afreqshift.c | 4 +-
libavfilter/af_anequalizer.c | 4 +-
libavfilter/af_apsyclip.c | 4 +-
libavfilter/af_arnndn.c | 4 +-
libavfilter/af_asdr.c | 12 +--
libavfilter/af_asoftclip.c | 4 +-
libavfilter/af_aspectralstats.c | 4 +-
libavfilter/af_astats.c | 4 +-
libavfilter/af_asubboost.c | 4 +-
libavfilter/af_asupercut.c | 4 +-
libavfilter/af_atilt.c | 4 +-
libavfilter/af_biquads.c | 4 +-
libavfilter/af_crystalizer.c | 4 +-
libavfilter/af_dynaudnorm.c | 8 +-
libavfilter/af_surround.c | 8 +-
libavfilter/anlms_template.c | 4 +-
libavfilter/arls_template.c | 4 +-
libavfilter/avf_avectorscope.c | 4 +-
libavfilter/avf_showcwt.c | 12 +--
libavfilter/colorchannelmixer_template.c | 8 +-
libavfilter/vf_amplify.c | 4 +-
libavfilter/vf_atadenoise.c | 4 +-
libavfilter/vf_backgroundkey.c | 8 +-
libavfilter/vf_bilateral.c | 16 ++--
libavfilter/vf_blackdetect.c | 4 +-
libavfilter/vf_blackframe.c | 4 +-
libavfilter/vf_blend.c | 4 +-
libavfilter/vf_bm3d.c | 4 +-
libavfilter/vf_bwdif.c | 2 +-
libavfilter/vf_cas.c | 8 +-
libavfilter/vf_chromakey.c | 16 ++--
libavfilter/vf_chromanr.c | 8 +-
libavfilter/vf_chromashift.c | 16 ++--
libavfilter/vf_colorbalance.c | 16 ++--
libavfilter/vf_colorconstancy.c | 20 ++---
libavfilter/vf_colorcontrast.c | 16 ++--
libavfilter/vf_colorcorrect.c | 24 +++---
libavfilter/vf_colordetect.c | 8 +-
libavfilter/vf_colorize.c | 16 ++--
libavfilter/vf_colorkey.c | 8 +-
libavfilter/vf_colorlevels.c | 4 +-
libavfilter/vf_colormap.c | 4 +-
libavfilter/vf_colormatrix.c | 16 ++--
libavfilter/vf_colortemperature.c | 20 ++---
libavfilter/vf_convolution.c | 4 +-
libavfilter/vf_convolve.c | 28 +++----
libavfilter/vf_corr.c | 8 +-
libavfilter/vf_curves.c | 8 +-
libavfilter/vf_datascope.c | 12 +--
libavfilter/vf_dctdnoiz.c | 4 +-
libavfilter/vf_deband.c | 16 ++--
libavfilter/vf_dedot.c | 8 +-
libavfilter/vf_despill.c | 4 +-
libavfilter/vf_displace.c | 8 +-
libavfilter/vf_epx.c | 8 +-
libavfilter/vf_estdif.c | 4 +-
libavfilter/vf_exposure.c | 4 +-
libavfilter/vf_fade.c | 28 +++----
libavfilter/vf_fftdnoiz.c | 4 +-
libavfilter/vf_fftfilt.c | 36 ++++-----
libavfilter/vf_gblur.c | 12 +--
libavfilter/vf_geq.c | 4 +-
libavfilter/vf_grayworld.c | 8 +-
libavfilter/vf_guided.c | 4 +-
libavfilter/vf_hqx.c | 4 +-
libavfilter/vf_hsvkey.c | 16 ++--
libavfilter/vf_huesaturation.c | 4 +-
libavfilter/vf_identity.c | 8 +-
libavfilter/vf_lagfun.c | 4 +-
libavfilter/vf_lensfun.c | 8 +-
libavfilter/vf_limitdiff.c | 4 +-
libavfilter/vf_limiter.c | 4 +-
libavfilter/vf_lumakey.c | 8 +-
libavfilter/vf_lut.c | 8 +-
libavfilter/vf_lut2.c | 4 +-
libavfilter/vf_lut3d.c | 24 +++---
libavfilter/vf_maskedclamp.c | 4 +-
libavfilter/vf_maskedmerge.c | 4 +-
libavfilter/vf_maskedminmax.c | 4 +-
libavfilter/vf_maskedthreshold.c | 4 +-
libavfilter/vf_maskfun.c | 4 +-
libavfilter/vf_median.c | 4 +-
libavfilter/vf_mix.c | 8 +-
libavfilter/vf_monochrome.c | 16 ++--
libavfilter/vf_morpho.c | 8 +-
libavfilter/vf_multiply.c | 4 +-
libavfilter/vf_negate.c | 4 +-
libavfilter/vf_neighbor.c | 4 +-
libavfilter/vf_nlmeans.c | 4 +-
libavfilter/vf_nnedi.c | 4 +-
libavfilter/vf_noise.c | 4 +-
libavfilter/vf_opencolorio.c | 5 +-
libavfilter/vf_overlay.c | 12 +--
libavfilter/vf_photosensitivity.c | 8 +-
libavfilter/vf_pixelize.c | 8 +-
libavfilter/vf_premultiply.c | 4 +-
libavfilter/vf_pseudocolor.c | 6 +-
libavfilter/vf_psnr.c | 4 +-
libavfilter/vf_remap.c | 8 +-
libavfilter/vf_removegrain.c | 4 +-
libavfilter/vf_scroll.c | 4 +-
libavfilter/vf_selectivecolor.c | 4 +-
libavfilter/vf_shear.c | 8 +-
libavfilter/vf_shufflepixels.c | 12 +--
libavfilter/vf_signalstats.c | 32 ++++----
libavfilter/vf_ssim.c | 8 +-
libavfilter/vf_stereo3d.c | 4 +-
libavfilter/vf_super2xsai.c | 4 +-
libavfilter/vf_threshold.c | 4 +-
libavfilter/vf_thumbnail.c | 8 +-
libavfilter/vf_tonemap.c | 4 +-
libavfilter/vf_transpose.c | 4 +-
libavfilter/vf_unsharp.c | 4 +-
libavfilter/vf_v360.c | 8 +-
libavfilter/vf_varblur.c | 4 +-
libavfilter/vf_vibrance.c | 16 ++--
libavfilter/vf_vif.c | 4 +-
libavfilter/vf_w3fdif.c | 4 +-
libavfilter/vf_waveform.c | 96 ++++++++++++------------
libavfilter/vf_weave.c | 4 +-
libavfilter/vf_xbr.c | 4 +-
libavfilter/vf_xfade.c | 4 +-
libavfilter/vf_xmedian.c | 4 +-
libavfilter/vf_yadif.c | 4 +-
libavfilter/vf_yaepblur.c | 12 +--
libavfilter/x86/vf_lut3d_init.c | 5 +-
136 files changed, 560 insertions(+), 558 deletions(-)
diff --git a/libavfilter/aap_template.c b/libavfilter/aap_template.c
index 0e0580fb32..a8cb18f260 100644
--- a/libavfilter/aap_template.c
+++ b/libavfilter/aap_template.c
@@ -196,8 +196,8 @@ static int fn(filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int n
{
AudioAPContext *s = ctx->priv;
AVFrame *out = arg;
- const int start = (out->ch_layout.nb_channels * jobnr) / nb_jobs;
- const int end = (out->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(out->ch_layout.nb_channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(out->ch_layout.nb_channels, jobnr + 1, nb_jobs);
for (int c = start; c < end; c++) {
const ftype *input = (const ftype *)s->frame[0]->extended_data[c];
diff --git a/libavfilter/adynamicequalizer_template.c b/libavfilter/adynamicequalizer_template.c
index 4eb2489cd6..a03d656416 100644
--- a/libavfilter/adynamicequalizer_template.c
+++ b/libavfilter/adynamicequalizer_template.c
@@ -269,8 +269,8 @@ static int fn(filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int n
const ftype tqfactor = s->tqfactor;
const ftype itqfactor = ONE / tqfactor;
const ftype fg = TAN(M_PI * tfrequency / sample_rate);
- const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs;
- const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(in->ch_layout.nb_channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(in->ch_layout.nb_channels, jobnr + 1, nb_jobs);
const int is_disabled = ctx->is_disabled;
const int detection = s->detection;
const int tftype = s->tftype;
diff --git a/libavfilter/af_acrossover.c b/libavfilter/af_acrossover.c
index fedf281d58..8b2786bae2 100644
--- a/libavfilter/af_acrossover.c
+++ b/libavfilter/af_acrossover.c
@@ -397,8 +397,8 @@ static int filter_channels_## name(AVFilterContext *ctx, void *arg, int jobnr, i
AudioCrossoverContext *s = ctx->priv; \
AVFrame *in = arg; \
AVFrame **frames = s->frames; \
- const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; \
- const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; \
+ const int start = ff_slice_pos(in->ch_layout.nb_channels, jobnr, nb_jobs); \
+ const int end = ff_slice_pos(in->ch_layout.nb_channels, jobnr + 1, nb_jobs); \
const int nb_samples = in->nb_samples; \
const int nb_outs = ctx->nb_outputs; \
const int first_order = s->first_order; \
diff --git a/libavfilter/af_adecorrelate.c b/libavfilter/af_adecorrelate.c
index 8991bf2077..40b1ab0af4 100644
--- a/libavfilter/af_adecorrelate.c
+++ b/libavfilter/af_adecorrelate.c
@@ -161,8 +161,8 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
ThreadData *td = arg;
AVFrame *out = td->out;
AVFrame *in = td->in;
- const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs;
- const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(in->ch_layout.nb_channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(in->ch_layout.nb_channels, jobnr + 1, nb_jobs);
for (int ch = start; ch < end; ch++)
s->filter_channel(ctx, ch, in, out);
diff --git a/libavfilter/af_adenorm.c b/libavfilter/af_adenorm.c
index 0d61eed1dd..e05b15b03a 100644
--- a/libavfilter/af_adenorm.c
+++ b/libavfilter/af_adenorm.c
@@ -188,8 +188,8 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
ThreadData *td = arg;
AVFrame *out = td->out;
AVFrame *in = td->in;
- const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs;
- const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(in->ch_layout.nb_channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(in->ch_layout.nb_channels, jobnr + 1, nb_jobs);
for (int ch = start; ch < end; ch++) {
s->filter[s->type](ctx, out->extended_data[ch],
diff --git a/libavfilter/af_adrc.c b/libavfilter/af_adrc.c
index 9e3becdf2e..690158e382 100644
--- a/libavfilter/af_adrc.c
+++ b/libavfilter/af_adrc.c
@@ -349,8 +349,8 @@ static int drc_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
AudioDRCContext *s = ctx->priv;
AVFrame *in = s->in;
AVFrame *out = arg;
- const int start = (out->ch_layout.nb_channels * jobnr) / nb_jobs;
- const int end = (out->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(out->ch_layout.nb_channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(out->ch_layout.nb_channels, jobnr + 1, nb_jobs);
for (int ch = start; ch < end; ch++)
drc_channel(ctx, in, out, ch);
diff --git a/libavfilter/af_aemphasis.c b/libavfilter/af_aemphasis.c
index d35111f89f..abc42207a5 100644
--- a/libavfilter/af_aemphasis.c
+++ b/libavfilter/af_aemphasis.c
@@ -105,8 +105,8 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
ThreadData *td = arg;
AVFrame *out = td->out;
AVFrame *in = td->in;
- const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs;
- const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(in->ch_layout.nb_channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(in->ch_layout.nb_channels, jobnr + 1, nb_jobs);
for (int ch = start; ch < end; ch++) {
const double *src = (const double *)in->extended_data[ch];
diff --git a/libavfilter/af_afftdn.c b/libavfilter/af_afftdn.c
index e97dfe1f0d..6486517781 100644
--- a/libavfilter/af_afftdn.c
+++ b/libavfilter/af_afftdn.c
@@ -1052,8 +1052,8 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_job
{
AudioFFTDeNoiseContext *s = ctx->priv;
AVFrame *in = arg;
- const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs;
- const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(in->ch_layout.nb_channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(in->ch_layout.nb_channels, jobnr + 1, nb_jobs);
const int window_length = s->window_length;
const double *window = s->window;
diff --git a/libavfilter/af_afftfilt.c b/libavfilter/af_afftfilt.c
index 7b68b19b72..926ce96e05 100644
--- a/libavfilter/af_afftfilt.c
+++ b/libavfilter/af_afftfilt.c
@@ -234,8 +234,8 @@ static int tx_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
{
AFFTFiltContext *s = ctx->priv;
const int channels = s->channels;
- const int start = (channels * jobnr) / nb_jobs;
- const int end = (channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(channels, jobnr + 1, nb_jobs);
for (int ch = start; ch < end; ch++) {
AVComplexFloat *fft_in = s->fft_in[ch];
@@ -254,8 +254,8 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_job
const float *window_lut = s->window_func_lut;
const float f = sqrtf(1.f - s->overlap);
const int channels = s->channels;
- const int start = (channels * jobnr) / nb_jobs;
- const int end = (channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(channels, jobnr + 1, nb_jobs);
double values[VAR_VARS_NB];
memcpy(values, arg, sizeof(values));
diff --git a/libavfilter/af_afir.c b/libavfilter/af_afir.c
index fa6b063e44..38dabc08c1 100644
--- a/libavfilter/af_afir.c
+++ b/libavfilter/af_afir.c
@@ -156,8 +156,8 @@ static int fir_channel(AVFilterContext *ctx, AVFrame *out, int ch)
static int fir_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
{
AVFrame *out = arg;
- const int start = (out->ch_layout.nb_channels * jobnr) / nb_jobs;
- const int end = (out->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(out->ch_layout.nb_channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(out->ch_layout.nb_channels, jobnr + 1, nb_jobs);
for (int ch = start; ch < end; ch++)
fir_channel(ctx, out, ch);
diff --git a/libavfilter/af_afreqshift.c b/libavfilter/af_afreqshift.c
index 68969f2fdd..b0f378173c 100644
--- a/libavfilter/af_afreqshift.c
+++ b/libavfilter/af_afreqshift.c
@@ -292,8 +292,8 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
ThreadData *td = arg;
AVFrame *out = td->out;
AVFrame *in = td->in;
- const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs;
- const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(in->ch_layout.nb_channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(in->ch_layout.nb_channels, jobnr + 1, nb_jobs);
for (int ch = start; ch < end; ch++)
s->filter_channel(ctx, ch, in, out);
diff --git a/libavfilter/af_anequalizer.c b/libavfilter/af_anequalizer.c
index 2f39e94cc4..074d9bdc4f 100644
--- a/libavfilter/af_anequalizer.c
+++ b/libavfilter/af_anequalizer.c
@@ -687,8 +687,8 @@ static int filter_channels(AVFilterContext *ctx, void *arg,
{
AudioNEqualizerContext *s = ctx->priv;
AVFrame *buf = arg;
- const int start = (buf->ch_layout.nb_channels * jobnr) / nb_jobs;
- const int end = (buf->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(buf->ch_layout.nb_channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(buf->ch_layout.nb_channels, jobnr + 1, nb_jobs);
for (int i = 0; i < s->nb_filters; i++) {
EqualizatorFilter *f = &s->filters[i];
diff --git a/libavfilter/af_apsyclip.c b/libavfilter/af_apsyclip.c
index 8298435592..934bd344ee 100644
--- a/libavfilter/af_apsyclip.c
+++ b/libavfilter/af_apsyclip.c
@@ -532,8 +532,8 @@ static int psy_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
{
AudioPsyClipContext *s = ctx->priv;
AVFrame *out = arg;
- const int start = (out->ch_layout.nb_channels * jobnr) / nb_jobs;
- const int end = (out->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(out->ch_layout.nb_channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(out->ch_layout.nb_channels, jobnr + 1, nb_jobs);
for (int ch = start; ch < end; ch++)
psy_channel(ctx, s->in, out, ch);
diff --git a/libavfilter/af_arnndn.c b/libavfilter/af_arnndn.c
index 23eeb17851..5d516f0b15 100644
--- a/libavfilter/af_arnndn.c
+++ b/libavfilter/af_arnndn.c
@@ -1411,8 +1411,8 @@ static int rnnoise_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_j
ThreadData *td = arg;
AVFrame *in = td->in;
AVFrame *out = td->out;
- const int start = (out->ch_layout.nb_channels * jobnr) / nb_jobs;
- const int end = (out->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(out->ch_layout.nb_channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(out->ch_layout.nb_channels, jobnr + 1, nb_jobs);
for (int ch = start; ch < end; ch++) {
rnnoise_channel(s, &s->st[ch],
diff --git a/libavfilter/af_asdr.c b/libavfilter/af_asdr.c
index ea74940179..0d299f0538 100644
--- a/libavfilter/af_asdr.c
+++ b/libavfilter/af_asdr.c
@@ -52,8 +52,8 @@ static int sdr_##name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)\
AVFrame *u = s->cache[0]; \
AVFrame *v = s->cache[1]; \
const int channels = u->ch_layout.nb_channels; \
- const int start = (channels * jobnr) / nb_jobs; \
- const int end = (channels * (jobnr+1)) / nb_jobs; \
+ const int start = ff_slice_pos(channels, jobnr, nb_jobs); \
+ const int end = ff_slice_pos(channels, jobnr + 1, nb_jobs); \
const int nb_samples = u->nb_samples; \
\
for (int ch = start; ch < end; ch++) { \
@@ -85,8 +85,8 @@ static int sisdr_##name(AVFilterContext *ctx, void *arg,int jobnr,int nb_jobs)\
AVFrame *u = s->cache[0]; \
AVFrame *v = s->cache[1]; \
const int channels = u->ch_layout.nb_channels; \
- const int start = (channels * jobnr) / nb_jobs; \
- const int end = (channels * (jobnr+1)) / nb_jobs; \
+ const int start = ff_slice_pos(channels, jobnr, nb_jobs); \
+ const int end = ff_slice_pos(channels, jobnr + 1, nb_jobs); \
const int nb_samples = u->nb_samples; \
\
for (int ch = start; ch < end; ch++) { \
@@ -121,8 +121,8 @@ static int psnr_##name(AVFilterContext *ctx, void *arg, int jobnr,int nb_jobs)\
AVFrame *u = s->cache[0]; \
AVFrame *v = s->cache[1]; \
const int channels = u->ch_layout.nb_channels; \
- const int start = (channels * jobnr) / nb_jobs; \
- const int end = (channels * (jobnr+1)) / nb_jobs; \
+ const int start = ff_slice_pos(channels, jobnr, nb_jobs); \
+ const int end = ff_slice_pos(channels, jobnr + 1, nb_jobs); \
const int nb_samples = u->nb_samples; \
\
for (int ch = start; ch < end; ch++) { \
diff --git a/libavfilter/af_asoftclip.c b/libavfilter/af_asoftclip.c
index 19923f2c34..3b183a7b10 100644
--- a/libavfilter/af_asoftclip.c
+++ b/libavfilter/af_asoftclip.c
@@ -410,8 +410,8 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
AVFrame *in = td->in;
const int channels = td->channels;
const int nb_samples = td->nb_samples;
- const int start = (channels * jobnr) / nb_jobs;
- const int end = (channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(channels, jobnr + 1, nb_jobs);
s->filter(s, (void **)out->extended_data, (const void **)in->extended_data,
nb_samples, channels, start, end);
diff --git a/libavfilter/af_aspectralstats.c b/libavfilter/af_aspectralstats.c
index ac7da748ee..b7ea65f679 100644
--- a/libavfilter/af_aspectralstats.c
+++ b/libavfilter/af_aspectralstats.c
@@ -438,8 +438,8 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_job
const float *window_func_lut = s->window_func_lut;
AVFrame *in = arg;
const int channels = s->nb_channels;
- const int start = (channels * jobnr) / nb_jobs;
- const int end = (channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(channels, jobnr + 1, nb_jobs);
const int offset = s->win_size - s->hop_size;
for (int ch = start; ch < end; ch++) {
diff --git a/libavfilter/af_astats.c b/libavfilter/af_astats.c
index 6ef69ff102..3e75c72671 100644
--- a/libavfilter/af_astats.c
+++ b/libavfilter/af_astats.c
@@ -684,8 +684,8 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_job
const uint8_t * const * const data = (const uint8_t * const *)buf->extended_data;
const int channels = s->nb_channels;
const int samples = buf->nb_samples;
- const int start = (buf->ch_layout.nb_channels * jobnr) / nb_jobs;
- const int end = (buf->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(buf->ch_layout.nb_channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(buf->ch_layout.nb_channels, jobnr + 1, nb_jobs);
switch (inlink->format) {
case AV_SAMPLE_FMT_DBLP:
diff --git a/libavfilter/af_asubboost.c b/libavfilter/af_asubboost.c
index 58135626b9..b10139c69d 100644
--- a/libavfilter/af_asubboost.c
+++ b/libavfilter/af_asubboost.c
@@ -108,8 +108,8 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
const double b2 = s->b2;
const double a1 = -s->a1;
const double a2 = -s->a2;
- const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs;
- const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(in->ch_layout.nb_channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(in->ch_layout.nb_channels, jobnr + 1, nb_jobs);
const int buffer_samples = s->buffer_samples;
for (int ch = start; ch < end; ch++) {
diff --git a/libavfilter/af_asupercut.c b/libavfilter/af_asupercut.c
index 3e032d74bd..621325e429 100644
--- a/libavfilter/af_asupercut.c
+++ b/libavfilter/af_asupercut.c
@@ -210,8 +210,8 @@ static int filter_channels_## name(AVFilterContext *ctx, void *arg, \
ThreadData *td = arg; \
AVFrame *out = td->out; \
AVFrame *in = td->in; \
- const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; \
- const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; \
+ const int start = ff_slice_pos(in->ch_layout.nb_channels, jobnr, nb_jobs); \
+ const int end = ff_slice_pos(in->ch_layout.nb_channels, jobnr + 1, nb_jobs); \
const double level = s->level; \
\
for (int ch = start; ch < end; ch++) { \
diff --git a/libavfilter/af_atilt.c b/libavfilter/af_atilt.c
index b2cdef8fbb..c2befcf558 100644
--- a/libavfilter/af_atilt.c
+++ b/libavfilter/af_atilt.c
@@ -125,8 +125,8 @@ static int filter_channels_## name(AVFilterContext *ctx, void *arg, \
ThreadData *td = arg; \
AVFrame *out = td->out; \
AVFrame *in = td->in; \
- const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; \
- const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; \
+ const int start = ff_slice_pos(in->ch_layout.nb_channels, jobnr, nb_jobs); \
+ const int end = ff_slice_pos(in->ch_layout.nb_channels, jobnr + 1, nb_jobs); \
const type level = s->level; \
\
for (int ch = start; ch < end; ch++) { \
diff --git a/libavfilter/af_biquads.c b/libavfilter/af_biquads.c
index 86ddeb17fb..19a6c63fd5 100644
--- a/libavfilter/af_biquads.c
+++ b/libavfilter/af_biquads.c
@@ -1245,8 +1245,8 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_job
AVFrame *buf = td->in;
AVFrame *out_buf = td->out;
BiquadsContext *s = ctx->priv;
- const int start = (buf->ch_layout.nb_channels * jobnr) / nb_jobs;
- const int end = (buf->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(buf->ch_layout.nb_channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(buf->ch_layout.nb_channels, jobnr + 1, nb_jobs);
int ch;
for (ch = start; ch < end; ch++) {
diff --git a/libavfilter/af_crystalizer.c b/libavfilter/af_crystalizer.c
index 3cb5dc71d8..ab6533571f 100644
--- a/libavfilter/af_crystalizer.c
+++ b/libavfilter/af_crystalizer.c
@@ -65,8 +65,8 @@ static int filter_## inverse ##_## fmt ##_## clp(AVFilterContext *ctx, \
const int channels = td->channels; \
const type mult = td->mult; \
const type scale = one / (-mult + one); \
- const int start = (channels * jobnr) / nb_jobs; \
- const int end = (channels * (jobnr+1)) / nb_jobs; \
+ const int start = ff_slice_pos(channels, jobnr, nb_jobs); \
+ const int end = ff_slice_pos(channels, jobnr + 1, nb_jobs); \
\
if (packed) { \
type *prv = p[0]; \
diff --git a/libavfilter/af_dynaudnorm.c b/libavfilter/af_dynaudnorm.c
index ddeedf6258..938f99f75c 100644
--- a/libavfilter/af_dynaudnorm.c
+++ b/libavfilter/af_dynaudnorm.c
@@ -579,8 +579,8 @@ static int update_gain_histories(AVFilterContext *ctx, void *arg, int jobnr, int
DynamicAudioNormalizerContext *s = ctx->priv;
AVFrame *analyze_frame = arg;
const int channels = s->channels;
- const int start = (channels * jobnr) / nb_jobs;
- const int end = (channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(channels, jobnr + 1, nb_jobs);
for (int c = start; c < end; c++)
update_gain_history(s, c, get_max_local_gain(s, analyze_frame, c));
@@ -824,8 +824,8 @@ static int amplify_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_j
AVFrame *in = td->in;
const int enabled = td->enabled;
const int channels = s->channels;
- const int start = (channels * jobnr) / nb_jobs;
- const int end = (channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(channels, jobnr + 1, nb_jobs);
for (int ch = start; ch < end; ch++)
amplify_channel(s, in, out, enabled, ch);
diff --git a/libavfilter/af_surround.c b/libavfilter/af_surround.c
index 6c973f5187..4e23e422ff 100644
--- a/libavfilter/af_surround.c
+++ b/libavfilter/af_surround.c
@@ -1261,8 +1261,8 @@ static int fft_channel(AVFilterContext *ctx, AVFrame *in, int ch)
static int fft_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
{
AVFrame *in = arg;
- const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs;
- const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(in->ch_layout.nb_channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(in->ch_layout.nb_channels, jobnr + 1, nb_jobs);
for (int ch = start; ch < end; ch++)
fft_channel(ctx, in, ch);
@@ -1302,8 +1302,8 @@ static int ifft_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs
{
AudioSurroundContext *s = ctx->priv;
AVFrame *out = arg;
- const int start = (out->ch_layout.nb_channels * jobnr) / nb_jobs;
- const int end = (out->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(out->ch_layout.nb_channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(out->ch_layout.nb_channels, jobnr + 1, nb_jobs);
for (int ch = start; ch < end; ch++) {
if (s->upmix)
diff --git a/libavfilter/anlms_template.c b/libavfilter/anlms_template.c
index a8d1dbfe0f..7a39922005 100644
--- a/libavfilter/anlms_template.c
+++ b/libavfilter/anlms_template.c
@@ -106,8 +106,8 @@ static int fn(filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int n
{
AudioNLMSContext *s = ctx->priv;
AVFrame *out = arg;
- const int start = (out->ch_layout.nb_channels * jobnr) / nb_jobs;
- const int end = (out->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(out->ch_layout.nb_channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(out->ch_layout.nb_channels, jobnr + 1, nb_jobs);
for (int c = start; c < end; c++) {
const ftype *input = (const ftype *)s->frame[0]->extended_data[c];
diff --git a/libavfilter/arls_template.c b/libavfilter/arls_template.c
index c67b48cf6f..51c85ceda3 100644
--- a/libavfilter/arls_template.c
+++ b/libavfilter/arls_template.c
@@ -133,8 +133,8 @@ static int fn(filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int n
{
AudioRLSContext *s = ctx->priv;
AVFrame *out = arg;
- const int start = (out->ch_layout.nb_channels * jobnr) / nb_jobs;
- const int end = (out->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(out->ch_layout.nb_channels, jobnr, nb_jobs);
+ const int end = ff_slice_pos(out->ch_layout.nb_channels, jobnr + 1, nb_jobs);
for (int c = start; c < end; c++) {
const ftype *input = (const ftype *)s->frame[0]->extended_data[c];
diff --git a/libavfilter/avf_avectorscope.c b/libavfilter/avf_avectorscope.c
index 4e477627b5..e20c00f75b 100644
--- a/libavfilter/avf_avectorscope.c
+++ b/libavfilter/avf_avectorscope.c
@@ -201,8 +201,8 @@ static int fade(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
AudioVectorScopeContext *s = ctx->priv;
const int linesize = s->outpicref->linesize[0];
const int height = s->outpicref->height;
- const int slice_start = (height * jobnr ) / nb_jobs;
- const int slice_end = (height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
if (s->fade[0] == 255 && s->fade[1] == 255 && s->fade[2] == 255) {
for (int i = slice_start; i < slice_end; i++)
diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c
index 4c4edaa768..ad1b6a179a 100644
--- a/libavfilter/avf_showcwt.c
+++ b/libavfilter/avf_showcwt.c
@@ -446,8 +446,8 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
const ptrdiff_t alinesize = s->outpicref->linesize[3];
const float log_factor = 1.f/logf(s->logarithmic_basis);
const int count = s->frequency_band_count;
- const int start = (count * jobnr) / nb_jobs;
- const int end = (count * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(count, jobnr, nb_jobs);
+ const int end = ff_slice_pos(count, jobnr + 1, nb_jobs);
const int nb_channels = s->nb_channels;
const int iscale = s->intensity_scale;
const int ihop_index = s->ihop_index;
@@ -650,8 +650,8 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
const float scale = 1.f / input_padding_size;
const int ihop_size = s->ihop_size;
const int count = s->frequency_band_count;
- const int start = (count * jobnr) / nb_jobs;
- const int end = (count * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(count, jobnr, nb_jobs);
+ const int end = ff_slice_pos(count, jobnr + 1, nb_jobs);
for (int y = start; y < end; y++) {
AVComplexFloat *chout = ((AVComplexFloat *)s->ch_out->extended_data[y]) + ch * ihop_size;
@@ -1222,8 +1222,8 @@ static int run_channels_cwt_prepare(AVFilterContext *ctx, void *arg, int jobnr,
{
ShowCWTContext *s = ctx->priv;
const int count = s->nb_channels;
- const int start = (count * jobnr) / nb_jobs;
- const int end = (count * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(count, jobnr, nb_jobs);
+ const int end = ff_slice_pos(count, jobnr + 1, nb_jobs);
for (int ch = start; ch < end; ch++)
run_channel_cwt_prepare(ctx, arg, jobnr, ch);
diff --git a/libavfilter/colorchannelmixer_template.c b/libavfilter/colorchannelmixer_template.c
index bef57476aa..aed5c59cff 100644
--- a/libavfilter/colorchannelmixer_template.c
+++ b/libavfilter/colorchannelmixer_template.c
@@ -54,8 +54,8 @@ static av_always_inline int fn(filter_slice_rgba_planar)(AVFilterContext *ctx, v
AVFrame *out = td->out;
const float pa = s->preserve_amount;
const float max = (1 << depth) - 1;
- const int slice_start = (out->height * jobnr) / nb_jobs;
- const int slice_end = (out->height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(out->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(out->height, jobnr + 1, nb_jobs);
const pixel *srcg = (const pixel *)(in->data[0] + slice_start * in->linesize[0]);
const pixel *srcb = (const pixel *)(in->data[1] + slice_start * in->linesize[1]);
const pixel *srcr = (const pixel *)(in->data[2] + slice_start * in->linesize[2]);
@@ -172,8 +172,8 @@ static av_always_inline int fn(filter_slice_rgba_packed)(AVFilterContext *ctx, v
AVFrame *out = td->out;
const float pa = s->preserve_amount;
const float max = (1 << depth) - 1;
- const int slice_start = (out->height * jobnr) / nb_jobs;
- const int slice_end = (out->height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(out->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(out->height, jobnr + 1, nb_jobs);
const uint8_t roffset = s->rgba_map[R];
const uint8_t goffset = s->rgba_map[G];
const uint8_t boffset = s->rgba_map[B];
diff --git a/libavfilter/vf_amplify.c b/libavfilter/vf_amplify.c
index 7f18012a53..56d55873cb 100644
--- a/libavfilter/vf_amplify.c
+++ b/libavfilter/vf_amplify.c
@@ -98,8 +98,8 @@ typedef struct ThreadData {
const stype limit[2] = { s->llimit, s->hlimit }; \
\
for (int p = 0; p < s->nb_planes; p++) { \
- const int slice_start = (s->height[p] * jobnr) / nb_jobs; \
- const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(s->height[p], jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(s->height[p], jobnr + 1, nb_jobs); \
type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
ptrdiff_t dst_linesize = out->linesize[p] / sizeof(type); \
\
diff --git a/libavfilter/vf_atadenoise.c b/libavfilter/vf_atadenoise.c
index f443d34de8..7773df5615 100644
--- a/libavfilter/vf_atadenoise.c
+++ b/libavfilter/vf_atadenoise.c
@@ -345,8 +345,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
const float *weights = s->weights[p];
const int h = s->planeheight[p];
const int w = s->planewidth[p];
- const int slice_start = (h * jobnr) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
const uint8_t *src = in->data[p] + slice_start * in->linesize[p];
uint8_t *dst = out->data[p] + slice_start * out->linesize[p];
const int thra = s->thra[p];
diff --git a/libavfilter/vf_backgroundkey.c b/libavfilter/vf_backgroundkey.c
index f0a76b977e..2a067fd8ae 100644
--- a/libavfilter/vf_backgroundkey.c
+++ b/libavfilter/vf_backgroundkey.c
@@ -48,8 +48,8 @@ static int do_backgroundkey_slice(AVFilterContext *avctx, void *arg, int jobnr,
{
BackgroundkeyContext *s = avctx->priv;
AVFrame *frame = arg;
- const int slice_start = (frame->height * jobnr) / nb_jobs;
- const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(frame->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(frame->height, jobnr + 1, nb_jobs);
const int min_diff = (255 + 255 + 255) * s->similarity;
const float blend = s->blend;
const int hsub = s->hsub_log2;
@@ -91,8 +91,8 @@ static int do_backgroundkey16_slice(AVFilterContext *avctx, void *arg, int jobnr
{
BackgroundkeyContext *s = avctx->priv;
AVFrame *frame = arg;
- const int slice_start = (frame->height * jobnr) / nb_jobs;
- const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(frame->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(frame->height, jobnr + 1, nb_jobs);
const int hsub = s->hsub_log2;
const int vsub = s->vsub_log2;
const int max = s->max;
diff --git a/libavfilter/vf_bilateral.c b/libavfilter/vf_bilateral.c
index cf62b2315d..0a08a6d6d6 100644
--- a/libavfilter/vf_bilateral.c
+++ b/libavfilter/vf_bilateral.c
@@ -157,8 +157,8 @@ static void bilateralh_##name(BilateralContext *s, AVFrame *out, AVFrame *in, \
{ \
const int width = s->planewidth[plane]; \
const int height = s->planeheight[plane]; \
- const int slice_start = (height * jobnr) / nb_jobs; \
- const int slice_end = (height * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs); \
const int src_linesize = in->linesize[plane] / sizeof(type); \
const type *src = (const type *)in->data[plane]; \
float *img_temp = s->img_temp[plane]; \
@@ -229,8 +229,8 @@ static void bilateralv_##name(BilateralContext *s, AVFrame *out, AVFrame *in, \
{ \
const int width = s->planewidth[plane]; \
const int height = s->planeheight[plane]; \
- const int slice_start = (width * jobnr) / nb_jobs; \
- const int slice_end = (width * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(width, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(width, jobnr + 1, nb_jobs); \
const int src_linesize = in->linesize[plane] / sizeof(type); \
const type *src = (const type *)in->data[plane] + slice_start; \
float *img_out_f = s->img_out_f[plane] + slice_start; \
@@ -332,8 +332,8 @@ static void bilateralo_##name(BilateralContext *s, AVFrame *out, AVFrame *in, \
{ \
const int width = s->planewidth[plane]; \
const int height = s->planeheight[plane]; \
- const int slice_start = (height * jobnr) / nb_jobs; \
- const int slice_end = (height * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs); \
const int dst_linesize = out->linesize[plane] / sizeof(type); \
\
for (int i = slice_start; i < slice_end; i++) { \
@@ -401,8 +401,8 @@ static int bilateralo_planes(AVFilterContext *ctx, void *arg,
if (!(s->planes & (1 << plane))) {
if (out != in) {
const int height = s->planeheight[plane];
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const int width = s->planewidth[plane];
const int linesize = in->linesize[plane];
const int dst_linesize = out->linesize[plane];
diff --git a/libavfilter/vf_blackdetect.c b/libavfilter/vf_blackdetect.c
index d39b2df006..30fc81c40c 100644
--- a/libavfilter/vf_blackdetect.c
+++ b/libavfilter/vf_blackdetect.c
@@ -168,8 +168,8 @@ static int black_counter(AVFilterContext *ctx, void *arg,
const int plane = s->alpha ? 3 : 0;
const int linesize = in->linesize[plane];
const int h = in->height;
- const int start = (h * jobnr) / nb_jobs;
- const int end = (h * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int end = ff_slice_pos(h, jobnr + 1, nb_jobs);
s->counter[jobnr] = s->func(in->data[plane] + start * linesize,
linesize, in->width, end - start,
diff --git a/libavfilter/vf_blackframe.c b/libavfilter/vf_blackframe.c
index 39343f02ce..fe98da604e 100644
--- a/libavfilter/vf_blackframe.c
+++ b/libavfilter/vf_blackframe.c
@@ -68,8 +68,8 @@ static const enum AVPixelFormat pix_fmts[] = {
static int blackframe_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
{
ThreadData *td = arg;
- int slice_start = (td->height * jobnr) / nb_jobs;
- int slice_end = (td->height * (jobnr+1)) / nb_jobs;
+ int slice_start = ff_slice_pos(td->height, jobnr, nb_jobs);
+ int slice_end = ff_slice_pos(td->height, jobnr + 1, nb_jobs);
const uint8_t *p;
unsigned int black_pixels_count = 0;
diff --git a/libavfilter/vf_blend.c b/libavfilter/vf_blend.c
index 07656f05b2..21f4b19091 100644
--- a/libavfilter/vf_blend.c
+++ b/libavfilter/vf_blend.c
@@ -168,8 +168,8 @@ DEFINE_BLEND_EXPR(float, 32bit, 4)
static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
{
ThreadData *td = arg;
- int slice_start = (td->h * jobnr ) / nb_jobs;
- int slice_end = (td->h * (jobnr+1)) / nb_jobs;
+ int slice_start = ff_slice_pos(td->h, jobnr, nb_jobs);
+ int slice_end = ff_slice_pos(td->h, jobnr + 1, nb_jobs);
int height = slice_end - slice_start;
const uint8_t *top = td->top->data[td->plane];
const uint8_t *bottom = td->bottom->data[td->plane];
diff --git a/libavfilter/vf_bm3d.c b/libavfilter/vf_bm3d.c
index b482f7693a..16f4d98ac6 100644
--- a/libavfilter/vf_bm3d.c
+++ b/libavfilter/vf_bm3d.c
@@ -695,9 +695,9 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
const int height = s->planeheight[plane];
const int block_pos_bottom = FFMAX(0, height - s->block_size);
const int block_pos_right = FFMAX(0, width - s->block_size);
- const int slice_start = (((height + block_step - 1) / block_step) * jobnr / nb_jobs) * block_step;
+ const int slice_start = ff_slice_pos((height + block_step - 1) / block_step, jobnr, nb_jobs) * block_step;
const int slice_end = (jobnr == nb_jobs - 1) ? block_pos_bottom + block_step :
- (((height + block_step - 1) / block_step) * (jobnr + 1) / nb_jobs) * block_step;
+ ff_slice_pos((height + block_step - 1) / block_step, jobnr + 1, nb_jobs) * block_step;
memset(sc->num, 0, width * height * sizeof(float));
memset(sc->den, 0, width * height * sizeof(float));
diff --git a/libavfilter/vf_bwdif.c b/libavfilter/vf_bwdif.c
index 67efc3a8c3..dbe35a029b 100644
--- a/libavfilter/vf_bwdif.c
+++ b/libavfilter/vf_bwdif.c
@@ -54,7 +54,7 @@ typedef struct ThreadData {
// and the frame is a multiple of 4 high then filter_line will never be called
static inline int job_start(const int jobnr, const int nb_jobs, const int h)
{
- return jobnr >= nb_jobs ? h : ((h * jobnr) / nb_jobs) & ~3;
+ return jobnr >= nb_jobs ? h : (ff_slice_pos(h, jobnr, nb_jobs)) & ~3;
}
static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
diff --git a/libavfilter/vf_cas.c b/libavfilter/vf_cas.c
index 54d164fb7f..0546b72197 100644
--- a/libavfilter/vf_cas.c
+++ b/libavfilter/vf_cas.c
@@ -52,8 +52,8 @@ static int cas_slice8(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs)
AVFrame *in = s->in;
for (int p = 0; p < s->nb_planes; p++) {
- const int slice_start = (s->planeheight[p] * jobnr) / nb_jobs;
- const int slice_end = (s->planeheight[p] * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(s->planeheight[p], jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(s->planeheight[p], jobnr + 1, nb_jobs);
const int linesize = out->linesize[p];
const int in_linesize = in->linesize[p];
const int w = s->planewidth[p];
@@ -119,8 +119,8 @@ static int cas_slice16(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs
AVFrame *in = s->in;
for (int p = 0; p < s->nb_planes; p++) {
- const int slice_start = (s->planeheight[p] * jobnr) / nb_jobs;
- const int slice_end = (s->planeheight[p] * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(s->planeheight[p], jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(s->planeheight[p], jobnr + 1, nb_jobs);
const int linesize = out->linesize[p] / 2;
const int in_linesize = in->linesize[p] / 2;
const int w = s->planewidth[p];
diff --git a/libavfilter/vf_chromakey.c b/libavfilter/vf_chromakey.c
index e5a7ac15b5..7ef75f2d07 100644
--- a/libavfilter/vf_chromakey.c
+++ b/libavfilter/vf_chromakey.c
@@ -116,8 +116,8 @@ static int do_chromakey_slice(AVFilterContext *avctx, void *arg, int jobnr, int
{
AVFrame *frame = arg;
- const int slice_start = (frame->height * jobnr) / nb_jobs;
- const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(frame->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(frame->height, jobnr + 1, nb_jobs);
ChromakeyContext *ctx = avctx->priv;
@@ -146,8 +146,8 @@ static int do_chromakey16_slice(AVFilterContext *avctx, void *arg, int jobnr, in
{
AVFrame *frame = arg;
- const int slice_start = (frame->height * jobnr) / nb_jobs;
- const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(frame->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(frame->height, jobnr + 1, nb_jobs);
ChromakeyContext *ctx = avctx->priv;
@@ -180,8 +180,8 @@ static int do_chromahold_slice(AVFilterContext *avctx, void *arg, int jobnr, int
{
ChromakeyContext *ctx = avctx->priv;
AVFrame *frame = arg;
- const int slice_start = ((frame->height >> ctx->vsub_log2) * jobnr) / nb_jobs;
- const int slice_end = ((frame->height >> ctx->vsub_log2) * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(frame->height >> ctx->vsub_log2, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(frame->height >> ctx->vsub_log2, jobnr + 1, nb_jobs);
int x, y, alpha;
@@ -217,8 +217,8 @@ static int do_chromahold16_slice(AVFilterContext *avctx, void *arg, int jobnr, i
{
ChromakeyContext *ctx = avctx->priv;
AVFrame *frame = arg;
- const int slice_start = ((frame->height >> ctx->vsub_log2) * jobnr) / nb_jobs;
- const int slice_end = ((frame->height >> ctx->vsub_log2) * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(frame->height >> ctx->vsub_log2, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(frame->height >> ctx->vsub_log2, jobnr + 1, nb_jobs);
const int mid = ctx->mid;
double max = ctx->max;
diff --git a/libavfilter/vf_chromanr.c b/libavfilter/vf_chromanr.c
index fe138162f8..748cf34784 100644
--- a/libavfilter/vf_chromanr.c
+++ b/libavfilter/vf_chromanr.c
@@ -83,8 +83,8 @@ static int distance ## _slice##name(AVFilterContext *ctx, void *arg,
\
{ \
const int h = s->planeheight[0]; \
- const int slice_start = (h * jobnr) / nb_jobs; \
- const int slice_end = (h * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs); \
\
av_image_copy_plane(out->data[0] + slice_start * out->linesize[0], \
out->linesize[0], \
@@ -118,8 +118,8 @@ static int distance ## _slice##name(AVFilterContext *ctx, void *arg,
const int thres_v = s->thres_v; \
const int h = s->planeheight[1]; \
const int w = s->planewidth[1]; \
- const int slice_start = (h * jobnr) / nb_jobs; \
- const int slice_end = (h * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs); \
type *out_uptr = (type *)(out->data[1] + slice_start * out_ulinesize); \
type *out_vptr = (type *)(out->data[2] + slice_start * out_vlinesize); \
\
diff --git a/libavfilter/vf_chromashift.c b/libavfilter/vf_chromashift.c
index f0449d5977..29691afbdb 100644
--- a/libavfilter/vf_chromashift.c
+++ b/libavfilter/vf_chromashift.c
@@ -64,8 +64,8 @@ static int smear_slice ## depth(AVFilterContext *ctx, void *arg, int jobnr, int
const int crv = s->crv; \
const int h = s->height[1]; \
const int w = s->width[1]; \
- const int slice_start = (h * jobnr) / nb_jobs; \
- const int slice_end = (h * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs); \
const type *su = (const type *)in->data[1]; \
const type *sv = (const type *)in->data[2]; \
type *du = (type *)out->data[1] + slice_start * ulinesize; \
@@ -106,8 +106,8 @@ static int wrap_slice ## depth(AVFilterContext *ctx, void *arg, int jobnr, int n
const int crv = s->crv; \
const int h = s->height[1]; \
const int w = s->width[1]; \
- const int slice_start = (h * jobnr) / nb_jobs; \
- const int slice_end = (h * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs); \
const type *su = (const type *)in->data[1]; \
const type *sv = (const type *)in->data[2]; \
type *du = (type *)out->data[1] + slice_start * ulinesize; \
@@ -169,8 +169,8 @@ static int rgbasmear_slice ## depth(AVFilterContext *ctx, void *arg, int jobnr,
const int av = s->av; \
const int h = s->height[1]; \
const int w = s->width[1]; \
- const int slice_start = (h * jobnr) / nb_jobs; \
- const int slice_end = (h * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs); \
const type *sr = (const type *)in->data[2]; \
const type *sg = (const type *)in->data[0]; \
const type *sb = (const type *)in->data[1]; \
@@ -236,8 +236,8 @@ static int rgbawrap_slice ## depth(AVFilterContext *ctx, void *arg, int jobnr, i
const int av = s->av; \
const int h = s->height[1]; \
const int w = s->width[1]; \
- const int slice_start = (h * jobnr) / nb_jobs; \
- const int slice_end = (h * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs); \
const type *sr = (const type *)in->data[2]; \
const type *sg = (const type *)in->data[0]; \
const type *sb = (const type *)in->data[1]; \
diff --git a/libavfilter/vf_colorbalance.c b/libavfilter/vf_colorbalance.c
index 80e218d32b..991692be34 100644
--- a/libavfilter/vf_colorbalance.c
+++ b/libavfilter/vf_colorbalance.c
@@ -153,8 +153,8 @@ static int color_balance8_p(AVFilterContext *ctx, void *arg, int jobnr, int nb_j
ThreadData *td = arg;
AVFrame *in = td->in;
AVFrame *out = td->out;
- const int slice_start = (out->height * jobnr) / nb_jobs;
- const int slice_end = (out->height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(out->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(out->height, jobnr + 1, nb_jobs);
const uint8_t *srcg = in->data[0] + slice_start * in->linesize[0];
const uint8_t *srcb = in->data[1] + slice_start * in->linesize[1];
const uint8_t *srcr = in->data[2] + slice_start * in->linesize[2];
@@ -206,8 +206,8 @@ static int color_balance16_p(AVFilterContext *ctx, void *arg, int jobnr, int nb_
ThreadData *td = arg;
AVFrame *in = td->in;
AVFrame *out = td->out;
- const int slice_start = (out->height * jobnr) / nb_jobs;
- const int slice_end = (out->height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(out->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(out->height, jobnr + 1, nb_jobs);
const uint16_t *srcg = (const uint16_t *)in->data[0] + slice_start * in->linesize[0] / 2;
const uint16_t *srcb = (const uint16_t *)in->data[1] + slice_start * in->linesize[1] / 2;
const uint16_t *srcr = (const uint16_t *)in->data[2] + slice_start * in->linesize[2] / 2;
@@ -261,8 +261,8 @@ static int color_balance8(AVFilterContext *ctx, void *arg, int jobnr, int nb_job
AVFrame *in = td->in;
AVFrame *out = td->out;
AVFilterLink *outlink = ctx->outputs[0];
- const int slice_start = (out->height * jobnr) / nb_jobs;
- const int slice_end = (out->height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(out->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(out->height, jobnr + 1, nb_jobs);
const uint8_t *srcrow = in->data[0] + slice_start * in->linesize[0];
const uint8_t roffset = s->rgba_map[R];
const uint8_t goffset = s->rgba_map[G];
@@ -312,8 +312,8 @@ static int color_balance16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
AVFrame *in = td->in;
AVFrame *out = td->out;
AVFilterLink *outlink = ctx->outputs[0];
- const int slice_start = (out->height * jobnr) / nb_jobs;
- const int slice_end = (out->height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(out->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(out->height, jobnr + 1, nb_jobs);
const uint16_t *srcrow = (const uint16_t *)in->data[0] + slice_start * in->linesize[0] / 2;
const uint8_t roffset = s->rgba_map[R];
const uint8_t goffset = s->rgba_map[G];
diff --git a/libavfilter/vf_colorconstancy.c b/libavfilter/vf_colorconstancy.c
index 7251cf3121..8c7086d1c4 100644
--- a/libavfilter/vf_colorconstancy.c
+++ b/libavfilter/vf_colorconstancy.c
@@ -270,8 +270,8 @@ static int slice_get_derivative(AVFilterContext* ctx, void* arg, int jobnr, int
if (dir == DIR_X) {
/** Applying gauss horizontally along each row */
const uint8_t *src = in->data[plane];
- slice_start = (height * jobnr ) / nb_jobs;
- slice_end = (height * (jobnr + 1)) / nb_jobs;
+ slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
for (r = slice_start; r < slice_end; ++r) {
for (c = 0; c < width; ++c) {
@@ -285,8 +285,8 @@ static int slice_get_derivative(AVFilterContext* ctx, void* arg, int jobnr, int
} else {
/** Applying gauss vertically along each column */
const double *src = td->data[src_index][plane];
- slice_start = (width * jobnr ) / nb_jobs;
- slice_end = (width * (jobnr + 1)) / nb_jobs;
+ slice_start = ff_slice_pos(width, jobnr, nb_jobs);
+ slice_end = ff_slice_pos(width, jobnr + 1, nb_jobs);
for (c = slice_start; c < slice_end; ++c) {
for (r = 0; r < height; ++r) {
@@ -325,8 +325,8 @@ static int slice_normalize(AVFilterContext* ctx, void* arg, int jobnr, int nb_jo
const int height = s->planeheight[plane];
const int width = s->planewidth[plane];
const int64_t numpixels = width * (int64_t)height;
- const int slice_start = (numpixels * jobnr ) / nb_jobs;
- const int slice_end = (numpixels * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(numpixels, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(numpixels, jobnr + 1, nb_jobs);
const double *dx = td->data[INDEX_DX][plane];
const double *dy = td->data[INDEX_DY][plane];
double *norm = td->data[INDEX_NORM][plane];
@@ -448,8 +448,8 @@ static int filter_slice_grey_edge(AVFilterContext* ctx, void* arg, int jobnr, in
const int height = s->planeheight[plane];
const int width = s->planewidth[plane];
const int in_linesize = in->linesize[plane];
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const uint8_t *img_data = in->data[plane];
const double *src = td->data[INDEX_NORM][plane];
double *dst = td->data[INDEX_DST][plane];
@@ -601,8 +601,8 @@ static int diagonal_transformation(AVFilterContext *ctx, void *arg, int jobnr, i
const int height = s->planeheight[plane];
const int width = s->planewidth[plane];
const int64_t numpixels = width * (int64_t)height;
- const int slice_start = (numpixels * jobnr) / nb_jobs;
- const int slice_end = (numpixels * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(numpixels, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(numpixels, jobnr + 1, nb_jobs);
const uint8_t *src = in->data[plane];
uint8_t *dst = out->data[plane];
double temp;
diff --git a/libavfilter/vf_colorcontrast.c b/libavfilter/vf_colorcontrast.c
index 05f2ad5676..61579e2e90 100644
--- a/libavfilter/vf_colorcontrast.c
+++ b/libavfilter/vf_colorcontrast.c
@@ -94,8 +94,8 @@ static int colorcontrast_slice8(AVFilterContext *ctx, void *arg, int jobnr, int
AVFrame *frame = arg;
const int width = frame->width;
const int height = frame->height;
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t glinesize = frame->linesize[0];
const ptrdiff_t blinesize = frame->linesize[1];
const ptrdiff_t rlinesize = frame->linesize[2];
@@ -148,8 +148,8 @@ static int colorcontrast_slice16(AVFilterContext *ctx, void *arg, int jobnr, int
const float max = (1 << depth) - 1;
const int width = frame->width;
const int height = frame->height;
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t glinesize = frame->linesize[0] / 2;
const ptrdiff_t blinesize = frame->linesize[1] / 2;
const ptrdiff_t rlinesize = frame->linesize[2] / 2;
@@ -201,8 +201,8 @@ static int colorcontrast_slice8p(AVFilterContext *ctx, void *arg, int jobnr, int
const int step = s->step;
const int width = frame->width;
const int height = frame->height;
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t linesize = frame->linesize[0];
const uint8_t roffset = s->rgba_map[R];
const uint8_t goffset = s->rgba_map[G];
@@ -253,8 +253,8 @@ static int colorcontrast_slice16p(AVFilterContext *ctx, void *arg, int jobnr, in
const float max = (1 << depth) - 1;
const int width = frame->width;
const int height = frame->height;
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t linesize = frame->linesize[0] / 2;
const uint8_t roffset = s->rgba_map[R];
const uint8_t goffset = s->rgba_map[G];
diff --git a/libavfilter/vf_colorcorrect.c b/libavfilter/vf_colorcorrect.c
index 4249bd414d..b6c3d04331 100644
--- a/libavfilter/vf_colorcorrect.c
+++ b/libavfilter/vf_colorcorrect.c
@@ -68,8 +68,8 @@ static int average_slice8(AVFilterContext *ctx, void *arg, int jobnr, int nb_job
const float imax = s->imax;
const int width = s->planewidth[1];
const int height = s->planeheight[1];
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t ulinesize = frame->linesize[1];
const ptrdiff_t vlinesize = frame->linesize[2];
const uint8_t *uptr = (const uint8_t *)frame->data[1] + slice_start * ulinesize;
@@ -99,8 +99,8 @@ static int average_slice16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
const float imax = s->imax;
const int width = s->planewidth[1];
const int height = s->planeheight[1];
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t ulinesize = frame->linesize[1] / 2;
const ptrdiff_t vlinesize = frame->linesize[2] / 2;
const uint16_t *uptr = (const uint16_t *)frame->data[1] + slice_start * ulinesize;
@@ -130,8 +130,8 @@ static int minmax_slice8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs
const float imax = s->imax;
const int width = s->planewidth[1];
const int height = s->planeheight[1];
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t ulinesize = frame->linesize[1];
const ptrdiff_t vlinesize = frame->linesize[2];
const uint8_t *uptr = (const uint8_t *)frame->data[1] + slice_start * ulinesize;
@@ -166,8 +166,8 @@ static int minmax_slice16(AVFilterContext *ctx, void *arg, int jobnr, int nb_job
const float imax = s->imax;
const int width = s->planewidth[1];
const int height = s->planeheight[1];
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t ulinesize = frame->linesize[1] / 2;
const ptrdiff_t vlinesize = frame->linesize[2] / 2;
const uint16_t *uptr = (const uint16_t *)frame->data[1] + slice_start * ulinesize;
@@ -322,8 +322,8 @@ static int colorcorrect_slice8(AVFilterContext *ctx, void *arg, int jobnr, int n
const int chroma_h = s->chroma_h;
const int width = s->planewidth[1];
const int height = s->planeheight[1];
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t ylinesize = frame->linesize[0];
const ptrdiff_t ulinesize = frame->linesize[1];
const ptrdiff_t vlinesize = frame->linesize[2];
@@ -363,8 +363,8 @@ static int colorcorrect_slice16(AVFilterContext *ctx, void *arg, int jobnr, int
const int chroma_h = s->chroma_h;
const int width = s->planewidth[1];
const int height = s->planeheight[1];
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t ylinesize = frame->linesize[0] / 2;
const ptrdiff_t ulinesize = frame->linesize[1] / 2;
const ptrdiff_t vlinesize = frame->linesize[2] / 2;
diff --git a/libavfilter/vf_colordetect.c b/libavfilter/vf_colordetect.c
index cfe7753ca3..397e278110 100644
--- a/libavfilter/vf_colordetect.c
+++ b/libavfilter/vf_colordetect.c
@@ -132,8 +132,8 @@ static int detect_range(AVFilterContext *ctx, void *arg,
ColorDetectContext *s = ctx->priv;
const AVFrame *in = arg;
const ptrdiff_t stride = in->linesize[0];
- const int y_start = (in->height * jobnr) / nb_jobs;
- const int y_end = (in->height * (jobnr + 1)) / nb_jobs;
+ const int y_start = ff_slice_pos(in->height, jobnr, nb_jobs);
+ const int y_end = ff_slice_pos(in->height, jobnr + 1, nb_jobs);
const int h_slice = y_end - y_start;
if (s->dsp.detect_range(in->data[0] + y_start * stride, stride,
@@ -151,8 +151,8 @@ static int detect_alpha(AVFilterContext *ctx, void *arg,
const AVFrame *in = arg;
const int w = in->width;
const int h = in->height;
- const int y_start = (h * jobnr) / nb_jobs;
- const int y_end = (h * (jobnr + 1)) / nb_jobs;
+ const int y_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int y_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
const int h_slice = y_end - y_start;
const int nb_planes = (s->desc->flags & AV_PIX_FMT_FLAG_RGB) ? 3 : 1;
diff --git a/libavfilter/vf_colorize.c b/libavfilter/vf_colorize.c
index 1ab71b2b87..3d0c423bfe 100644
--- a/libavfilter/vf_colorize.c
+++ b/libavfilter/vf_colorize.c
@@ -50,8 +50,8 @@ static int colorizey_slice8(AVFilterContext *ctx, void *arg, int jobnr, int nb_j
AVFrame *frame = arg;
const int width = s->planewidth[0];
const int height = s->planeheight[0];
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t ylinesize = frame->linesize[0];
uint8_t *yptr = frame->data[0] + slice_start * ylinesize;
const int yv = s->c[0];
@@ -73,8 +73,8 @@ static int colorizey_slice16(AVFilterContext *ctx, void *arg, int jobnr, int nb_
AVFrame *frame = arg;
const int width = s->planewidth[0];
const int height = s->planeheight[0];
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t ylinesize = frame->linesize[0] / 2;
uint16_t *yptr = (uint16_t *)frame->data[0] + slice_start * ylinesize;
const int yv = s->c[0];
@@ -96,8 +96,8 @@ static int colorize_slice8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
AVFrame *frame = arg;
const int width = s->planewidth[1];
const int height = s->planeheight[1];
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t ulinesize = frame->linesize[1];
const ptrdiff_t vlinesize = frame->linesize[2];
uint8_t *uptr = frame->data[1] + slice_start * ulinesize;
@@ -124,8 +124,8 @@ static int colorize_slice16(AVFilterContext *ctx, void *arg, int jobnr, int nb_j
AVFrame *frame = arg;
const int width = s->planewidth[1];
const int height = s->planeheight[1];
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t ulinesize = frame->linesize[1] / 2;
const ptrdiff_t vlinesize = frame->linesize[2] / 2;
uint16_t *uptr = (uint16_t *)frame->data[1] + slice_start * ulinesize;
diff --git a/libavfilter/vf_colorkey.c b/libavfilter/vf_colorkey.c
index 4781e53bb2..4ad0b4c89c 100644
--- a/libavfilter/vf_colorkey.c
+++ b/libavfilter/vf_colorkey.c
@@ -67,8 +67,8 @@ static int do_colorkey_slice##name(AVFilterContext *avctx, \
int jobnr, int nb_jobs) \
{ \
AVFrame *frame = arg; \
- const int slice_start = (frame->height * jobnr) / nb_jobs; \
- const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(frame->height, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(frame->height, jobnr + 1, nb_jobs); \
ColorkeyContext *ctx = avctx->priv; \
const float similarity = ctx->similarity; \
const float iblend = 1.f / ctx->blend; \
@@ -102,8 +102,8 @@ static int do_colorhold_slice##name(AVFilterContext *avctx, void *arg, \
int jobnr, int nb_jobs) \
{ \
AVFrame *frame = arg; \
- const int slice_start = (frame->height * jobnr) / nb_jobs; \
- const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(frame->height, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(frame->height, jobnr + 1, nb_jobs); \
ColorkeyContext *ctx = avctx->priv; \
const int depth = ctx->depth; \
const int max = ctx->max; \
diff --git a/libavfilter/vf_colorlevels.c b/libavfilter/vf_colorlevels.c
index 5fa378ca38..8e5479d1d4 100644
--- a/libavfilter/vf_colorlevels.c
+++ b/libavfilter/vf_colorlevels.c
@@ -106,8 +106,8 @@ typedef struct ThreadData {
const int linesize = s->linesize; \
const int step = s->step; \
const int process_h = td->h; \
- const int slice_start = (process_h * jobnr ) / nb_jobs; \
- const int slice_end = (process_h * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(process_h, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(process_h, jobnr + 1, nb_jobs); \
const int src_linesize = td->src_linesize / sizeof(type); \
const int dst_linesize = td->dst_linesize / sizeof(type); \
const type *src_r = (const type *)(td->srcrow[R]) + src_linesize * slice_start; \
diff --git a/libavfilter/vf_colormap.c b/libavfilter/vf_colormap.c
index e0afc471ef..4680a7b501 100644
--- a/libavfilter/vf_colormap.c
+++ b/libavfilter/vf_colormap.c
@@ -309,8 +309,8 @@ static int colormap_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_job
const int maps = s->nb_maps;
const int width = out->width;
const int height = out->height;
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const int sr_linesize = in->linesize[2] / 4;
const int dr_linesize = out->linesize[2] / 4;
const int sg_linesize = in->linesize[0] / 4;
diff --git a/libavfilter/vf_colormatrix.c b/libavfilter/vf_colormatrix.c
index 04504cd3fb..596548cea4 100644
--- a/libavfilter/vf_colormatrix.c
+++ b/libavfilter/vf_colormatrix.c
@@ -209,8 +209,8 @@ static int process_slice_uyvy422(AVFilterContext *ctx, void *arg, int jobnr, int
const int width = src->width*2;
const int src_pitch = src->linesize[0];
const int dst_pitch = dst->linesize[0];
- const int slice_start = (height * jobnr ) / nb_jobs;
- const int slice_end = (height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const unsigned char *srcp = src->data[0] + slice_start * src_pitch;
unsigned char *dstp = dst->data[0] + slice_start * dst_pitch;
const int c2 = td->c2;
@@ -245,8 +245,8 @@ static int process_slice_yuv444p(AVFilterContext *ctx, void *arg, int jobnr, int
AVFrame *dst = td->dst;
const int height = src->height;
const int width = src->width;
- const int slice_start = (height * jobnr ) / nb_jobs;
- const int slice_end = (height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const int src_pitchY = src->linesize[0];
const int src_pitchUV = src->linesize[1];
const unsigned char *srcpU = src->data[1] + slice_start * src_pitchUV;
@@ -292,8 +292,8 @@ static int process_slice_yuv422p(AVFilterContext *ctx, void *arg, int jobnr, int
AVFrame *dst = td->dst;
const int height = src->height;
const int width = src->width;
- const int slice_start = (height * jobnr ) / nb_jobs;
- const int slice_end = (height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const int src_pitchY = src->linesize[0];
const int src_pitchUV = src->linesize[1];
const unsigned char *srcpU = src->data[1] + slice_start * src_pitchUV;
@@ -340,8 +340,8 @@ static int process_slice_yuv420p(AVFilterContext *ctx, void *arg, int jobnr, int
AVFrame *dst = td->dst;
const int height = FFALIGN(src->height, 2) >> 1;
const int width = src->width;
- const int slice_start = ((height * jobnr ) / nb_jobs) << 1;
- const int slice_end = ((height * (jobnr+1)) / nb_jobs) << 1;
+ const int slice_start = (ff_slice_pos(height, jobnr, nb_jobs)) << 1;
+ const int slice_end = (ff_slice_pos(height, jobnr + 1, nb_jobs)) << 1;
const int src_pitchY = src->linesize[0];
const int src_pitchUV = src->linesize[1];
const int dst_pitchY = dst->linesize[0];
diff --git a/libavfilter/vf_colortemperature.c b/libavfilter/vf_colortemperature.c
index b56bf837fb..1373c9e8c0 100644
--- a/libavfilter/vf_colortemperature.c
+++ b/libavfilter/vf_colortemperature.c
@@ -109,8 +109,8 @@ static int temperature_slice8(AVFilterContext *ctx, void *arg, int jobnr, int nb
const float mix = s->mix;
const float preserve = s->preserve;
const float *color = s->color;
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t glinesize = frame->linesize[0];
const ptrdiff_t blinesize = frame->linesize[1];
const ptrdiff_t rlinesize = frame->linesize[2];
@@ -151,8 +151,8 @@ static int temperature_slice16(AVFilterContext *ctx, void *arg, int jobnr, int n
const float preserve = s->preserve;
const float mix = s->mix;
const float *color = s->color;
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t glinesize = frame->linesize[0] / sizeof(uint16_t);
const ptrdiff_t blinesize = frame->linesize[1] / sizeof(uint16_t);
const ptrdiff_t rlinesize = frame->linesize[2] / sizeof(uint16_t);
@@ -192,8 +192,8 @@ static int temperature_slice32(AVFilterContext *ctx, void *arg, int jobnr, int n
const float preserve = s->preserve;
const float mix = s->mix;
const float *color = s->color;
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t glinesize = frame->linesize[0] / sizeof(float);
const ptrdiff_t blinesize = frame->linesize[1] / sizeof(float);
const ptrdiff_t rlinesize = frame->linesize[2] / sizeof(float);
@@ -237,8 +237,8 @@ static int temperature_slice8p(AVFilterContext *ctx, void *arg, int jobnr, int n
const uint8_t roffset = s->rgba_map[R];
const uint8_t goffset = s->rgba_map[G];
const uint8_t boffset = s->rgba_map[B];
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t linesize = frame->linesize[0];
uint8_t *ptr = frame->data[0] + slice_start * linesize;
@@ -277,8 +277,8 @@ static int temperature_slice16p(AVFilterContext *ctx, void *arg, int jobnr, int
const uint8_t roffset = s->rgba_map[R];
const uint8_t goffset = s->rgba_map[G];
const uint8_t boffset = s->rgba_map[B];
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t linesize = frame->linesize[0] / sizeof(uint16_t);
uint16_t *ptr = (uint16_t *)frame->data[0] + slice_start * linesize;
diff --git a/libavfilter/vf_convolution.c b/libavfilter/vf_convolution.c
index 7a27bdba20..59dcc9340a 100644
--- a/libavfilter/vf_convolution.c
+++ b/libavfilter/vf_convolution.c
@@ -582,8 +582,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
const int dstride = out->linesize[plane];
const int sizeh = mode == MATRIX_COLUMN ? width : height;
const int sizew = mode == MATRIX_COLUMN ? height : width;
- const int slice_start = (sizeh * jobnr) / nb_jobs;
- const int slice_end = (sizeh * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(sizeh, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(sizeh, jobnr + 1, nb_jobs);
const float rdiv = s->rdiv[plane];
const float bias = s->bias[plane];
const uint8_t *src = in->data[plane];
diff --git a/libavfilter/vf_convolve.c b/libavfilter/vf_convolve.c
index ea9cc45882..80f1c52844 100644
--- a/libavfilter/vf_convolve.c
+++ b/libavfilter/vf_convolve.c
@@ -189,8 +189,8 @@ static int fft_horizontal(AVFilterContext *ctx, void *arg, int jobnr, int nb_job
AVComplexFloat *hdata_out = td->hdata_out;
const int plane = td->plane;
const int n = td->n;
- int start = (n * jobnr) / nb_jobs;
- int end = (n * (jobnr+1)) / nb_jobs;
+ int start = ff_slice_pos(n, jobnr, nb_jobs);
+ int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
int y;
for (y = start; y < end; y++) {
@@ -376,8 +376,8 @@ static int fft_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
AVComplexFloat *vdata_out = td->vdata_out;
const int plane = td->plane;
const int n = td->n;
- int start = (n * jobnr) / nb_jobs;
- int end = (n * (jobnr+1)) / nb_jobs;
+ int start = ff_slice_pos(n, jobnr, nb_jobs);
+ int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
int y, x;
for (y = start; y < end; y++) {
@@ -401,8 +401,8 @@ static int ifft_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs
AVComplexFloat *vdata_in = td->vdata_in;
const int plane = td->plane;
const int n = td->n;
- int start = (n * jobnr) / nb_jobs;
- int end = (n * (jobnr+1)) / nb_jobs;
+ int start = ff_slice_pos(n, jobnr, nb_jobs);
+ int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
int y, x;
for (y = start; y < end; y++) {
@@ -425,8 +425,8 @@ static int ifft_horizontal(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
AVComplexFloat *hdata_in = td->hdata_in;
const int plane = td->plane;
const int n = td->n;
- int start = (n * jobnr) / nb_jobs;
- int end = (n * (jobnr+1)) / nb_jobs;
+ int start = ff_slice_pos(n, jobnr, nb_jobs);
+ int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
int y;
for (y = start; y < end; y++) {
@@ -518,8 +518,8 @@ static int complex_multiply(AVFilterContext *ctx, void *arg, int jobnr, int nb_j
AVComplexFloat *filter = td->vdata_in;
const float noise = s->noise;
const int n = td->n;
- int start = (n * jobnr) / nb_jobs;
- int end = (n * (jobnr+1)) / nb_jobs;
+ int start = ff_slice_pos(n, jobnr, nb_jobs);
+ int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
int y, x;
for (y = start; y < end; y++) {
@@ -548,8 +548,8 @@ static int complex_xcorrelate(AVFilterContext *ctx, void *arg, int jobnr, int nb
AVComplexFloat *filter = td->vdata_in;
const int n = td->n;
const float scale = 1.f / (n * n);
- int start = (n * jobnr) / nb_jobs;
- int end = (n * (jobnr+1)) / nb_jobs;
+ int start = ff_slice_pos(n, jobnr, nb_jobs);
+ int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
for (int y = start; y < end; y++) {
int yn = y * n;
@@ -578,8 +578,8 @@ static int complex_divide(AVFilterContext *ctx, void *arg, int jobnr, int nb_job
AVComplexFloat *filter = td->vdata_in;
const float noise = s->noise;
const int n = td->n;
- int start = (n * jobnr) / nb_jobs;
- int end = (n * (jobnr+1)) / nb_jobs;
+ int start = ff_slice_pos(n, jobnr, nb_jobs);
+ int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
int y, x;
for (y = start; y < end; y++) {
diff --git a/libavfilter/vf_corr.c b/libavfilter/vf_corr.c
index 7b87fa2c48..e3234bd437 100644
--- a/libavfilter/vf_corr.c
+++ b/libavfilter/vf_corr.c
@@ -101,8 +101,8 @@ static int sum_##name(AVFilterContext *ctx, void *arg, \
sizeof(type); \
const int h = s->planeheight[c]; \
const int w = s->planewidth[c]; \
- const int slice_start = (h * jobnr) / nb_jobs; \
- const int slice_end = (h * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs); \
const type *src1 = (const type *)master->data[c] + \
linesize1 * slice_start; \
const type *src2 = (const type *)ref->data[c] + \
@@ -147,8 +147,8 @@ static int corr_##name(AVFilterContext *ctx, void *arg, \
const type *src2 = (const type *)ref->data[c]; \
const int h = s->planeheight[c]; \
const int w = s->planewidth[c]; \
- const int slice_start = (h * jobnr) / nb_jobs; \
- const int slice_end = (h * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs); \
const float scale = 1.f / s->max[c]; \
const float mean1 = s->mean[c][0]; \
const float mean2 = s->mean[c][1]; \
diff --git a/libavfilter/vf_curves.c b/libavfilter/vf_curves.c
index 1d4b2d3b6e..4a7a51a3db 100644
--- a/libavfilter/vf_curves.c
+++ b/libavfilter/vf_curves.c
@@ -757,8 +757,8 @@ static int filter_slice_packed(AVFilterContext *ctx, void *arg, int jobnr, int n
const uint8_t g = curves->rgba_map[G];
const uint8_t b = curves->rgba_map[B];
const uint8_t a = curves->rgba_map[A];
- const int slice_start = (in->height * jobnr ) / nb_jobs;
- const int slice_end = (in->height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(in->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(in->height, jobnr + 1, nb_jobs);
if (curves->is_16bit) {
for (y = slice_start; y < slice_end; y++) {
@@ -805,8 +805,8 @@ static int filter_slice_planar(AVFilterContext *ctx, void *arg, int jobnr, int n
const uint8_t g = curves->rgba_map[G];
const uint8_t b = curves->rgba_map[B];
const uint8_t a = curves->rgba_map[A];
- const int slice_start = (in->height * jobnr ) / nb_jobs;
- const int slice_end = (in->height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(in->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(in->height, jobnr + 1, nb_jobs);
if (curves->is_16bit) {
for (y = slice_start; y < slice_end; y++) {
diff --git a/libavfilter/vf_datascope.c b/libavfilter/vf_datascope.c
index 3b37fd162e..8d96d92b57 100644
--- a/libavfilter/vf_datascope.c
+++ b/libavfilter/vf_datascope.c
@@ -194,8 +194,8 @@ static int filter_color2(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs
const int W = (outlink->w - xoff) / (C * 10);
const int H = (outlink->h - yoff) / (PP * 12);
const char *format[4] = {"%02X\n", "%04X\n", "%03d\n", "%05d\n"};
- const int slice_start = (W * jobnr) / nb_jobs;
- const int slice_end = (W * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(W, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(W, jobnr + 1, nb_jobs);
int x, y, p;
for (y = 0; y < H && (y + s->y < inlink->h); y++) {
@@ -241,8 +241,8 @@ static int filter_color(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
const int W = (outlink->w - xoff) / (C * 10);
const int H = (outlink->h - yoff) / (PP * 12);
const char *format[4] = {"%02X\n", "%04X\n", "%03d\n", "%05d\n"};
- const int slice_start = (W * jobnr) / nb_jobs;
- const int slice_end = (W * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(W, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(W, jobnr + 1, nb_jobs);
int x, y, p;
for (y = 0; y < H && (y + s->y < inlink->h); y++) {
@@ -284,8 +284,8 @@ static int filter_mono(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
const int W = (outlink->w - xoff) / (C * 10);
const int H = (outlink->h - yoff) / (PP * 12);
const char *format[4] = {"%02X\n", "%04X\n", "%03d\n", "%05d\n"};
- const int slice_start = (W * jobnr) / nb_jobs;
- const int slice_end = (W * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(W, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(W, jobnr + 1, nb_jobs);
int x, y, p;
for (y = 0; y < H && (y + s->y < inlink->h); y++) {
diff --git a/libavfilter/vf_dctdnoiz.c b/libavfilter/vf_dctdnoiz.c
index 9241b3a9eb..90fa8ee6c6 100644
--- a/libavfilter/vf_dctdnoiz.c
+++ b/libavfilter/vf_dctdnoiz.c
@@ -675,8 +675,8 @@ static int filter_slice(AVFilterContext *ctx,
const ThreadData *td = arg;
const int w = s->pr_width;
const int h = s->pr_height;
- const int slice_start = (h * jobnr ) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
const int slice_start_ctx = FFMAX(slice_start - s->bsize + 1, 0);
const int slice_end_ctx = FFMIN(slice_end, h - s->bsize + 1);
const int slice_h = slice_end_ctx - slice_start_ctx;
diff --git a/libavfilter/vf_deband.c b/libavfilter/vf_deband.c
index 97bd33e20e..2ff4fca6fa 100644
--- a/libavfilter/vf_deband.c
+++ b/libavfilter/vf_deband.c
@@ -146,8 +146,8 @@ static int deband_8_c(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
const int dst_linesize = out->linesize[p];
const int src_linesize = in->linesize[p];
const int thr = s->thr[p];
- const int start = (s->planeheight[p] * jobnr ) / nb_jobs;
- const int end = (s->planeheight[p] * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(s->planeheight[p], jobnr, nb_jobs);
+ const int end = ff_slice_pos(s->planeheight[p], jobnr + 1, nb_jobs);
const int w = s->planewidth[p] - 1;
const int h = s->planeheight[p] - 1;
@@ -187,8 +187,8 @@ static int deband_8_coupling_c(AVFilterContext *ctx, void *arg, int jobnr, int n
ThreadData *td = arg;
AVFrame *in = td->in;
AVFrame *out = td->out;
- const int start = (s->planeheight[0] * jobnr ) / nb_jobs;
- const int end = (s->planeheight[0] * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(s->planeheight[0], jobnr, nb_jobs);
+ const int end = ff_slice_pos(s->planeheight[0], jobnr + 1, nb_jobs);
int x, y, p;
for (y = start; y < end; y++) {
@@ -252,8 +252,8 @@ static int deband_16_coupling_c(AVFilterContext *ctx, void *arg, int jobnr, int
ThreadData *td = arg;
AVFrame *in = td->in;
AVFrame *out = td->out;
- const int start = (s->planeheight[0] * jobnr ) / nb_jobs;
- const int end = (s->planeheight[0] * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(s->planeheight[0], jobnr, nb_jobs);
+ const int end = ff_slice_pos(s->planeheight[0], jobnr + 1, nb_jobs);
int x, y, p, z;
for (y = start; y < end; y++) {
@@ -327,8 +327,8 @@ static int deband_16_c(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
const int dst_linesize = out->linesize[p] / 2;
const int src_linesize = in->linesize[p] / 2;
const int thr = s->thr[p];
- const int start = (s->planeheight[p] * jobnr ) / nb_jobs;
- const int end = (s->planeheight[p] * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(s->planeheight[p], jobnr, nb_jobs);
+ const int end = ff_slice_pos(s->planeheight[p], jobnr + 1, nb_jobs);
const int w = s->planewidth[p] - 1;
const int h = s->planeheight[p] - 1;
diff --git a/libavfilter/vf_dedot.c b/libavfilter/vf_dedot.c
index 69b92141d1..c37626a34a 100644
--- a/libavfilter/vf_dedot.c
+++ b/libavfilter/vf_dedot.c
@@ -84,8 +84,8 @@ static int dedotcrawl##name(AVFilterContext *ctx, void *arg, \
int p3_linesize = s->frames[3]->linesize[0] / div; \
int p4_linesize = s->frames[4]->linesize[0] / div; \
const int h = s->planeheight[0]; \
- int slice_start = (h * jobnr) / nb_jobs; \
- int slice_end = (h * (jobnr+1)) / nb_jobs; \
+ int slice_start = ff_slice_pos(h, jobnr, nb_jobs); \
+ int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs); \
type *p0 = (type *)s->frames[0]->data[0]; \
type *p1 = (type *)s->frames[1]->data[0]; \
type *p3 = (type *)s->frames[3]->data[0]; \
@@ -159,8 +159,8 @@ static int derainbow##name(AVFilterContext *ctx, void *arg, \
AVFrame *out = td->out; \
const int plane = td->plane; \
const int h = s->planeheight[plane]; \
- int slice_start = (h * jobnr) / nb_jobs; \
- int slice_end = (h * (jobnr+1)) / nb_jobs; \
+ int slice_start = ff_slice_pos(h, jobnr, nb_jobs); \
+ int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs); \
int src_linesize = s->frames[2]->linesize[plane] / div; \
int dst_linesize = out->linesize[plane] / div; \
int p0_linesize = s->frames[0]->linesize[plane] / div; \
diff --git a/libavfilter/vf_despill.c b/libavfilter/vf_despill.c
index 25bdd1acd7..2ecbab0390 100644
--- a/libavfilter/vf_despill.c
+++ b/libavfilter/vf_despill.c
@@ -43,8 +43,8 @@ static int do_despill_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_j
DespillContext *s = ctx->priv;
AVFrame *frame = arg;
const int ro = s->co[0], go = s->co[1], bo = s->co[2], ao = s->co[3];
- const int slice_start = (frame->height * jobnr) / nb_jobs;
- const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(frame->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(frame->height, jobnr + 1, nb_jobs);
const float brightness = s->brightness;
const float redscale = s->redscale;
const float greenscale = s->greenscale;
diff --git a/libavfilter/vf_displace.c b/libavfilter/vf_displace.c
index 3a860fc973..eef9a9970f 100644
--- a/libavfilter/vf_displace.c
+++ b/libavfilter/vf_displace.c
@@ -90,8 +90,8 @@ static int displace_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
for (int plane = 0; plane < s->nb_planes; plane++) {
const int h = s->height[plane];
const int w = s->width[plane];
- const int slice_start = (h * jobnr ) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
const int dlinesize = out->linesize[plane];
const int slinesize = in->linesize[plane];
const int xlinesize = xin->linesize[plane];
@@ -171,8 +171,8 @@ static int displace_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
const int step = s->step;
const int h = s->height[0];
const int w = s->width[0];
- const int slice_start = (h * jobnr ) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
const int dlinesize = out->linesize[0];
const int slinesize = in->linesize[0];
const int xlinesize = xin->linesize[0];
diff --git a/libavfilter/vf_epx.c b/libavfilter/vf_epx.c
index af40917b66..96b41a34b9 100644
--- a/libavfilter/vf_epx.c
+++ b/libavfilter/vf_epx.c
@@ -48,8 +48,8 @@ static int epx2_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
ThreadData *td = arg;
const AVFrame *in = td->in;
AVFrame *out = td->out;
- const int slice_start = (in->height * jobnr ) / nb_jobs;
- const int slice_end = (in->height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(in->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(in->height, jobnr + 1, nb_jobs);
for (int p = 0; p < 1; p++) {
const int width = in->width;
@@ -115,8 +115,8 @@ static int epx3_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
ThreadData *td = arg;
const AVFrame *in = td->in;
AVFrame *out = td->out;
- const int slice_start = (in->height * jobnr ) / nb_jobs;
- const int slice_end = (in->height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(in->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(in->height, jobnr + 1, nb_jobs);
for (int p = 0; p < 1; p++) {
const int width = in->width;
diff --git a/libavfilter/vf_estdif.c b/libavfilter/vf_estdif.c
index 6fdfe19e7e..ae61e2bce6 100644
--- a/libavfilter/vf_estdif.c
+++ b/libavfilter/vf_estdif.c
@@ -354,8 +354,8 @@ static int deinterlace_slice(AVFilterContext *ctx, void *arg,
const int height = s->planeheight[plane];
const int src_linesize = in->linesize[plane];
const int dst_linesize = out->linesize[plane];
- const int start = (int)((int64_t)height * jobnr / nb_jobs);
- const int end = (int)((int64_t)height * (jobnr + 1) / nb_jobs);
+ const int start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const uint8_t *prev_line, *prev2_line, *next_line, *next2_line, *in_line;
const uint8_t *prev3_line, *next3_line;
uint8_t *out_line;
diff --git a/libavfilter/vf_exposure.c b/libavfilter/vf_exposure.c
index 833aa953d5..486659160c 100644
--- a/libavfilter/vf_exposure.c
+++ b/libavfilter/vf_exposure.c
@@ -46,8 +46,8 @@ static int exposure_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_job
ThreadData *td = arg;
const int width = td->out->width;
const int height = td->out->height;
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const float black = s->black;
const float scale = s->scale;
diff --git a/libavfilter/vf_fade.c b/libavfilter/vf_fade.c
index efe0ea380d..08ef733787 100644
--- a/libavfilter/vf_fade.c
+++ b/libavfilter/vf_fade.c
@@ -253,8 +253,8 @@ static int filter_slice_rgb(AVFilterContext *ctx, void *arg, int jobnr,
{
FadeContext *s = ctx->priv;
AVFrame *frame = arg;
- int slice_start = (frame->height * jobnr ) / nb_jobs;
- int slice_end = (frame->height * (jobnr+1)) / nb_jobs;
+ int slice_start = ff_slice_pos(frame->height, jobnr, nb_jobs);
+ int slice_end = ff_slice_pos(frame->height, jobnr + 1, nb_jobs);
if (s->is_planar && s->alpha)
filter_rgb_planar(s, frame, slice_start, slice_end, 1);
@@ -273,8 +273,8 @@ static int filter_slice_luma(AVFilterContext *ctx, void *arg, int jobnr,
{
FadeContext *s = ctx->priv;
AVFrame *frame = arg;
- int slice_start = (frame->height * jobnr ) / nb_jobs;
- int slice_end = (frame->height * (jobnr+1)) / nb_jobs;
+ int slice_start = ff_slice_pos(frame->height, jobnr, nb_jobs);
+ int slice_end = ff_slice_pos(frame->height, jobnr + 1, nb_jobs);
int i, j;
for (int k = 0; k < 1 + 2 * (s->is_planar && s->is_rgb); k++) {
@@ -298,8 +298,8 @@ static int filter_slice_luma16(AVFilterContext *ctx, void *arg, int jobnr,
{
FadeContext *s = ctx->priv;
AVFrame *frame = arg;
- int slice_start = (frame->height * jobnr ) / nb_jobs;
- int slice_end = (frame->height * (jobnr+1)) / nb_jobs;
+ int slice_start = ff_slice_pos(frame->height, jobnr, nb_jobs);
+ int slice_end = ff_slice_pos(frame->height, jobnr + 1, nb_jobs);
int i, j;
for (int k = 0; k < 1 + 2 * (s->is_planar && s->is_rgb); k++) {
@@ -326,8 +326,8 @@ static int filter_slice_chroma(AVFilterContext *ctx, void *arg, int jobnr,
int i, j, plane;
const int width = AV_CEIL_RSHIFT(frame->width, s->hsub);
const int height= AV_CEIL_RSHIFT(frame->height, s->vsub);
- int slice_start = (height * jobnr ) / nb_jobs;
- int slice_end = FFMIN(((height * (jobnr+1)) / nb_jobs), frame->height);
+ int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ int slice_end = FFMIN((ff_slice_pos(height, jobnr + 1, nb_jobs)), frame->height);
for (plane = 1; plane < 3; plane++) {
for (i = slice_start; i < slice_end; i++) {
@@ -355,8 +355,8 @@ static int filter_slice_chroma16(AVFilterContext *ctx, void *arg, int jobnr,
const int height= AV_CEIL_RSHIFT(frame->height, s->vsub);
const int mid = 1 << (s->depth - 1);
const int add = ((mid << 1) + 1) << 15;
- int slice_start = (height * jobnr ) / nb_jobs;
- int slice_end = FFMIN(((height * (jobnr+1)) / nb_jobs), frame->height);
+ int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ int slice_end = FFMIN((ff_slice_pos(height, jobnr + 1, nb_jobs)), frame->height);
for (plane = 1; plane < 3; plane++) {
for (i = slice_start; i < slice_end; i++) {
@@ -377,8 +377,8 @@ static int filter_slice_alpha(AVFilterContext *ctx, void *arg, int jobnr,
FadeContext *s = ctx->priv;
AVFrame *frame = arg;
int plane = s->is_packed_rgb ? 0 : A;
- int slice_start = (frame->height * jobnr ) / nb_jobs;
- int slice_end = (frame->height * (jobnr+1)) / nb_jobs;
+ int slice_start = ff_slice_pos(frame->height, jobnr, nb_jobs);
+ int slice_end = ff_slice_pos(frame->height, jobnr + 1, nb_jobs);
int i, j;
for (i = slice_start; i < slice_end; i++) {
@@ -402,8 +402,8 @@ static int filter_slice_alpha16(AVFilterContext *ctx, void *arg, int jobnr,
FadeContext *s = ctx->priv;
AVFrame *frame = arg;
int plane = s->is_packed_rgb ? 0 : A;
- int slice_start = (frame->height * jobnr ) / nb_jobs;
- int slice_end = (frame->height * (jobnr+1)) / nb_jobs;
+ int slice_start = ff_slice_pos(frame->height, jobnr, nb_jobs);
+ int slice_end = ff_slice_pos(frame->height, jobnr + 1, nb_jobs);
int i, j;
for (i = slice_start; i < slice_end; i++) {
diff --git a/libavfilter/vf_fftdnoiz.c b/libavfilter/vf_fftdnoiz.c
index 13afbf0377..66a889776a 100644
--- a/libavfilter/vf_fftdnoiz.c
+++ b/libavfilter/vf_fftdnoiz.c
@@ -549,8 +549,8 @@ static int denoise(AVFilterContext *ctx, void *arg,
PlaneContext *p = &s->planes[plane];
const int nox = p->nox;
const int noy = p->noy;
- const int slice_start = (noy * jobnr) / nb_jobs;
- const int slice_end = (noy * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(noy, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(noy, jobnr + 1, nb_jobs);
if (!((1 << plane) & s->planesf) || ctx->is_disabled)
continue;
diff --git a/libavfilter/vf_fftfilt.c b/libavfilter/vf_fftfilt.c
index b94008fc15..043479b0c3 100644
--- a/libavfilter/vf_fftfilt.c
+++ b/libavfilter/vf_fftfilt.c
@@ -133,8 +133,8 @@ static int rdft_horizontal8(AVFilterContext *ctx, void *arg, int jobnr, int nb_j
for (int plane = 0; plane < s->nb_planes; plane++) {
const int w = s->planewidth[plane];
const int h = s->planeheight[plane];
- const int slice_start = (h * jobnr) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
for (int i = slice_start; i < slice_end; i++) {
const uint8_t *src = in->data[plane] + i * in->linesize[plane];
@@ -164,8 +164,8 @@ static int rdft_horizontal16(AVFilterContext *ctx, void *arg, int jobnr, int nb_
for (int plane = 0; plane < s->nb_planes; plane++) {
const int w = s->planewidth[plane];
const int h = s->planeheight[plane];
- const int slice_start = (h * jobnr) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
for (int i = slice_start; i < slice_end; i++) {
const uint16_t *src = (const uint16_t *)(in->data[plane] + i * in->linesize[plane]);
@@ -195,8 +195,8 @@ static int irdft_horizontal8(AVFilterContext *ctx, void *arg, int jobnr, int nb_
for (int plane = 0; plane < s->nb_planes; plane++) {
const int w = s->planewidth[plane];
const int h = s->planeheight[plane];
- const int slice_start = (h * jobnr) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
for (int i = slice_start; i < slice_end; i++)
s->ihtx_fn(s->ihrdft[jobnr][plane],
@@ -226,8 +226,8 @@ static int irdft_horizontal16(AVFilterContext *ctx, void *arg, int jobnr, int nb
int max = (1 << s->depth) - 1;
const int w = s->planewidth[plane];
const int h = s->planeheight[plane];
- const int slice_start = (h * jobnr) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
for (int i = slice_start; i < slice_end; i++)
s->ihtx_fn(s->ihrdft[jobnr][plane],
@@ -396,8 +396,8 @@ static int multiply_data(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs
for (int plane = 0; plane < s->nb_planes; plane++) {
const int height = s->rdft_hlen[plane];
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
/*Change user defined parameters*/
for (int i = slice_start; i < slice_end; i++) {
const double *weight = s->weight[plane] + i * s->rdft_vlen[plane];
@@ -420,8 +420,8 @@ static int copy_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs
const int vlen = s->rdft_vlen[plane];
const int hstride = s->rdft_hstride[plane];
const int vstride = s->rdft_vstride[plane];
- const int slice_start = (hlen * jobnr) / nb_jobs;
- const int slice_end = (hlen * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(hlen, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(hlen, jobnr + 1, nb_jobs);
const int h = s->planeheight[plane];
float *hdata = s->rdft_hdata_out[plane];
float *vdata = s->rdft_vdata_in[plane];
@@ -442,8 +442,8 @@ static int rdft_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs
for (int plane = 0; plane < s->nb_planes; plane++) {
const int height = s->rdft_hlen[plane];
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
for (int i = slice_start; i < slice_end; i++)
s->vtx_fn(s->vrdft[jobnr][plane],
@@ -461,8 +461,8 @@ static int irdft_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_job
for (int plane = 0; plane < s->nb_planes; plane++) {
const int height = s->rdft_hlen[plane];
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
for (int i = slice_start; i < slice_end; i++)
s->ivtx_fn(s->ivrdft[jobnr][plane],
@@ -482,8 +482,8 @@ static int copy_horizontal(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
const int hlen = s->rdft_hlen[plane];
const int hstride = s->rdft_hstride[plane];
const int vstride = s->rdft_vstride[plane];
- const int slice_start = (hlen * jobnr) / nb_jobs;
- const int slice_end = (hlen * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(hlen, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(hlen, jobnr + 1, nb_jobs);
const int h = s->planeheight[plane];
float *hdata = s->rdft_hdata_in[plane];
float *vdata = s->rdft_vdata_in[plane];
diff --git a/libavfilter/vf_gblur.c b/libavfilter/vf_gblur.c
index 0b37562663..45320333fa 100644
--- a/libavfilter/vf_gblur.c
+++ b/libavfilter/vf_gblur.c
@@ -61,8 +61,8 @@ static int filter_horizontally(AVFilterContext *ctx, void *arg, int jobnr, int n
ThreadData *td = arg;
const int height = td->height;
const int width = td->width;
- const int slice_start = (height * jobnr ) / nb_jobs;
- const int slice_end = (height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const float boundaryscale = s->boundaryscale;
const int steps = s->steps;
const float nu = s->nu;
@@ -83,8 +83,8 @@ static int filter_vertically(AVFilterContext *ctx, void *arg, int jobnr, int nb_
ThreadData *td = arg;
const int height = td->height;
const int width = td->width;
- const int slice_start = (width * jobnr ) / nb_jobs;
- const int slice_end = (width * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(width, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(width, jobnr + 1, nb_jobs);
const float boundaryscale = s->boundaryscaleV;
const int steps = s->steps;
const float nu = s->nuV;
@@ -105,8 +105,8 @@ static int filter_postscale(AVFilterContext *ctx, void *arg, int jobnr, int nb_j
const int height = td->height;
const int width = td->width;
const int awidth = FFALIGN(width, 64);
- const int slice_start = (height * jobnr ) / nb_jobs;
- const int slice_end = (height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const float postscale = s->postscale * s->postscaleV;
const int slice_size = slice_end - slice_start;
diff --git a/libavfilter/vf_geq.c b/libavfilter/vf_geq.c
index 13b0065956..1256bbe971 100644
--- a/libavfilter/vf_geq.c
+++ b/libavfilter/vf_geq.c
@@ -405,8 +405,8 @@ static int slice_geq_filter(AVFilterContext *ctx, void *arg, int jobnr, int nb_j
const int width = td->width;
const int plane = td->plane;
const int linesize = td->linesize;
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
int x, y;
double values[VAR_VARS_NB];
diff --git a/libavfilter/vf_grayworld.c b/libavfilter/vf_grayworld.c
index 21d6aafd9a..c1821eb7b8 100644
--- a/libavfilter/vf_grayworld.c
+++ b/libavfilter/vf_grayworld.c
@@ -126,8 +126,8 @@ static int convert_frame(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs
AVFrame *in = td->in;
AVFrame *out = td->out;
AVFilterLink *outlink = ctx->outputs[0];
- const int slice_start = (out->height * jobnr) / nb_jobs;
- const int slice_end = (out->height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(out->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(out->height, jobnr + 1, nb_jobs);
float rgb[3], lab[3];
for (int i = slice_start; i < slice_end; i++) {
@@ -193,8 +193,8 @@ static int correct_frame(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs
ThreadData *td = arg;
AVFrame *out = td->out;
AVFilterLink *outlink = ctx->outputs[0];
- const int slice_start = (out->height * jobnr) / nb_jobs;
- const int slice_end = (out->height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(out->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(out->height, jobnr + 1, nb_jobs);
float rgb[3], lab[3];
for (int i = slice_start; i < slice_end; i++) {
diff --git a/libavfilter/vf_guided.c b/libavfilter/vf_guided.c
index 4749beab48..005b2128f3 100644
--- a/libavfilter/vf_guided.c
+++ b/libavfilter/vf_guided.c
@@ -113,8 +113,8 @@ static int box_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
const int height = t->height;
const int src_stride = t->srcStride;
const int dst_stride = t->dstStride;
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const int radius = s->radius;
const float *src = t->src;
float *dst = t->dst;
diff --git a/libavfilter/vf_hqx.c b/libavfilter/vf_hqx.c
index 4dcd03514f..370dbc0d7d 100644
--- a/libavfilter/vf_hqx.c
+++ b/libavfilter/vf_hqx.c
@@ -388,8 +388,8 @@ static av_always_inline void hqx_filter(const ThreadData *td, int jobnr, int nb_
const uint32_t *r2y = td->rgbtoyuv;
const int height = in->height;
const int width = in->width;
- const int slice_start = (height * jobnr ) / nb_jobs;
- const int slice_end = (height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const int dst_linesize = out->linesize[0];
const int src_linesize = in->linesize[0];
uint8_t *dst = out->data[0] + slice_start * dst_linesize * n;
diff --git a/libavfilter/vf_hsvkey.c b/libavfilter/vf_hsvkey.c
index 9a1a897a94..804bd8ae04 100644
--- a/libavfilter/vf_hsvkey.c
+++ b/libavfilter/vf_hsvkey.c
@@ -88,8 +88,8 @@ static int do_hsvkey_slice(AVFilterContext *avctx, void *arg, int jobnr, int nb_
{
HSVKeyContext *s = avctx->priv;
AVFrame *frame = arg;
- const int slice_start = (frame->height * jobnr) / nb_jobs;
- const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(frame->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(frame->height, jobnr + 1, nb_jobs);
const int hsub_log2 = s->hsub_log2;
const int vsub_log2 = s->vsub_log2;
const float hue = s->hue;
@@ -113,8 +113,8 @@ static int do_hsvkey16_slice(AVFilterContext *avctx, void *arg, int jobnr, int n
{
HSVKeyContext *s = avctx->priv;
AVFrame *frame = arg;
- const int slice_start = (frame->height * jobnr) / nb_jobs;
- const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(frame->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(frame->height, jobnr + 1, nb_jobs);
const int hsub_log2 = s->hsub_log2;
const int vsub_log2 = s->vsub_log2;
const float hue = s->hue;
@@ -143,8 +143,8 @@ static int do_hsvhold_slice(AVFilterContext *avctx, void *arg, int jobnr, int nb
const int vsub_log2 = s->vsub_log2;
const int width = frame->width >> hsub_log2;
const int height = frame->height >> vsub_log2;
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const float scale = s->scale;
const float hue = s->hue;
const float sat = s->sat;
@@ -179,8 +179,8 @@ static int do_hsvhold16_slice(AVFilterContext *avctx, void *arg, int jobnr, int
const int vsub_log2 = s->vsub_log2;
const int width = frame->width >> hsub_log2;
const int height = frame->height >> vsub_log2;
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const float scale = s->scale;
const float half = s->half;
const float hue = s->hue;
diff --git a/libavfilter/vf_huesaturation.c b/libavfilter/vf_huesaturation.c
index 7e1b4d1e9d..6a4aadeee1 100644
--- a/libavfilter/vf_huesaturation.c
+++ b/libavfilter/vf_huesaturation.c
@@ -103,8 +103,8 @@ static int do_slice_##name##_##xall(AVFilterContext *ctx, \
const int step = s->step; \
const int width = frame->width; \
const int process_h = frame->height; \
- const int slice_start = (process_h * jobnr ) / nb_jobs; \
- const int slice_end = (process_h * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(process_h, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(process_h, jobnr + 1, nb_jobs); \
const ptrdiff_t linesize = frame->linesize[0] / sizeof(type); \
type *row = (type *)frame->data[0] + linesize * slice_start; \
const uint8_t offset_r = s->rgba_map[R]; \
diff --git a/libavfilter/vf_identity.c b/libavfilter/vf_identity.c
index 6a94a92355..2e6c06ea7e 100644
--- a/libavfilter/vf_identity.c
+++ b/libavfilter/vf_identity.c
@@ -103,8 +103,8 @@ int compute_images_msad(AVFilterContext *ctx, void *arg,
for (int c = 0; c < td->nb_components; c++) {
const int outw = td->planewidth[c];
const int outh = td->planeheight[c];
- const int slice_start = (outh * jobnr) / nb_jobs;
- const int slice_end = (outh * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(outh, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(outh, jobnr + 1, nb_jobs);
const int ref_linesize = td->ref_linesize[c];
const int main_linesize = td->main_linesize[c];
const uint8_t *main_line = td->main_data[c] + main_linesize * slice_start;
@@ -131,8 +131,8 @@ int compute_images_identity(AVFilterContext *ctx, void *arg,
for (int c = 0; c < td->nb_components; c++) {
const int outw = td->planewidth[c];
const int outh = td->planeheight[c];
- const int slice_start = (outh * jobnr) / nb_jobs;
- const int slice_end = (outh * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(outh, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(outh, jobnr + 1, nb_jobs);
const int ref_linesize = td->ref_linesize[c];
const int main_linesize = td->main_linesize[c];
const uint8_t *main_line = td->main_data[c] + main_linesize * slice_start;
diff --git a/libavfilter/vf_lagfun.c b/libavfilter/vf_lagfun.c
index 9ec936212c..1fdb1b66b0 100644
--- a/libavfilter/vf_lagfun.c
+++ b/libavfilter/vf_lagfun.c
@@ -81,8 +81,8 @@ static int lagfun_frame##name(AVFilterContext *ctx, void *arg, \
AVFrame *out = td->out; \
\
for (int p = 0; p < s->nb_planes; p++) { \
- const int slice_start = (s->planeheight[p] * jobnr) / nb_jobs; \
- const int slice_end = (s->planeheight[p] * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(s->planeheight[p], jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(s->planeheight[p], jobnr + 1, nb_jobs); \
const int width = s->planewidth[p]; \
const type *src = (const type *)in->data[p] + \
slice_start * in->linesize[p] / sizeof(type); \
diff --git a/libavfilter/vf_lensfun.c b/libavfilter/vf_lensfun.c
index 668c68562c..3b7403c26a 100644
--- a/libavfilter/vf_lensfun.c
+++ b/libavfilter/vf_lensfun.c
@@ -284,8 +284,8 @@ static int config_props(AVFilterLink *inlink)
static int vignetting_filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
{
const VignettingThreadData *thread_data = arg;
- const int slice_start = thread_data->height * jobnr / nb_jobs;
- const int slice_end = thread_data->height * (jobnr + 1) / nb_jobs;
+ const int slice_start = ff_slice_pos(thread_data->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(thread_data->height, jobnr + 1, nb_jobs);
lf_modifier_apply_color_modification(thread_data->modifier,
thread_data->data_in + slice_start * thread_data->linesize_in,
@@ -307,8 +307,8 @@ static float square(float x)
static int distortion_correction_filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
{
const DistortionCorrectionThreadData *thread_data = arg;
- const int slice_start = thread_data->height * jobnr / nb_jobs;
- const int slice_end = thread_data->height * (jobnr + 1) / nb_jobs;
+ const int slice_start = ff_slice_pos(thread_data->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(thread_data->height, jobnr + 1, nb_jobs);
int x, y, i, j, rgb_index;
float interpolated, new_x, new_y, d, norm;
diff --git a/libavfilter/vf_limitdiff.c b/libavfilter/vf_limitdiff.c
index d823275528..fe24df9cca 100644
--- a/libavfilter/vf_limitdiff.c
+++ b/libavfilter/vf_limitdiff.c
@@ -170,8 +170,8 @@ static int limitdiff_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
const int thr2 = s->thr2;
const int w = s->planewidth[p];
const int h = s->planeheight[p];
- const int slice_start = (h * jobnr) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
const uint8_t *filtered = td->filtered->data[p] + slice_start * filtered_linesize;
const uint8_t *source = td->source->data[p] + slice_start * source_linesize;
const uint8_t *reference = td->reference->data[p] + slice_start * reference_linesize;
diff --git a/libavfilter/vf_limiter.c b/libavfilter/vf_limiter.c
index 4f50ace386..68e7e9d98d 100644
--- a/libavfilter/vf_limiter.c
+++ b/libavfilter/vf_limiter.c
@@ -157,8 +157,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
for (p = 0; p < s->nb_planes; p++) {
const int h = s->height[p];
- const int slice_start = (h * jobnr) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
if (!((1 << p) & s->planes)) {
if (out != in)
diff --git a/libavfilter/vf_lumakey.c b/libavfilter/vf_lumakey.c
index a827d31b48..6e13fbc607 100644
--- a/libavfilter/vf_lumakey.c
+++ b/libavfilter/vf_lumakey.c
@@ -43,8 +43,8 @@ static int do_lumakey_slice8(AVFilterContext *ctx, void *arg, int jobnr, int nb_
{
LumakeyContext *s = ctx->priv;
AVFrame *frame = arg;
- const int slice_start = (frame->height * jobnr) / nb_jobs;
- const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(frame->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(frame->height, jobnr + 1, nb_jobs);
uint8_t *alpha = frame->data[3] + slice_start * frame->linesize[3];
const uint8_t *luma = frame->data[0] + slice_start * frame->linesize[0];
const int so = s->so;
@@ -75,8 +75,8 @@ static int do_lumakey_slice16(AVFilterContext *ctx, void *arg, int jobnr, int nb
{
LumakeyContext *s = ctx->priv;
AVFrame *frame = arg;
- const int slice_start = (frame->height * jobnr) / nb_jobs;
- const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(frame->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(frame->height, jobnr + 1, nb_jobs);
uint16_t *alpha = (uint16_t *)(frame->data[3] + slice_start * frame->linesize[3]);
const uint16_t *luma = (const uint16_t *)(frame->data[0] + slice_start * frame->linesize[0]);
const int so = s->so;
diff --git a/libavfilter/vf_lut.c b/libavfilter/vf_lut.c
index ac0636dc52..a3fbb7b2a3 100644
--- a/libavfilter/vf_lut.c
+++ b/libavfilter/vf_lut.c
@@ -358,8 +358,8 @@ struct thread_data {
const uint16_t (*tab)[256*256] = (const uint16_t (*)[256*256])s->lut;\
const int step = s->step;\
\
- const int slice_start = (h * jobnr ) / nb_jobs;\
- const int slice_end = (h * (jobnr+1)) / nb_jobs;\
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs); \
/* packed, 16-bit */
static int lut_packed_16bits(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
@@ -441,8 +441,8 @@ static int lut_packed_8bits(AVFilterContext *ctx, void *arg, int jobnr, int nb_j
int w = AV_CEIL_RSHIFT(td->w, hsub);\
const uint16_t *tab = s->lut[plane];\
\
- const int slice_start = (h * jobnr ) / nb_jobs;\
- const int slice_end = (h * (jobnr+1)) / nb_jobs;\
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs); \
/* planar >8 bit depth */
static int lut_planar_16bits(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
diff --git a/libavfilter/vf_lut2.c b/libavfilter/vf_lut2.c
index 3b8ee3af65..cabdc980ea 100644
--- a/libavfilter/vf_lut2.c
+++ b/libavfilter/vf_lut2.c
@@ -259,8 +259,8 @@ static int lut2_##zname##_##xname##_##yname(AVFilterContext *ctx,
int p, y, x; \
\
for (p = 0; p < s->nb_planes; p++) { \
- const int slice_start = (s->heightx[p] * jobnr) / nb_jobs; \
- const int slice_end = (s->heightx[p] * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(s->heightx[p], jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(s->heightx[p], jobnr + 1, nb_jobs); \
const uint16_t *lut = s->lut[p]; \
const xtype *srcxx; \
const ytype *srcyy; \
diff --git a/libavfilter/vf_lut3d.c b/libavfilter/vf_lut3d.c
index 4ed609d810..6ab33790c6 100644
--- a/libavfilter/vf_lut3d.c
+++ b/libavfilter/vf_lut3d.c
@@ -328,8 +328,8 @@ static int interp_##nbits##_##name##_p##depth(AVFilterContext *ctx, void *arg, i
const AVFrame *in = td->in; \
const AVFrame *out = td->out; \
const int direct = out == in; \
- const int slice_start = (in->height * jobnr ) / nb_jobs; \
- const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(in->height, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(in->height, jobnr + 1, nb_jobs); \
uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
@@ -426,8 +426,8 @@ static int interp_##name##_pf##depth(AVFilterContext *ctx, void *arg, int jobnr,
const AVFrame *in = td->in; \
const AVFrame *out = td->out; \
const int direct = out == in; \
- const int slice_start = (in->height * jobnr ) / nb_jobs; \
- const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(in->height, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(in->height, jobnr + 1, nb_jobs); \
uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
@@ -498,8 +498,8 @@ static int interp_##nbits##_##name(AVFilterContext *ctx, void *arg, int jobnr, i
const uint8_t g = lut3d->rgba_map[G]; \
const uint8_t b = lut3d->rgba_map[B]; \
const uint8_t a = lut3d->rgba_map[A]; \
- const int slice_start = (in->height * jobnr ) / nb_jobs; \
- const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(in->height, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(in->height, jobnr + 1, nb_jobs); \
uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; \
const uint8_t *srcrow = in ->data[0] + slice_start * in ->linesize[0]; \
const float lut_max = lut3d->lutsize - 1; \
@@ -1870,8 +1870,8 @@ static int interp_1d_##nbits##_##name##_p##depth(AVFilterContext *ctx, \
const AVFrame *in = td->in; \
const AVFrame *out = td->out; \
const int direct = out == in; \
- const int slice_start = (in->height * jobnr ) / nb_jobs; \
- const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(in->height, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(in->height, jobnr + 1, nb_jobs); \
uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
@@ -1966,8 +1966,8 @@ static int interp_1d_##name##_pf##depth(AVFilterContext *ctx, \
const AVFrame *in = td->in; \
const AVFrame *out = td->out; \
const int direct = out == in; \
- const int slice_start = (in->height * jobnr ) / nb_jobs; \
- const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(in->height, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(in->height, jobnr + 1, nb_jobs); \
uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
@@ -2036,8 +2036,8 @@ static int interp_1d_##nbits##_##name(AVFilterContext *ctx, void *arg, \
const uint8_t g = lut1d->rgba_map[G]; \
const uint8_t b = lut1d->rgba_map[B]; \
const uint8_t a = lut1d->rgba_map[A]; \
- const int slice_start = (in->height * jobnr ) / nb_jobs; \
- const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(in->height, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(in->height, jobnr + 1, nb_jobs); \
uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; \
const uint8_t *srcrow = in ->data[0] + slice_start * in ->linesize[0]; \
const float factor = (1 << nbits) - 1; \
diff --git a/libavfilter/vf_maskedclamp.c b/libavfilter/vf_maskedclamp.c
index 606afd3913..f287c136a1 100644
--- a/libavfilter/vf_maskedclamp.c
+++ b/libavfilter/vf_maskedclamp.c
@@ -94,8 +94,8 @@ static int maskedclamp_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_
const ptrdiff_t dlinesize = td->d->linesize[p];
const int w = s->width[p];
const int h = s->height[p];
- const int slice_start = (h * jobnr) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
const uint8_t *bsrc = td->b->data[p] + slice_start * blinesize;
const uint8_t *darksrc = td->o->data[p] + slice_start * darklinesize;
const uint8_t *brightsrc = td->m->data[p] + slice_start * brightlinesize;
diff --git a/libavfilter/vf_maskedmerge.c b/libavfilter/vf_maskedmerge.c
index 18b960034e..299c05c1ba 100644
--- a/libavfilter/vf_maskedmerge.c
+++ b/libavfilter/vf_maskedmerge.c
@@ -76,8 +76,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
for (p = 0; p < s->nb_planes; p++) {
const int h = s->height[p];
- const int slice_start = (h * jobnr) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
if (!((1 << p) & s->planes)) {
av_image_copy_plane(out->data[p] + slice_start * out->linesize[p],
diff --git a/libavfilter/vf_maskedminmax.c b/libavfilter/vf_maskedminmax.c
index b6762e16bf..5e630711e2 100644
--- a/libavfilter/vf_maskedminmax.c
+++ b/libavfilter/vf_maskedminmax.c
@@ -149,8 +149,8 @@ static int maskedminmax_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb
const ptrdiff_t dst_linesize = td->dst->linesize[p];
const int w = s->planewidth[p];
const int h = s->planeheight[p];
- const int slice_start = (h * jobnr) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
const uint8_t *src = td->src->data[p] + slice_start * src_linesize;
const uint8_t *f1 = td->f1->data[p] + slice_start * f1_linesize;
const uint8_t *f2 = td->f2->data[p] + slice_start * f2_linesize;
diff --git a/libavfilter/vf_maskedthreshold.c b/libavfilter/vf_maskedthreshold.c
index 41c204f6f5..649b9558d9 100644
--- a/libavfilter/vf_maskedthreshold.c
+++ b/libavfilter/vf_maskedthreshold.c
@@ -154,8 +154,8 @@ static int threshold_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
const ptrdiff_t dst_linesize = td->dst->linesize[p];
const int w = s->planewidth[p];
const int h = s->planeheight[p];
- const int slice_start = (h * jobnr) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
const uint8_t *src = td->src->data[p] + slice_start * src_linesize;
const uint8_t *ref = td->ref->data[p] + slice_start * ref_linesize;
uint8_t *dst = td->dst->data[p] + slice_start * dst_linesize;
diff --git a/libavfilter/vf_maskfun.c b/libavfilter/vf_maskfun.c
index 9869ae4e33..f04fb40ae5 100644
--- a/libavfilter/vf_maskfun.c
+++ b/libavfilter/vf_maskfun.c
@@ -168,8 +168,8 @@ static int maskfun##name(AVFilterContext *ctx, void *arg, \
const int linesize = out->linesize[p] / div; \
const int w = s->planewidth[p]; \
const int h = s->planeheight[p]; \
- const int slice_start = (h * jobnr) / nb_jobs; \
- const int slice_end = (h * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs); \
const type *src = (type *)in->data[p] + \
slice_start * src_linesize; \
type *dst = (type *)out->data[p] + \
diff --git a/libavfilter/vf_median.c b/libavfilter/vf_median.c
index 6e00cdf885..3b11adbcad 100644
--- a/libavfilter/vf_median.c
+++ b/libavfilter/vf_median.c
@@ -186,8 +186,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
for (int plane = 0; plane < s->nb_planes; plane++) {
const int h = s->planeheight[plane];
const int w = s->planewidth[plane];
- const int slice_h_start = (h * jobnr) / nb_jobs;
- const int slice_h_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_h_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_h_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
if (!(s->planes & (1 << plane))) {
av_image_copy_plane(out->data[plane] + slice_h_start * out->linesize[plane],
diff --git a/libavfilter/vf_mix.c b/libavfilter/vf_mix.c
index 517bb2450f..3143f6e9c8 100644
--- a/libavfilter/vf_mix.c
+++ b/libavfilter/vf_mix.c
@@ -159,8 +159,8 @@ typedef struct ThreadData {
#define FAST_TMIX_SLICE(type, stype, round) \
for (int p = 0; p < s->nb_planes; p++) { \
- const int slice_start = (s->height[p] * jobnr) / nb_jobs; \
- const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(s->height[p], jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(s->height[p], jobnr + 1, nb_jobs); \
const int width = s->linesizes[p] / sizeof(type); \
stype *sum = (stype *)(s->sum[p] + slice_start * s->linesizes[p] * 2); \
type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
@@ -198,8 +198,8 @@ typedef struct ThreadData {
#define MIX_SLICE(type, fun, clip) \
for (int p = 0; p < s->nb_planes; p++) { \
- const int slice_start = (s->height[p] * jobnr) / nb_jobs; \
- const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(s->height[p], jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(s->height[p], jobnr + 1, nb_jobs); \
const int width = s->linesizes[p] / sizeof(type); \
type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
const ptrdiff_t dst_linesize = out->linesize[p] / sizeof(type); \
diff --git a/libavfilter/vf_monochrome.c b/libavfilter/vf_monochrome.c
index 4718642921..1e6d6539c9 100644
--- a/libavfilter/vf_monochrome.c
+++ b/libavfilter/vf_monochrome.c
@@ -87,8 +87,8 @@ static int monochrome_slice8(AVFilterContext *ctx, void *arg, int jobnr, int nb_
const float imax = 1.f / max;
const int width = frame->width;
const int height = frame->height;
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t ylinesize = frame->linesize[0];
const ptrdiff_t ulinesize = frame->linesize[1];
const ptrdiff_t vlinesize = frame->linesize[2];
@@ -126,8 +126,8 @@ static int monochrome_slice16(AVFilterContext *ctx, void *arg, int jobnr, int nb
const float imax = 1.f / max;
const int width = frame->width;
const int height = frame->height;
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t ylinesize = frame->linesize[0] / 2;
const ptrdiff_t ulinesize = frame->linesize[1] / 2;
const ptrdiff_t vlinesize = frame->linesize[2] / 2;
@@ -164,8 +164,8 @@ static int clear_slice8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
const int subh = s->subh;
const int width = AV_CEIL_RSHIFT(frame->width, subw);
const int height = AV_CEIL_RSHIFT(frame->height, subh);
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t ulinesize = frame->linesize[1];
const ptrdiff_t vlinesize = frame->linesize[2];
@@ -190,8 +190,8 @@ static int clear_slice16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs
const int subh = s->subh;
const int width = AV_CEIL_RSHIFT(frame->width, subw);
const int height = AV_CEIL_RSHIFT(frame->height, subh);
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t ulinesize = frame->linesize[1] / 2;
const ptrdiff_t vlinesize = frame->linesize[2] / 2;
diff --git a/libavfilter/vf_morpho.c b/libavfilter/vf_morpho.c
index 098d00dfd1..342ead266c 100644
--- a/libavfilter/vf_morpho.c
+++ b/libavfilter/vf_morpho.c
@@ -802,8 +802,8 @@ static int morpho_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
for (int p = 0; p < s->nb_planes; p++) {
const int width = s->planewidth[p];
const int height = s->planeheight[p];
- const int y0 = (height * jobnr ) / nb_jobs;
- const int y1 = (height * (jobnr+1)) / nb_jobs;
+ const int y0 = ff_slice_pos(height, jobnr, nb_jobs);
+ const int y1 = ff_slice_pos(height, jobnr + 1, nb_jobs);
const int depth = s->depth;
if (ctx->is_disabled || !(s->planes & (1 << p))) {
@@ -857,8 +857,8 @@ static int morpho_sliceX(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs
for (int p = 0; p < s->nb_planes; p++) {
const int height = s->planeheight[p];
- const int y0 = (height * jobnr ) / nb_jobs;
- const int y1 = (height * (jobnr+1)) / nb_jobs;
+ const int y0 = ff_slice_pos(height, jobnr, nb_jobs);
+ const int y1 = ff_slice_pos(height, jobnr + 1, nb_jobs);
if (ctx->is_disabled || !(s->planes & (1 << p))) {
copy:
diff --git a/libavfilter/vf_multiply.c b/libavfilter/vf_multiply.c
index f7db2195db..da3104f714 100644
--- a/libavfilter/vf_multiply.c
+++ b/libavfilter/vf_multiply.c
@@ -98,8 +98,8 @@ static int multiply_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_job
const ptrdiff_t dst_linesize = td->dst->linesize[p];
const int w = td->src->width;
const int h = td->src->height;
- const int slice_start = (h * jobnr) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
const uint8_t *src = td->src->data[p] + slice_start * src_linesize;
const uint8_t *ref = td->ref->data[p] + slice_start * ref_linesize;
uint8_t *dst = td->dst->data[p] + slice_start * dst_linesize;
diff --git a/libavfilter/vf_negate.c b/libavfilter/vf_negate.c
index c4774eee8a..8d5cfd16c0 100644
--- a/libavfilter/vf_negate.c
+++ b/libavfilter/vf_negate.c
@@ -278,8 +278,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
for (int p = 0; p < s->nb_planes; p++) {
const int h = s->height[p];
- const int slice_start = (h * jobnr) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
if (!((1 << p) & s->planes)) {
if (out != in)
diff --git a/libavfilter/vf_neighbor.c b/libavfilter/vf_neighbor.c
index 7bdc2ab91f..b121a48562 100644
--- a/libavfilter/vf_neighbor.c
+++ b/libavfilter/vf_neighbor.c
@@ -268,8 +268,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
const int dstride = out->linesize[plane];
const int height = s->planeheight[plane];
const int width = s->planewidth[plane];
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const uint8_t *src = (const uint8_t *)in->data[plane] + slice_start * stride;
uint8_t *dst = out->data[plane] + slice_start * dstride;
diff --git a/libavfilter/vf_nlmeans.c b/libavfilter/vf_nlmeans.c
index 2679e5fee4..35ff499d54 100644
--- a/libavfilter/vf_nlmeans.c
+++ b/libavfilter/vf_nlmeans.c
@@ -292,8 +292,8 @@ static int nlmeans_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs
const struct thread_data *td = arg;
const ptrdiff_t src_linesize = td->src_linesize;
const int process_h = td->endy - td->starty;
- const int slice_start = (process_h * jobnr ) / nb_jobs;
- const int slice_end = (process_h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(process_h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(process_h, jobnr + 1, nb_jobs);
const int starty = td->starty + slice_start;
const int endy = td->starty + slice_end;
const int p = td->p;
diff --git a/libavfilter/vf_nnedi.c b/libavfilter/vf_nnedi.c
index d3f52b3f94..148791f804 100644
--- a/libavfilter/vf_nnedi.c
+++ b/libavfilter/vf_nnedi.c
@@ -551,8 +551,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
for (int p = 0; p < s->nb_planes; p++) {
const int height = s->planeheight[p];
const int width = s->planewidth[p];
- const int slice_start = 2 * ((height / 2 * jobnr) / nb_jobs);
- const int slice_end = 2 * ((height / 2 * (jobnr+1)) / nb_jobs);
+ const int slice_start = 2 * (ff_slice_pos(height / 2, jobnr, nb_jobs));
+ const int slice_end = 2 * (ff_slice_pos(height / 2, jobnr + 1, nb_jobs));
const uint8_t *src_data = in->data[p];
uint8_t *dst_data = out->data[p];
uint8_t *dst = out->data[p] + slice_start * out->linesize[p];
diff --git a/libavfilter/vf_noise.c b/libavfilter/vf_noise.c
index ae4a08ca50..2760e4b0e5 100644
--- a/libavfilter/vf_noise.c
+++ b/libavfilter/vf_noise.c
@@ -231,8 +231,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
for (plane = 0; plane < s->nb_planes; plane++) {
const int height = s->height[plane];
- const int start = (height * jobnr ) / nb_jobs;
- const int end = (height * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int end = ff_slice_pos(height, jobnr + 1, nb_jobs);
noise(td->out->data[plane] + start * td->out->linesize[plane],
td->in->data[plane] + start * td->in->linesize[plane],
td->out->linesize[plane], td->in->linesize[plane],
diff --git a/libavfilter/vf_opencolorio.c b/libavfilter/vf_opencolorio.c
index d34922deca..80bcfa133f 100644
--- a/libavfilter/vf_opencolorio.c
+++ b/libavfilter/vf_opencolorio.c
@@ -19,6 +19,7 @@
*/
#include "avfilter.h"
+#include "filters.h"
#include "formats.h"
#include "libavutil/half2float.h"
#include "libavutil/opt.h"
@@ -55,8 +56,8 @@ static int ocio_filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_
AVFrame *in = td->in;
AVFrame *out = td->out;
const int height = out->height;
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const int slice_h = slice_end - slice_start;
return ocio_apply(ctx, s->ocio, in, out, slice_start, slice_h);
diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c
index d627db0889..43f6e736c3 100644
--- a/libavfilter/vf_overlay.c
+++ b/libavfilter/vf_overlay.c
@@ -397,8 +397,8 @@ static av_always_inline void blend_slice_packed_rgb(AVFilterContext *ctx,
i = FFMAX(-y, 0);
imax = FFMIN3(-y + dst_h, FFMIN(src_h, dst_h), y + src_h);
- slice_start = i + (imax * jobnr) / nb_jobs;
- slice_end = i + (imax * (jobnr+1)) / nb_jobs;
+ slice_start = i + ff_slice_pos(imax, jobnr, nb_jobs);
+ slice_end = i + ff_slice_pos(imax, jobnr + 1, nb_jobs);
sp = src->data[0] + (slice_start) * src->linesize[0];
dp = dst->data[0] + (y + slice_start) * dst->linesize[0];
@@ -484,8 +484,8 @@ static av_always_inline void blend_plane_##depth##_##nbits##bits(AVFilterContext
\
const int jmin = FFMAX(-yp, 0), jmax = FFMIN3(-yp + dst_hp, FFMIN(src_hp, dst_hp), yp + src_hp); \
const int kmin = FFMAX(-xp, 0), kmax = FFMIN(-xp + dst_wp, src_wp); \
- const int slice_start = jmin + (jmax * jobnr) / nb_jobs; \
- const int slice_end = jmin + (jmax * (jobnr + 1)) / nb_jobs; \
+ const int slice_start = jmin + ff_slice_pos(jmax, jobnr, nb_jobs); \
+ const int slice_end = jmin + ff_slice_pos(jmax, jobnr + 1, nb_jobs); \
\
const uint8_t *sp = src->data[i] + (slice_start) * src->linesize[i]; \
uint8_t *dp = dst->data[dst_plane] \
@@ -594,8 +594,8 @@ static inline void alpha_composite_##depth##_##nbits##bits(const AVFrame *src, c
\
const int imin = FFMAX(-y, 0), imax = FFMIN3(-y + dst_h, FFMIN(src_h, dst_h), y + src_h); \
const int jmin = FFMAX(-x, 0), jmax = FFMIN(-x + dst_w, src_w); \
- const int slice_start = imin + ( imax * jobnr) / nb_jobs; \
- const int slice_end = imin + ((imax * (jobnr + 1)) / nb_jobs); \
+ const int slice_start = imin + ff_slice_pos(imax, jobnr, nb_jobs); \
+ const int slice_end = imin + (ff_slice_pos(imax, jobnr + 1, nb_jobs)); \
\
const uint8_t *sa = src->data[3] + (slice_start) * src->linesize[3]; \
uint8_t *da = dst->data[3] + (y + slice_start) * dst->linesize[3]; \
diff --git a/libavfilter/vf_photosensitivity.c b/libavfilter/vf_photosensitivity.c
index b8d3667ff8..c14d7b3024 100644
--- a/libavfilter/vf_photosensitivity.c
+++ b/libavfilter/vf_photosensitivity.c
@@ -84,8 +84,8 @@ static int convert_frame_partial(AVFilterContext *ctx, void *arg, int jobnr, int
ThreadData_convert_frame *td = arg;
- const int slice_start = (NUM_CELLS * jobnr) / nb_jobs;
- const int slice_end = (NUM_CELLS * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(NUM_CELLS, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(NUM_CELLS, jobnr + 1, nb_jobs);
int width = td->in->width, height = td->in->height, linesize = td->in->linesize[0], skip = td->skip;
const uint8_t *data = td->in->data[0];
@@ -149,8 +149,8 @@ static int blend_frame_partial(AVFilterContext *ctx, void *arg, int jobnr, int n
ThreadData_blend_frame *td = arg;
const uint16_t s_mul = td->s_mul;
const uint16_t t_mul = 0x100 - s_mul;
- const int slice_start = (td->target->height * jobnr) / nb_jobs;
- const int slice_end = (td->target->height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(td->target->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(td->target->height, jobnr + 1, nb_jobs);
const int linesize = td->target->linesize[0];
for (y = slice_start; y < slice_end; y++) {
diff --git a/libavfilter/vf_pixelize.c b/libavfilter/vf_pixelize.c
index a6f0e38dd7..abde241d18 100644
--- a/libavfilter/vf_pixelize.c
+++ b/libavfilter/vf_pixelize.c
@@ -189,10 +189,10 @@ static int pixelize_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_job
const int wh = s->planeheight[p];
const int h = (s->planeheight[p] + s->block_h[p] - 1) / s->block_h[p];
const int w = (s->planewidth[p] + s->block_w[p] - 1) / s->block_w[p];
- const int wslice_start = (wh * jobnr) / nb_jobs;
- const int wslice_end = (wh * (jobnr+1)) / nb_jobs;
- const int slice_start = (h * jobnr) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int wslice_start = ff_slice_pos(wh, jobnr, nb_jobs);
+ const int wslice_end = ff_slice_pos(wh, jobnr + 1, nb_jobs);
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
const ptrdiff_t out_linesize = out->linesize[p];
const ptrdiff_t in_linesize = in->linesize[p];
const uint8_t *src = in->data[p];
diff --git a/libavfilter/vf_premultiply.c b/libavfilter/vf_premultiply.c
index 93e74d6c93..1cea3cab7f 100644
--- a/libavfilter/vf_premultiply.c
+++ b/libavfilter/vf_premultiply.c
@@ -507,8 +507,8 @@ static int premultiply_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_
int p;
for (p = 0; p < s->nb_planes; p++) {
- const int slice_start = (s->height[p] * jobnr) / nb_jobs;
- const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(s->height[p], jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(s->height[p], jobnr + 1, nb_jobs);
if (!((1 << p) & s->planes) || p == 3) {
av_image_copy_plane(out->data[p] + slice_start * out->linesize[p],
diff --git a/libavfilter/vf_pseudocolor.c b/libavfilter/vf_pseudocolor.c
index 7d5657f26c..793278ce89 100644
--- a/libavfilter/vf_pseudocolor.c
+++ b/libavfilter/vf_pseudocolor.c
@@ -981,9 +981,9 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
AVFrame *out = td->out;
for (int plane = 0; plane < s->nb_planes; plane++) {
- const int slice_start = (s->height[plane] * jobnr) / nb_jobs;
- const int slice_end = (s->height[plane] * (jobnr+1)) / nb_jobs;
- const int islice_start = (s->height[s->index] * jobnr) / nb_jobs;
+ const int slice_start = ff_slice_pos(s->height[plane], jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(s->height[plane], jobnr + 1, nb_jobs);
+ const int islice_start = ff_slice_pos(s->height[s->index], jobnr, nb_jobs);
ptrdiff_t ilinesize = in->linesize[s->index];
ptrdiff_t slinesize = in->linesize[plane];
ptrdiff_t dlinesize = out->linesize[plane];
diff --git a/libavfilter/vf_psnr.c b/libavfilter/vf_psnr.c
index 4a173c73d9..baaf7605c2 100644
--- a/libavfilter/vf_psnr.c
+++ b/libavfilter/vf_psnr.c
@@ -104,8 +104,8 @@ int compute_images_mse(AVFilterContext *ctx, void *arg,
for (int c = 0; c < td->nb_components; c++) {
const int outw = td->planewidth[c];
const int outh = td->planeheight[c];
- const int slice_start = (outh * jobnr) / nb_jobs;
- const int slice_end = (outh * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(outh, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(outh, jobnr + 1, nb_jobs);
const int ref_linesize = td->ref_linesize[c];
const int main_linesize = td->main_linesize[c];
const uint8_t *main_line = td->main_data[c] + main_linesize * slice_start;
diff --git a/libavfilter/vf_remap.c b/libavfilter/vf_remap.c
index c3f02c4cfc..de83bb4671 100644
--- a/libavfilter/vf_remap.c
+++ b/libavfilter/vf_remap.c
@@ -143,8 +143,8 @@ static int remap_planar##bits##_##name##_slice(AVFilterContext *ctx, void *arg,
const AVFrame *xin = td->xin; \
const AVFrame *yin = td->yin; \
const AVFrame *out = td->out; \
- const int slice_start = (out->height * jobnr ) / nb_jobs; \
- const int slice_end = (out->height * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(out->height, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(out->height, jobnr + 1, nb_jobs); \
const int xlinesize = xin->linesize[0] / 2; \
const int ylinesize = yin->linesize[0] / 2; \
int x , y, plane; \
@@ -194,8 +194,8 @@ static int remap_packed##bits##_##name##_slice(AVFilterContext *ctx, void *arg,
const AVFrame *xin = td->xin; \
const AVFrame *yin = td->yin; \
const AVFrame *out = td->out; \
- const int slice_start = (out->height * jobnr ) / nb_jobs; \
- const int slice_end = (out->height * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(out->height, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(out->height, jobnr + 1, nb_jobs); \
const int dlinesize = out->linesize[0] / div; \
const int slinesize = in->linesize[0] / div; \
const int xlinesize = xin->linesize[0] / 2; \
diff --git a/libavfilter/vf_removegrain.c b/libavfilter/vf_removegrain.c
index 0a0c60fb20..faaa6af712 100644
--- a/libavfilter/vf_removegrain.c
+++ b/libavfilter/vf_removegrain.c
@@ -523,8 +523,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
const int om = in->linesize[i] - 1;
const int o0 = in->linesize[i] ;
const int op = in->linesize[i] + 1;
- int start = (height * jobnr ) / nb_jobs;
- int end = (height * (jobnr+1)) / nb_jobs;
+ int start = ff_slice_pos(height, jobnr, nb_jobs);
+ int end = ff_slice_pos(height, jobnr + 1, nb_jobs);
int x, y;
start = FFMAX(1, start);
diff --git a/libavfilter/vf_scroll.c b/libavfilter/vf_scroll.c
index cd728a4968..d64ac2733d 100644
--- a/libavfilter/vf_scroll.c
+++ b/libavfilter/vf_scroll.c
@@ -80,8 +80,8 @@ static int scroll_slice(AVFilterContext *ctx, void *arg, int jobnr,
const uint8_t *src = in->data[p];
const int h = s->planeheight[p];
const int w = s->planewidth[p] * s->bytes;
- const int slice_start = (h * jobnr) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
uint8_t *dst = out->data[p] + slice_start * out->linesize[p];
for (int y = slice_start; y < slice_end; y++) {
diff --git a/libavfilter/vf_selectivecolor.c b/libavfilter/vf_selectivecolor.c
index 99aa32f013..4fa8b32f3c 100644
--- a/libavfilter/vf_selectivecolor.c
+++ b/libavfilter/vf_selectivecolor.c
@@ -316,8 +316,8 @@ static inline int selective_color_##nbits(AVFilterContext *ctx, ThreadData *td,
const SelectiveColorContext *s = ctx->priv; \
const int height = in->height; \
const int width = in->width; \
- const int slice_start = (height * jobnr ) / nb_jobs; \
- const int slice_end = (height * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs); \
const int dst_linesize = out->linesize[0] / ((nbits + 7) / 8); \
const int src_linesize = in->linesize[0] / ((nbits + 7) / 8); \
const uint8_t roffset = s->rgba_map[R]; \
diff --git a/libavfilter/vf_shear.c b/libavfilter/vf_shear.c
index 11edd1063d..1c24a36478 100644
--- a/libavfilter/vf_shear.c
+++ b/libavfilter/vf_shear.c
@@ -130,8 +130,8 @@ static int filter_slice_nn##name(AVFilterContext *ctx, void *arg, int jobnr, \
const int height = s->planeheight[p]; \
const int wx = vsub * shx * height * 0.5f / hsub; \
const int wy = hsub * shy * width * 0.5f / vsub; \
- const int slice_start = (height * jobnr) / nb_jobs; \
- const int slice_end = (height * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs); \
const int src_linesize = in->linesize[p] / sizeof(type); \
const int dst_linesize = out->linesize[p] / sizeof(type); \
const type *src = (const type *)in->data[p]; \
@@ -177,8 +177,8 @@ static int filter_slice_bl##name(AVFilterContext *ctx, void *arg, int jobnr, \
const int height = s->planeheight[p]; \
const float wx = vsub * shx * height * 0.5f / hsub; \
const float wy = hsub * shy * width * 0.5f / vsub; \
- const int slice_start = (height * jobnr) / nb_jobs; \
- const int slice_end = (height * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs); \
const int src_linesize = in->linesize[p] / sizeof(type); \
const int dst_linesize = out->linesize[p] / sizeof(type); \
const type *src = (const type *)in->data[p]; \
diff --git a/libavfilter/vf_shufflepixels.c b/libavfilter/vf_shufflepixels.c
index 3ba950f7b6..ebe0b81155 100644
--- a/libavfilter/vf_shufflepixels.c
+++ b/libavfilter/vf_shufflepixels.c
@@ -204,8 +204,8 @@ static int shuffle_horizontal## name(AVFilterContext *ctx, void *arg, \
AVFrame *out = td->out; \
\
for (int p = 0; p < s->nb_planes; p++) { \
- const int slice_start = (s->planeheight[p] * jobnr) / nb_jobs; \
- const int slice_end = (s->planeheight[p] * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(s->planeheight[p], jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(s->planeheight[p], jobnr + 1, nb_jobs); \
type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
const type *src = (const type *)(in->data[p] + \
slice_start * in->linesize[p]); \
@@ -237,8 +237,8 @@ static int shuffle_vertical## name(AVFilterContext *ctx, void *arg, \
AVFrame *out = td->out; \
\
for (int p = 0; p < s->nb_planes; p++) { \
- const int slice_start = (s->planeheight[p] * jobnr) / nb_jobs; \
- const int slice_end = (s->planeheight[p] * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(s->planeheight[p], jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(s->planeheight[p], jobnr + 1, nb_jobs); \
type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
const int32_t *map = s->map; \
\
@@ -267,8 +267,8 @@ static int shuffle_block## name(AVFilterContext *ctx, void *arg, \
AVFrame *out = td->out; \
\
for (int p = 0; p < s->nb_planes; p++) { \
- const int slice_start = (s->planeheight[p] * jobnr) / nb_jobs; \
- const int slice_end = (s->planeheight[p] * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(s->planeheight[p], jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(s->planeheight[p], jobnr + 1, nb_jobs); \
type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
const type *src = (const type *)in->data[p]; \
const int32_t *map = s->map + slice_start * s->planewidth[p]; \
diff --git a/libavfilter/vf_signalstats.c b/libavfilter/vf_signalstats.c
index 77b94669bd..5859b46478 100644
--- a/libavfilter/vf_signalstats.c
+++ b/libavfilter/vf_signalstats.c
@@ -218,8 +218,8 @@ static int filter8_brng(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
AVFrame *out = td->out;
const int w = in->width;
const int h = in->height;
- const int slice_start = (h * jobnr ) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
int x, y, score = 0;
for (y = slice_start; y < slice_end; y++) {
@@ -253,8 +253,8 @@ static int filter16_brng(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs
const int mult = 1 << (s->depth - 8);
const int w = in->width;
const int h = in->height;
- const int slice_start = (h * jobnr ) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
int x, y, score = 0;
for (y = slice_start; y < slice_end; y++) {
@@ -292,8 +292,8 @@ static int filter8_tout(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
AVFrame *out = td->out;
const int w = in->width;
const int h = in->height;
- const int slice_start = (h * jobnr ) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
const uint8_t *p = in->data[0];
int lw = in->linesize[0];
int x, y, score = 0, filt;
@@ -340,8 +340,8 @@ static int filter16_tout(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs
AVFrame *out = td->out;
const int w = in->width;
const int h = in->height;
- const int slice_start = (h * jobnr ) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
const uint16_t *p = (uint16_t *)in->data[0];
int lw = in->linesize[0] / 2;
int x, y, score = 0, filt;
@@ -383,8 +383,8 @@ static int filter8_vrep(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
AVFrame *out = td->out;
const int w = in->width;
const int h = in->height;
- const int slice_start = (h * jobnr ) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
const uint8_t *p = in->data[0];
const int lw = in->linesize[0];
int x, y, score = 0;
@@ -417,8 +417,8 @@ static int filter16_vrep(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs
AVFrame *out = td->out;
const int w = in->width;
const int h = in->height;
- const int slice_start = (h * jobnr ) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
const uint16_t *p = (uint16_t *)in->data[0];
const int lw = in->linesize[0] / 2;
int x, y, score = 0;
@@ -464,8 +464,8 @@ static int compute_sat_hue_metrics8(AVFilterContext *ctx, void *arg, int jobnr,
AVFrame *dst_sat = td->dst_sat;
AVFrame *dst_hue = td->dst_hue;
- const int slice_start = (s->chromah * jobnr ) / nb_jobs;
- const int slice_end = (s->chromah * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(s->chromah, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(s->chromah, jobnr + 1, nb_jobs);
const int lsz_u = src->linesize[1];
const int lsz_v = src->linesize[2];
@@ -503,8 +503,8 @@ static int compute_sat_hue_metrics16(AVFilterContext *ctx, void *arg, int jobnr,
AVFrame *dst_hue = td->dst_hue;
const int mid = 1 << (s->depth - 1);
- const int slice_start = (s->chromah * jobnr ) / nb_jobs;
- const int slice_end = (s->chromah * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(s->chromah, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(s->chromah, jobnr + 1, nb_jobs);
const int lsz_u = src->linesize[1] / 2;
const int lsz_v = src->linesize[2] / 2;
diff --git a/libavfilter/vf_ssim.c b/libavfilter/vf_ssim.c
index dfb91e8da5..85aa420683 100644
--- a/libavfilter/vf_ssim.c
+++ b/libavfilter/vf_ssim.c
@@ -247,8 +247,8 @@ static int ssim_plane_16bit(AVFilterContext *ctx, void *arg,
const int ref_stride = td->ref_linesize[c];
int width = td->planewidth[c];
int height = td->planeheight[c];
- const int slice_start = ((height >> 2) * jobnr) / nb_jobs;
- const int slice_end = ((height >> 2) * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height >> 2, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height >> 2, jobnr + 1, nb_jobs);
const int ystart = FFMAX(1, slice_start);
int z = ystart - 1;
double ssim = 0.0;
@@ -290,8 +290,8 @@ static int ssim_plane(AVFilterContext *ctx, void *arg,
const int ref_stride = td->ref_linesize[c];
int width = td->planewidth[c];
int height = td->planeheight[c];
- const int slice_start = ((height >> 2) * jobnr) / nb_jobs;
- const int slice_end = ((height >> 2) * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height >> 2, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height >> 2, jobnr + 1, nb_jobs);
const int ystart = FFMAX(1, slice_start);
int z = ystart - 1;
double ssim = 0.0;
diff --git a/libavfilter/vf_stereo3d.c b/libavfilter/vf_stereo3d.c
index e84af47f4d..15d6f31c11 100644
--- a/libavfilter/vf_stereo3d.c
+++ b/libavfilter/vf_stereo3d.c
@@ -623,8 +623,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
AVFrame *iright = td->iright;
AVFrame *out = td->out;
int height = s->out.height;
- int start = (height * jobnr ) / nb_jobs;
- int end = (height * (jobnr+1)) / nb_jobs;
+ int start = ff_slice_pos(height, jobnr, nb_jobs);
+ int end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const int **ana_matrix = s->ana_matrix;
s->dsp.anaglyph(out->data[0] + out->linesize[0] * start,
diff --git a/libavfilter/vf_super2xsai.c b/libavfilter/vf_super2xsai.c
index ef75b4dc73..77dc9de7db 100644
--- a/libavfilter/vf_super2xsai.c
+++ b/libavfilter/vf_super2xsai.c
@@ -76,8 +76,8 @@ static int super2xsai(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
const uint32_t lo_pixel_mask = s->lo_pixel_mask;
const uint32_t q_hi_pixel_mask = s->q_hi_pixel_mask;
const uint32_t q_lo_pixel_mask = s->q_lo_pixel_mask;
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
/* Point to the first 4 lines, first line is duplicated */
src_line[0] = src + src_linesize*FFMAX(slice_start - 1, 0);
diff --git a/libavfilter/vf_threshold.c b/libavfilter/vf_threshold.c
index 633deb9474..5a1d37736b 100644
--- a/libavfilter/vf_threshold.c
+++ b/libavfilter/vf_threshold.c
@@ -86,8 +86,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
for (int p = 0; p < s->nb_planes; p++) {
const int h = s->height[p];
- const int slice_start = (h * jobnr) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
if (!(s->planes & (1 << p))) {
av_image_copy_plane(out->data[p] + slice_start * out->linesize[p],
diff --git a/libavfilter/vf_thumbnail.c b/libavfilter/vf_thumbnail.c
index b594996b9b..c51a5d1194 100644
--- a/libavfilter/vf_thumbnail.c
+++ b/libavfilter/vf_thumbnail.c
@@ -206,8 +206,8 @@ static int do_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
int *hist = s->thread_histogram + HIST_SIZE * jobnr;
const int h = frame->height;
const int w = frame->width;
- const int slice_start = (h * jobnr) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
const uint8_t *p = frame->data[0] + slice_start * frame->linesize[0];
memset(hist, 0, sizeof(*hist) * HIST_SIZE);
@@ -252,8 +252,8 @@ static int do_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
break;
default:
for (int plane = 0; plane < s->planes; plane++) {
- const int slice_start = (s->planeheight[plane] * jobnr) / nb_jobs;
- const int slice_end = (s->planeheight[plane] * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(s->planeheight[plane], jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(s->planeheight[plane], jobnr + 1, nb_jobs);
const uint8_t *p = frame->data[plane] + slice_start * frame->linesize[plane];
const ptrdiff_t linesize = frame->linesize[plane];
const int planewidth = s->planewidth[plane];
diff --git a/libavfilter/vf_tonemap.c b/libavfilter/vf_tonemap.c
index 54811ca40b..c5be4b1510 100644
--- a/libavfilter/vf_tonemap.c
+++ b/libavfilter/vf_tonemap.c
@@ -185,8 +185,8 @@ static int tonemap_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs
AVFrame *in = td->in;
AVFrame *out = td->out;
const AVPixFmtDescriptor *desc = td->desc;
- const int slice_start = (in->height * jobnr) / nb_jobs;
- const int slice_end = (in->height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(in->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(in->height, jobnr + 1, nb_jobs);
double peak = td->peak;
for (int y = slice_start; y < slice_end; y++)
diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c
index c457b01a4e..62c222f3c2 100644
--- a/libavfilter/vf_transpose.c
+++ b/libavfilter/vf_transpose.c
@@ -282,8 +282,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr,
int inh = AV_CEIL_RSHIFT(in->height, vsub);
int outw = AV_CEIL_RSHIFT(out->width, hsub);
int outh = AV_CEIL_RSHIFT(out->height, vsub);
- int start = (outh * jobnr ) / nb_jobs;
- int end = (outh * (jobnr+1)) / nb_jobs;
+ int start = ff_slice_pos(outh, jobnr, nb_jobs);
+ int end = ff_slice_pos(outh, jobnr + 1, nb_jobs);
uint8_t *dst, *src;
int dstlinesize, srclinesize;
int x, y;
diff --git a/libavfilter/vf_unsharp.c b/libavfilter/vf_unsharp.c
index 57eccc76d7..6d2be4328d 100644
--- a/libavfilter/vf_unsharp.c
+++ b/libavfilter/vf_unsharp.c
@@ -110,8 +110,8 @@ static int name##_##nbits(AVFilterContext *ctx, void *arg, int jobnr, int nb_job
const int height = td->height; \
const int sc_offset = jobnr * 2 * steps_y; \
const int sr_offset = jobnr * (MAX_MATRIX_SIZE - 1); \
- const int slice_start = (height * jobnr) / nb_jobs; \
- const int slice_end = (height * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs); \
\
int32_t res; \
int x, y, z; \
diff --git a/libavfilter/vf_v360.c b/libavfilter/vf_v360.c
index 4384fa578b..17628e831c 100644
--- a/libavfilter/vf_v360.c
+++ b/libavfilter/vf_v360.c
@@ -308,8 +308,8 @@ static int remap##ws##_##bits##bit_slice(AVFilterContext *ctx, void *arg, int jo
const int width = s->pr_width[plane]; \
const int height = s->pr_height[plane]; \
\
- const int slice_start = (height * jobnr ) / nb_jobs; \
- const int slice_end = (height * (jobnr + 1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs); \
\
for (int y = slice_start; y < slice_end && !mask; y++) { \
const int16_t *const u = r->u[map] + (y - slice_start) * uv_linesize * ws * ws; \
@@ -4246,8 +4246,8 @@ static int v360_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
const int height = s->pr_height[p];
const int in_width = s->inplanewidth[p];
const int in_height = s->inplaneheight[p];
- const int slice_start = (height * jobnr ) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const int elements = s->elements;
float du, dv;
float vec[3];
diff --git a/libavfilter/vf_varblur.c b/libavfilter/vf_varblur.c
index 6a9aa89ce1..74efa0c6b3 100644
--- a/libavfilter/vf_varblur.c
+++ b/libavfilter/vf_varblur.c
@@ -215,8 +215,8 @@ static int blur_planes(AVFilterContext *ctx, void *arg,
for (int plane = 0; plane < s->nb_planes; plane++) {
const int height = s->planeheight[plane];
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const int width = s->planewidth[plane];
const int linesize = in->linesize[plane];
const int dst_linesize = out->linesize[plane];
diff --git a/libavfilter/vf_vibrance.c b/libavfilter/vf_vibrance.c
index 94c3d569c6..295e582412 100644
--- a/libavfilter/vf_vibrance.c
+++ b/libavfilter/vf_vibrance.c
@@ -75,8 +75,8 @@ static int vibrance_slice8(AVFilterContext *avctx, void *arg, int jobnr, int nb_
const float sgintensity = alternate * FFSIGN(gintensity);
const float sbintensity = alternate * FFSIGN(bintensity);
const float srintensity = alternate * FFSIGN(rintensity);
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t glinesize = frame->linesize[0];
const ptrdiff_t blinesize = frame->linesize[1];
const ptrdiff_t rlinesize = frame->linesize[2];
@@ -152,8 +152,8 @@ static int vibrance_slice16(AVFilterContext *avctx, void *arg, int jobnr, int nb
const float sgintensity = alternate * FFSIGN(gintensity);
const float sbintensity = alternate * FFSIGN(bintensity);
const float srintensity = alternate * FFSIGN(rintensity);
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t gslinesize = in->linesize[0] / 2;
const ptrdiff_t bslinesize = in->linesize[1] / 2;
const ptrdiff_t rslinesize = in->linesize[2] / 2;
@@ -232,8 +232,8 @@ static int vibrance_slice8p(AVFilterContext *avctx, void *arg, int jobnr, int nb
const float sgintensity = alternate * FFSIGN(gintensity);
const float sbintensity = alternate * FFSIGN(bintensity);
const float srintensity = alternate * FFSIGN(rintensity);
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t linesize = frame->linesize[0];
const ptrdiff_t slinesize = in->linesize[0];
const uint8_t *src = in->data[0] + slice_start * slinesize;
@@ -298,8 +298,8 @@ static int vibrance_slice16p(AVFilterContext *avctx, void *arg, int jobnr, int n
const float sgintensity = alternate * FFSIGN(gintensity);
const float sbintensity = alternate * FFSIGN(bintensity);
const float srintensity = alternate * FFSIGN(rintensity);
- const int slice_start = (height * jobnr) / nb_jobs;
- const int slice_end = (height * (jobnr + 1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const ptrdiff_t linesize = frame->linesize[0] / 2;
const ptrdiff_t slinesize = in->linesize[0] / 2;
const uint16_t *src = (const uint16_t *)in->data[0] + slice_start * slinesize;
diff --git a/libavfilter/vf_vif.c b/libavfilter/vf_vif.c
index 6ec8a8d066..64eb39699f 100644
--- a/libavfilter/vf_vif.c
+++ b/libavfilter/vf_vif.c
@@ -215,8 +215,8 @@ static int vif_filter1d(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
int dst_stride = td->dst_stride;
int filt_w = td->filter_width;
float *temp = td->temp[jobnr];
- const int slice_start = (h * jobnr) / nb_jobs;
- const int slice_end = (h * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(h, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(h, jobnr + 1, nb_jobs);
for (int i = slice_start; i < slice_end; i++) {
/** Vertical pass. */
diff --git a/libavfilter/vf_w3fdif.c b/libavfilter/vf_w3fdif.c
index afde426f1a..465453db25 100644
--- a/libavfilter/vf_w3fdif.c
+++ b/libavfilter/vf_w3fdif.c
@@ -378,8 +378,8 @@ static int deinterlace_plane_slice(AVFilterContext *ctx, void *arg,
const int cur_line_stride = cur->linesize[plane];
const int adj_line_stride = adj->linesize[plane];
const int dst_line_stride = out->linesize[plane];
- const int start = (height * jobnr) / nb_jobs;
- const int end = (height * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const int max = s->max;
const int interlaced = !!(cur->flags & AV_FRAME_FLAG_INTERLACED);
const int tff = s->field == (s->parity == -1 ? interlaced ? !!(cur->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) : 1 :
diff --git a/libavfilter/vf_waveform.c b/libavfilter/vf_waveform.c
index 4753999d0e..8c8fdae796 100644
--- a/libavfilter/vf_waveform.c
+++ b/libavfilter/vf_waveform.c
@@ -705,10 +705,10 @@ static av_always_inline void lowpass16(WaveformContext *s,
const int max = limit - intensity;
const int src_h = AV_CEIL_RSHIFT(in->height, shift_h);
const int src_w = AV_CEIL_RSHIFT(in->width, shift_w);
- const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
- const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
- const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
- const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
+ const int sliceh_start = !column ? ff_slice_pos(src_h, jobnr, nb_jobs) : 0;
+ const int sliceh_end = !column ? ff_slice_pos(src_h, jobnr + 1, nb_jobs) : src_h;
+ const int slicew_start = column ? ff_slice_pos(src_w, jobnr, nb_jobs) : 0;
+ const int slicew_end = column ? ff_slice_pos(src_w, jobnr + 1, nb_jobs) : src_w;
const int step = column ? 1 << shift_w : 1 << shift_h;
const uint16_t *src_data = (const uint16_t *)in->data[plane] + sliceh_start * src_linesize;
uint16_t *dst_data = (uint16_t *)out->data[dplane] + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
@@ -842,10 +842,10 @@ static av_always_inline void lowpass(WaveformContext *s,
const int max = 255 - intensity;
const int src_h = AV_CEIL_RSHIFT(in->height, shift_h);
const int src_w = AV_CEIL_RSHIFT(in->width, shift_w);
- const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
- const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
- const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
- const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
+ const int sliceh_start = !column ? ff_slice_pos(src_h, jobnr, nb_jobs) : 0;
+ const int sliceh_end = !column ? ff_slice_pos(src_h, jobnr + 1, nb_jobs) : src_h;
+ const int slicew_start = column ? ff_slice_pos(src_w, jobnr, nb_jobs) : 0;
+ const int slicew_end = column ? ff_slice_pos(src_w, jobnr + 1, nb_jobs) : src_w;
const int step = column ? 1 << shift_w : 1 << shift_h;
const uint8_t *src_data = in->data[plane] + sliceh_start * src_linesize;
uint8_t *dst_data = out->data[dplane] + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
@@ -986,10 +986,10 @@ static av_always_inline void flat16(WaveformContext *s,
const int mid = s->max / 2;
const int src_h = in->height;
const int src_w = in->width;
- const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
- const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
- const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
- const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
+ const int sliceh_start = !column ? ff_slice_pos(src_h, jobnr, nb_jobs) : 0;
+ const int sliceh_end = !column ? ff_slice_pos(src_h, jobnr + 1, nb_jobs) : src_h;
+ const int slicew_start = column ? ff_slice_pos(src_w, jobnr, nb_jobs) : 0;
+ const int slicew_end = column ? ff_slice_pos(src_w, jobnr + 1, nb_jobs) : src_w;
int x, y;
if (column) {
@@ -1123,10 +1123,10 @@ static av_always_inline void flat(WaveformContext *s,
const int max = 255 - intensity;
const int src_h = in->height;
const int src_w = in->width;
- const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
- const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
- const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
- const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
+ const int sliceh_start = !column ? ff_slice_pos(src_h, jobnr, nb_jobs) : 0;
+ const int sliceh_end = !column ? ff_slice_pos(src_h, jobnr + 1, nb_jobs) : src_h;
+ const int slicew_start = column ? ff_slice_pos(src_w, jobnr, nb_jobs) : 0;
+ const int slicew_end = column ? ff_slice_pos(src_w, jobnr + 1, nb_jobs) : src_w;
int x, y;
if (column) {
@@ -1269,10 +1269,10 @@ static int name(AVFilterContext *ctx,
const int mid = s->max / 2; \
const int src_h = in->height; \
const int src_w = in->width; \
- const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0; \
- const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h; \
- const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0; \
- const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w; \
+ const int sliceh_start = !column ? ff_slice_pos(src_h, jobnr, nb_jobs) : 0; \
+ const int sliceh_end = !column ? ff_slice_pos(src_h, jobnr + 1, nb_jobs) : src_h; \
+ const int slicew_start = column ? ff_slice_pos(src_w, jobnr, nb_jobs) : 0; \
+ const int slicew_end = column ? ff_slice_pos(src_w, jobnr + 1, nb_jobs) : src_w; \
int x, y; \
\
if (column) { \
@@ -1386,10 +1386,10 @@ static int name(AVFilterContext *ctx,
int offset_x = td->offset_x; \
const int src_h = in->height; \
const int src_w = in->width; \
- const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0; \
- const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h; \
- const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0; \
- const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w; \
+ const int sliceh_start = !column ? ff_slice_pos(src_h, jobnr, nb_jobs) : 0; \
+ const int sliceh_end = !column ? ff_slice_pos(src_h, jobnr + 1, nb_jobs) : src_h; \
+ const int slicew_start = column ? ff_slice_pos(src_w, jobnr, nb_jobs) : 0; \
+ const int slicew_end = column ? ff_slice_pos(src_w, jobnr + 1, nb_jobs) : src_w; \
const int intensity = s->intensity; \
const int plane = s->desc->comp[component].plane; \
const int c0_linesize = in->linesize[ plane + 0 ]; \
@@ -1550,10 +1550,10 @@ static av_always_inline void chroma16(WaveformContext *s,
const int c1_shift_h = s->shift_h[(component + 2) % s->ncomp];
const int src_h = in->height;
const int src_w = in->width;
- const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
- const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
- const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
- const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
+ const int sliceh_start = !column ? ff_slice_pos(src_h, jobnr, nb_jobs) : 0;
+ const int sliceh_end = !column ? ff_slice_pos(src_h, jobnr + 1, nb_jobs) : src_h;
+ const int slicew_start = column ? ff_slice_pos(src_w, jobnr, nb_jobs) : 0;
+ const int slicew_end = column ? ff_slice_pos(src_w, jobnr + 1, nb_jobs) : src_w;
int x, y;
if (column) {
@@ -1646,10 +1646,10 @@ static av_always_inline void chroma(WaveformContext *s,
const int plane = s->desc->comp[component].plane;
const int src_h = in->height;
const int src_w = in->width;
- const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
- const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
- const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
- const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
+ const int sliceh_start = !column ? ff_slice_pos(src_h, jobnr, nb_jobs) : 0;
+ const int sliceh_end = !column ? ff_slice_pos(src_h, jobnr + 1, nb_jobs) : src_h;
+ const int slicew_start = column ? ff_slice_pos(src_w, jobnr, nb_jobs) : 0;
+ const int slicew_end = column ? ff_slice_pos(src_w, jobnr + 1, nb_jobs) : src_w;
const int c0_linesize = in->linesize[(plane + 1) % s->ncomp];
const int c1_linesize = in->linesize[(plane + 2) % s->ncomp];
const int dst_linesize = out->linesize[plane];
@@ -1751,10 +1751,10 @@ static av_always_inline void color16(WaveformContext *s,
const int limit = s->max - 1;
const int src_h = in->height;
const int src_w = in->width;
- const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
- const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
- const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
- const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
+ const int sliceh_start = !column ? ff_slice_pos(src_h, jobnr, nb_jobs) : 0;
+ const int sliceh_end = !column ? ff_slice_pos(src_h, jobnr + 1, nb_jobs) : src_h;
+ const int slicew_start = column ? ff_slice_pos(src_w, jobnr, nb_jobs) : 0;
+ const int slicew_end = column ? ff_slice_pos(src_w, jobnr + 1, nb_jobs) : src_w;
const int c0_linesize = in->linesize[ plane + 0 ] / 2;
const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2;
const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2;
@@ -1883,10 +1883,10 @@ static av_always_inline void color(WaveformContext *s,
const int plane = s->desc->comp[component].plane;
const int src_h = in->height;
const int src_w = in->width;
- const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
- const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
- const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
- const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
+ const int sliceh_start = !column ? ff_slice_pos(src_h, jobnr, nb_jobs) : 0;
+ const int sliceh_end = !column ? ff_slice_pos(src_h, jobnr + 1, nb_jobs) : src_h;
+ const int slicew_start = column ? ff_slice_pos(src_w, jobnr, nb_jobs) : 0;
+ const int slicew_end = column ? ff_slice_pos(src_w, jobnr + 1, nb_jobs) : src_w;
const int c0_linesize = in->linesize[ plane + 0 ];
const int c1_linesize = in->linesize[(plane + 1) % s->ncomp];
const int c2_linesize = in->linesize[(plane + 2) % s->ncomp];
@@ -2017,10 +2017,10 @@ static av_always_inline void acolor16(WaveformContext *s,
const int max = limit - intensity;
const int src_h = in->height;
const int src_w = in->width;
- const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
- const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
- const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
- const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
+ const int sliceh_start = !column ? ff_slice_pos(src_h, jobnr, nb_jobs) : 0;
+ const int sliceh_end = !column ? ff_slice_pos(src_h, jobnr + 1, nb_jobs) : src_h;
+ const int slicew_start = column ? ff_slice_pos(src_w, jobnr, nb_jobs) : 0;
+ const int slicew_end = column ? ff_slice_pos(src_w, jobnr + 1, nb_jobs) : src_w;
const int c0_shift_h = s->shift_h[ component + 0 ];
const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
@@ -2149,10 +2149,10 @@ static av_always_inline void acolor(WaveformContext *s,
const int plane = s->desc->comp[component].plane;
const int src_h = in->height;
const int src_w = in->width;
- const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
- const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
- const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
- const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
+ const int sliceh_start = !column ? ff_slice_pos(src_h, jobnr, nb_jobs) : 0;
+ const int sliceh_end = !column ? ff_slice_pos(src_h, jobnr + 1, nb_jobs) : src_h;
+ const int slicew_start = column ? ff_slice_pos(src_w, jobnr, nb_jobs) : 0;
+ const int slicew_end = column ? ff_slice_pos(src_w, jobnr + 1, nb_jobs) : src_w;
const int c0_shift_w = s->shift_w[ component + 0 ];
const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
diff --git a/libavfilter/vf_weave.c b/libavfilter/vf_weave.c
index 91c98e0e66..957fbb599a 100644
--- a/libavfilter/vf_weave.c
+++ b/libavfilter/vf_weave.c
@@ -114,8 +114,8 @@ static int weave_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
for (int i = 0; i < s->nb_planes; i++) {
const int height = s->planeheight[i];
- const int start = (height * jobnr) / nb_jobs;
- const int end = (height * (jobnr+1)) / nb_jobs;
+ const int start = ff_slice_pos(height, jobnr, nb_jobs);
+ const int end = ff_slice_pos(height, jobnr + 1, nb_jobs);
const int compensation = 2*end > s->outheight[i];
av_image_copy_plane(out->data[i] + out->linesize[i] * field1 +
diff --git a/libavfilter/vf_xbr.c b/libavfilter/vf_xbr.c
index c9a4bc5be7..b2237749f5 100644
--- a/libavfilter/vf_xbr.c
+++ b/libavfilter/vf_xbr.c
@@ -219,8 +219,8 @@ static av_always_inline void xbr_filter(const ThreadData *td, int jobnr, int nb_
const AVFrame *input = td->in;
AVFrame *output = td->out;
const uint32_t *r2y = td->rgbtoyuv;
- const int slice_start = (input->height * jobnr ) / nb_jobs;
- const int slice_end = (input->height * (jobnr+1)) / nb_jobs;
+ const int slice_start = ff_slice_pos(input->height, jobnr, nb_jobs);
+ const int slice_end = ff_slice_pos(input->height, jobnr + 1, nb_jobs);
const int nl = output->linesize[0] >> 2;
const int nl1 = nl + nl;
const int nl2 = nl1 + nl;
diff --git a/libavfilter/vf_xfade.c b/libavfilter/vf_xfade.c
index 4517e4e6b3..53dcf3e1e5 100644
--- a/libavfilter/vf_xfade.c
+++ b/libavfilter/vf_xfade.c
@@ -2193,8 +2193,8 @@ static int xfade_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
XFadeContext *s = ctx->priv;
AVFilterLink *outlink = ctx->outputs[0];
ThreadData *td = arg;
- int slice_start = (outlink->h * jobnr ) / nb_jobs;
- int slice_end = (outlink->h * (jobnr+1)) / nb_jobs;
+ int slice_start = ff_slice_pos(outlink->h, jobnr, nb_jobs);
+ int slice_end = ff_slice_pos(outlink->h, jobnr + 1, nb_jobs);
s->transitionf(ctx, td->xf[0], td->xf[1], td->out, td->progress, slice_start, slice_end, jobnr);
diff --git a/libavfilter/vf_xmedian.c b/libavfilter/vf_xmedian.c
index f411d063f1..7f64a96c94 100644
--- a/libavfilter/vf_xmedian.c
+++ b/libavfilter/vf_xmedian.c
@@ -145,8 +145,8 @@ static int median_frames ## name(AVFilterContext *ctx, void *arg, int jobnr, int
type values[256]; \
\
for (int p = 0; p < s->nb_planes; p++) { \
- const int slice_start = (s->height[p] * jobnr) / nb_jobs; \
- const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; \
+ const int slice_start = ff_slice_pos(s->height[p], jobnr, nb_jobs); \
+ const int slice_end = ff_slice_pos(s->height[p], jobnr + 1, nb_jobs); \
const int width = s->width[p]; \
type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
ptrdiff_t dst_linesize = out->linesize[p] / sizeof(type); \
diff --git a/libavfilter/vf_yadif.c b/libavfilter/vf_yadif.c
index 9e4f8d5b43..41ba056ad4 100644
--- a/libavfilter/vf_yadif.c
+++ b/libavfilter/vf_yadif.c
@@ -193,8 +193,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
int refs = s->cur->linesize[td->plane];
int df = (s->csp->comp[td->plane].depth + 7) / 8;
int pix_3 = 3 * df;
- int slice_start = (td->h * jobnr ) / nb_jobs;
- int slice_end = (td->h * (jobnr+1)) / nb_jobs;
+ int slice_start = ff_slice_pos(td->h, jobnr, nb_jobs);
+ int slice_end = ff_slice_pos(td->h, jobnr + 1, nb_jobs);
int y;
int edge = 3 + MAX_ALIGN / df - 1;
diff --git a/libavfilter/vf_yaepblur.c b/libavfilter/vf_yaepblur.c
index 50fe78df5a..59f3501f35 100644
--- a/libavfilter/vf_yaepblur.c
+++ b/libavfilter/vf_yaepblur.c
@@ -104,8 +104,8 @@ static int pre_calculate_row_##name(AVFilterContext *ctx, void *arg, \
const int linesize = td->src_linesize / sizeof(type); \
const int sat_linesize = s->sat_linesize; \
\
- const int starty = height * jobnr / nb_jobs; \
- const int endy = height * (jobnr+1) / nb_jobs; \
+ const int starty = ff_slice_pos(height, jobnr, nb_jobs); \
+ const int endy = ff_slice_pos(height, jobnr + 1, nb_jobs); \
\
uint64_t *sat = s->sat + (starty + 1) * sat_linesize; \
uint64_t *square_sat = s->square_sat + (starty + 1) * sat_linesize; \
@@ -139,8 +139,8 @@ static int pre_calculate_col(AVFilterContext *ctx, void *arg,
const int height = td->height;
const int sat_linesize = s->sat_linesize;
- const int startx = width * jobnr / nb_jobs;
- const int endx = width * (jobnr + 1) / nb_jobs;
+ const int startx = ff_slice_pos(width, jobnr, nb_jobs);
+ const int endx = ff_slice_pos(width, jobnr + 1, nb_jobs);
uint64_t *sat, *square_sat;
int x, y;
@@ -178,8 +178,8 @@ static int filter_slice_##name(AVFilterContext *ctx, void *arg, int jobnr, int n
const type *src = (const type *)td->src; \
type *dst = (type *)td->dst; \
\
- const int starty = height * jobnr / nb_jobs; \
- const int endy = height * (jobnr + 1) / nb_jobs; \
+ const int starty = ff_slice_pos(height, jobnr, nb_jobs); \
+ const int endy = ff_slice_pos(height, jobnr + 1, nb_jobs); \
\
int x, y; \
int lower_x, higher_x; \
diff --git a/libavfilter/x86/vf_lut3d_init.c b/libavfilter/x86/vf_lut3d_init.c
index db1a152f51..d149f66394 100644
--- a/libavfilter/x86/vf_lut3d_init.c
+++ b/libavfilter/x86/vf_lut3d_init.c
@@ -21,6 +21,7 @@
#include "libavutil/attributes.h"
#include "libavutil/cpu.h"
#include "libavutil/x86/cpu.h"
+#include "libavfilter/filters.h"
#include "libavfilter/lut3d.h"
#define DEFINE_INTERP_FUNC(name, format, opt) \
@@ -33,8 +34,8 @@ static int interp_##name##_##format##_##opt(AVFilterContext *ctx, void *arg, int
AVFrame *in = td->in; \
AVFrame *out = td->out; \
int has_alpha = in->linesize[3] && out != in; \
- int slice_start = (in->height * jobnr ) / nb_jobs; \
- int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
+ int slice_start = ff_slice_pos(in->height, jobnr, nb_jobs); \
+ int slice_end = ff_slice_pos(in->height, jobnr + 1, nb_jobs); \
ff_interp_##name##_##format##_##opt(lut3d, prelut, in, out, slice_start, slice_end, has_alpha); \
return 0; \
}
--
2.52.0
2
1
[PR] avformat/rtsp: add MIKEY PSK-INIT key management for SRTP over RTSPS (PR #23408)
by Thomas Devoogdt 08 Jun '26
by Thomas Devoogdt 08 Jun '26
08 Jun '26
PR #23408 opened by Thomas Devoogdt (ThomasDevoogdt)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23408
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23408.patch
Add a minimal MIKEY ([RFC 3830](https://www.rfc-editor.org/info/rfc3830/)) PSK-INIT decoder (`ff_mikey_parse`) that
extracts SRTP master key, salt, SSRC and ROC from SDP `a=key-mgmt:mikey`
attributes ([RFC 4567](https://www.rfc-editor.org/info/rfc4567/))
Only the subset required for RTSPS is implemented: PSK-INIT messages
(data_type 0) with NULL encryption and NULL MAC inside the KEMAC
payload, carrying a TEK or TEK+SALT key data sub-payload ([RFC 3830 Section 6.13](https://www.rfc-editor.org/info/rfc3830/#section-6.13))
Any unsupported variant returns AVERROR_PATCHWELCOME so
unhandled configurations are never silently ignored.
The SRTP CS ID map entry ([RFC 3830 Section 6.1.1](https://www.rfc-editor.org/info/rfc3830/#section-6.1.1)) carries a per-stream
SSRC and Roll-Over Counter alongside the key material. Both are now
extracted and applied after `ff_srtp_set_crypto()`:
- `SRTPContext.roc` is initialised from the MIKEY ROC so that the HMAC
index computation starts at the correct packet count rather than 0.
Without this every SRTP HMAC verification fails when the server has
already sent packets before the client connects.
- `RTPDemuxContext.ssrc` is set from the MIKEY SSRC when non-zero and
not already supplied by an SDP `a=ssrc:` attribute ([RFC 5576](https://www.rfc-editor.org/info/rfc5576/))
A MIKEY SSRC of 0 means the sender did not know the SSRC at
key-exchange time ([RFC 3830 Section 6.1.1](https://www.rfc-editor.org/info/rfc3830/#section-6.1.1)) and is ignored.
The decoded key material is fed into `ff_srtp_set_crypto()` via the
existing crypto_suite/crypto_params fields on RTSPStream, following the
same path as [RFC 4568](https://www.rfc-editor.org/info/rfc4568/) `a=crypto:`.
Also fix the RTSPS handler unconditionally forcing lower_transport_mask
to TCP. RTSPS secures only the RTSP signalling channel; the RTP/SRTP
media transport is negotiated independently. Forcing TCP interleaved
prevents UDP-based SRTP streams from being established. Leave
lower_transport_mask untouched so the normal negotiation order applies
and an explicit -rtsp_transport flag is honoured.
Fixes: #10871
Signed-off-by: Thomas Devoogdt <thomas(a)devoogdt.com>
From af3ac827d4527ca03f1b4644e31a78c21cf95e90 Mon Sep 17 00:00:00 2001
From: Thomas Devoogdt <thomas(a)devoogdt.com>
Date: Fri, 5 Jun 2026 23:28:22 +0200
Subject: [PATCH] avformat/rtsp: add MIKEY PSK-INIT key management for SRTP
over RTSPS
Add a minimal MIKEY (RFC 3830) PSK-INIT decoder (ff_mikey_parse) that
extracts SRTP master key, salt, SSRC and ROC from SDP a=key-mgmt:mikey
attributes (RFC 4567).
Only the subset required for RTSPS is implemented: PSK-INIT messages
(data_type 0) with NULL encryption and NULL MAC inside the KEMAC
payload, carrying a TEK or TEK+SALT key data sub-payload (RFC 3830
Section 6.13). Any unsupported variant returns AVERROR_PATCHWELCOME so
unhandled configurations are never silently ignored.
The SRTP CS ID map entry (RFC 3830 Section 6.1.1) carries a per-stream
SSRC and Roll-Over Counter alongside the key material. Both are now
extracted and applied after ff_srtp_set_crypto():
- SRTPContext.roc is initialised from the MIKEY ROC so that the HMAC
index computation starts at the correct packet count rather than 0.
Without this every SRTP HMAC verification fails when the server has
already sent packets before the client connects.
- RTPDemuxContext.ssrc is set from the MIKEY SSRC when non-zero and
not already supplied by an SDP a=ssrc: attribute (RFC 5576).
A MIKEY SSRC of 0 means the sender did not know the SSRC at
key-exchange time (RFC 3830 Section 6.1.1) and is ignored.
The decoded key material is fed into ff_srtp_set_crypto() via the
existing crypto_suite/crypto_params fields on RTSPStream, following the
same path as RFC 4568 a=crypto:.
Also fix the RTSPS handler unconditionally forcing lower_transport_mask
to TCP. RTSPS secures only the RTSP signalling channel; the RTP/SRTP
media transport is negotiated independently. Forcing TCP interleaved
prevents UDP-based SRTP streams from being established. Leave
lower_transport_mask untouched so the normal negotiation order applies
and an explicit -rtsp_transport flag is honoured.
Fixes: #10871
Signed-off-by: Thomas Devoogdt <thomas(a)devoogdt.com>
---
libavformat/Makefile | 2 +-
libavformat/mikey.c | 416 +++++++++++++++++++++++++++++++++++++++++++
libavformat/mikey.h | 49 +++++
libavformat/rtsp.c | 34 +++-
libavformat/rtsp.h | 2 +
5 files changed, 498 insertions(+), 5 deletions(-)
create mode 100644 libavformat/mikey.c
create mode 100644 libavformat/mikey.h
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 0db0c7c2a9..12da915688 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -546,7 +546,7 @@ OBJS-$(CONFIG_RTP_MUXER) += rtp.o \
rtpenc_vp8.o \
rtpenc_vp9.o \
rtpenc_xiph.o
-OBJS-$(CONFIG_RTSP_DEMUXER) += rtsp.o rtspdec.o httpauth.o
+OBJS-$(CONFIG_RTSP_DEMUXER) += rtsp.o rtspdec.o httpauth.o mikey.o
OBJS-$(CONFIG_RTSP_MUXER) += rtsp.o rtspenc.o httpauth.o
OBJS-$(CONFIG_S337M_DEMUXER) += s337m.o spdif.o
OBJS-$(CONFIG_SAMI_DEMUXER) += samidec.o subtitles.o
diff --git a/libavformat/mikey.c b/libavformat/mikey.c
new file mode 100644
index 0000000000..32f65523ea
--- /dev/null
+++ b/libavformat/mikey.c
@@ -0,0 +1,416 @@
+/*
+ * MIKEY (RFC 3830) PSK-INIT key management for SRTP
+ *
+ * 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
+ */
+
+/**
+ * Minimal MIKEY PSK-INIT decoder (RFC 3830).
+ *
+ * Only the subset needed to extract SRTP master key and salt from a
+ * PSK-INIT message carried over RTSPS is implemented:
+ * - data_type 0 (PSK-INIT)
+ * - payload chain: HDR -> T -> RAND -> KEMAC
+ * - KEMAC encryption: NULL (ENC_NULL = 0)
+ * - KEMAC MAC: NULL (MAC_NULL = 0)
+ * - KEY_DATA type: TEK (2) or TEK+salt (3), KV = NULL (0)
+ *
+ * Any field value outside this subset is logged at AV_LOG_ERROR and
+ * causes the parser to return AVERROR_PATCHWELCOME so that unsupported
+ * configurations are never silently ignored.
+ *
+ * Wire format is byte-aligned (each logical field occupies one or more
+ * full octets). See the field layout notes beside each parse step.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "libavutil/base64.h"
+#include "libavutil/error.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/log.h"
+
+#include "mikey.h"
+
+/* RFC 3830 6.1 Table 6.1.b - next-payload type identifiers */
+#define MIKEY_PT_LAST 0
+#define MIKEY_PT_KEMAC 1
+#define MIKEY_PT_T 5
+#define MIKEY_PT_RAND 11
+
+/* RFC 3830 6.1 Table 6.1.a - data_type values */
+#define MIKEY_TYPE_PSK_INIT 0
+
+/* RFC 3830 6.1 Table 6.1.c - PRF function */
+#define MIKEY_PRF_MIKEY_1 0
+
+/* RFC 3830 6.1 Table 6.1.d - CS ID map type */
+#define MIKEY_MAP_TYPE_SRTP 0
+
+/* RFC 3830 6.2 Table 6.2.a - KEMAC encryption algorithm */
+#define MIKEY_ENC_NULL 0
+
+/* RFC 3830 6.2 Table 6.2.b - KEMAC MAC algorithm */
+#define MIKEY_MAC_NULL 0
+
+/* RFC 3830 6.6 Table 6.6 - timestamp type */
+#define MIKEY_TS_NTP_UTC 0
+
+/* RFC 3830 6.13 Table 6.13.a - KEY_DATA Type (upper nibble of byte 1).
+ * TGK (0) and TGK+SALT (1) require TEK derivation (Section 4.1.3),
+ * which is not implemented. Only TEK (2) and TEK+SALT (3) are accepted. */
+#define MIKEY_KD_TEK 2
+#define MIKEY_KD_TEK_WITH_SALT 3
+
+/* Fixed sizes */
+#define MIKEY_HDR_SIZE 10 /* common header without CS ID map */
+#define MIKEY_CS_SRTP_SIZE 9 /* per-CS SRTP map: policy(1)+SSRC(4)+ROC(4) */
+#define MIKEY_RAND_MIN_LEN 16 /* RFC 3830 6.11: RAND SHOULD be >= 16 bytes */
+#define MIKEY_T_NTP_SIZE 8 /* RFC 3830 6.6: NTP-UTC timestamp */
+
+/* Maximum supported key/salt sizes (AES-128-CM) */
+#define MIKEY_MAX_KEY_LEN 16
+#define MIKEY_MAX_SALT_LEN 14
+
+int ff_mikey_parse(const char *mikey_b64,
+ char *suite_out, int suite_size,
+ char *params_out, int params_size,
+ uint32_t *roc_out, uint32_t *ssrc_out,
+ void *logctx)
+{
+ uint8_t raw[512];
+ uint8_t key[MIKEY_MAX_KEY_LEN];
+ uint8_t salt[MIKEY_MAX_SALT_LEN];
+ uint8_t combined[MIKEY_MAX_KEY_LEN + MIKEY_MAX_SALT_LEN];
+ const uint8_t *d;
+ int raw_len, remaining, key_len, salt_len, n_cs, saw_t, saw_rand;
+ uint8_t next_payload;
+
+ raw_len = av_base64_decode(raw, mikey_b64, sizeof(raw));
+ if (raw_len < 0) {
+ av_log(logctx, AV_LOG_ERROR, "MIKEY: base64 decode failed\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (raw_len < MIKEY_HDR_SIZE) {
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: message too short (%d bytes)\n", raw_len);
+ return AVERROR_INVALIDDATA;
+ }
+
+ d = raw;
+ remaining = raw_len;
+ key_len = 0;
+ salt_len = 0;
+ saw_t = 0;
+ saw_rand = 0;
+
+ /* RFC 3830 6.1: common header
+ * [0] version (must be 1)
+ * [1] data_type (0 = PSK-INIT)
+ * [2] next_payload (type of first payload after header)
+ * [3] V(1b) | PRF_func(7b)
+ * [4-7] CSB_ID (32-bit big-endian, not needed for key extraction)
+ * [8] #CS (number of crypto sessions)
+ * [9] CS_ID_map_type
+ */
+ if (d[0] != 1) {
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: unsupported version %u\n", d[0]);
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (d[1] != MIKEY_TYPE_PSK_INIT) {
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: unsupported data_type %u; only PSK-INIT (%u) supported\n",
+ d[1], MIKEY_TYPE_PSK_INIT);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ next_payload = d[2];
+
+ /* RFC 3830 6.1: V flag means the initiator expects a verification-response
+ * message. It has no bearing on key extraction; ignore it. */
+
+ if ((d[3] & 0x7F) != MIKEY_PRF_MIKEY_1) {
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: unsupported PRF function %u\n", d[3] & 0x7F);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ n_cs = d[8];
+
+ if (d[9] != MIKEY_MAP_TYPE_SRTP) {
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: unsupported CS ID map type %u\n", d[9]);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ if (n_cs != 1) {
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: only single-CS messages supported (got %d)\n", n_cs);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ if (remaining < MIKEY_HDR_SIZE + n_cs * MIKEY_CS_SRTP_SIZE) {
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: message truncated in CS ID map\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ /*
+ * RFC 3830 6.1.1: SRTP CS ID map entry (9 bytes per CS):
+ * [0] policy_no
+ * [1-4] SSRC (32-bit big-endian)
+ * [5-8] ROC (32-bit big-endian)
+ */
+ *ssrc_out = AV_RB32(d + MIKEY_HDR_SIZE + 1);
+ *roc_out = AV_RB32(d + MIKEY_HDR_SIZE + 5);
+
+ d += MIKEY_HDR_SIZE + n_cs * MIKEY_CS_SRTP_SIZE;
+ remaining -= MIKEY_HDR_SIZE + n_cs * MIKEY_CS_SRTP_SIZE;
+
+ /* RFC 3830 5.3: walk the payload chain */
+ while (next_payload != MIKEY_PT_LAST && remaining > 0) {
+ uint8_t pt = next_payload;
+
+ switch (pt) {
+
+ case MIKEY_PT_T: {
+ /*
+ * RFC 3830 6.6: timestamp payload
+ * [0] next_payload
+ * [1] TS_type (0 = NTP-UTC)
+ * [2-9] 8-byte NTP-UTC timestamp
+ */
+ if (remaining < 2)
+ goto err_truncated;
+ next_payload = d[0];
+ if (d[1] != MIKEY_TS_NTP_UTC) {
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: unsupported timestamp type %u\n", d[1]);
+ return AVERROR_PATCHWELCOME;
+ }
+ if (remaining < 2 + MIKEY_T_NTP_SIZE)
+ goto err_truncated;
+ saw_t = 1;
+ d += 2 + MIKEY_T_NTP_SIZE;
+ remaining -= 2 + MIKEY_T_NTP_SIZE;
+ break;
+ }
+
+ case MIKEY_PT_RAND: {
+ /*
+ * RFC 3830 6.11: RAND payload
+ * [0] next_payload
+ * [1] rand_len
+ * [2 .. 2+rand_len-1] random bytes
+ */
+ uint8_t rand_len;
+ if (remaining < 2)
+ goto err_truncated;
+ next_payload = d[0];
+ rand_len = d[1];
+ if (rand_len < MIKEY_RAND_MIN_LEN)
+ av_log(logctx, AV_LOG_WARNING,
+ "MIKEY: RAND too short (%u < %u)\n",
+ rand_len, MIKEY_RAND_MIN_LEN);
+ if (remaining < 2 + (int)rand_len)
+ goto err_truncated;
+ saw_rand = 1;
+ d += 2 + rand_len;
+ remaining -= 2 + rand_len;
+ break;
+ }
+
+ case MIKEY_PT_KEMAC: {
+ /*
+ * RFC 3830 6.2: KEMAC payload
+ * [0] next_payload (must be PT_LAST for PSK-INIT)
+ * [1] enc_alg (must be ENC_NULL)
+ * [2-3] enc_len (length of encrypted data, BE16)
+ * [4 .. 4+enc_len-1] encrypted key-data region
+ * [4+enc_len] mac_alg (must be MAC_NULL)
+ *
+ * RFC 3830 6.13: KEY_DATA sub-payload inside the encrypted region
+ * [0] Next payload (0 = last; only one sub-payload supported)
+ * [1] Type(4b) | KV(4b)
+ * [2-3] Key data len (BE16)
+ * [4 .. 4+key_len-1] Key data
+ * if type == MIKEY_KD_TEK_WITH_SALT:
+ * [4+key_len .. 4+key_len+1] salt_len (BE16)
+ * [4+key_len+2 .. ...] salt bytes
+ */
+ const uint8_t *enc_data;
+ uint8_t enc_alg, mac_alg, sub_next, type_kv, kd_type, kv_type;
+ uint16_t enc_len, kd_key_len;
+ int has_salt, pos;
+
+ if (remaining < 5)
+ goto err_truncated;
+
+ /* RFC 3830 3.1: PSK-INIT ordering requires T and RAND before KEMAC */
+ if (!saw_t || !saw_rand) {
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: T and RAND payloads must precede KEMAC\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ enc_alg = d[1];
+ enc_len = AV_RB16(d + 2);
+
+ /* RFC 3830 4.2.3: assert NULL encryption */
+ if (enc_alg != MIKEY_ENC_NULL) {
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: KEMAC encryption alg %u not supported; "
+ "only NULL (%u) is accepted over RTSPS\n",
+ enc_alg, MIKEY_ENC_NULL);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ if (remaining < 5 + (int)enc_len)
+ goto err_truncated;
+
+ mac_alg = d[4 + enc_len];
+
+ /* RFC 3830 4.2.4: assert NULL MAC */
+ if (mac_alg != MIKEY_MAC_NULL) {
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: KEMAC MAC alg %u not supported; "
+ "only NULL (%u) is accepted over RTSPS\n",
+ mac_alg, MIKEY_MAC_NULL);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ if (d[0] != MIKEY_PT_LAST) {
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: additional payloads after KEMAC not supported\n");
+ return AVERROR_PATCHWELCOME;
+ }
+
+ /* Parse KEY_DATA sub-payload */
+ enc_data = d + 4;
+ if (enc_len < 4)
+ goto err_truncated;
+
+ sub_next = enc_data[0];
+ if (sub_next != MIKEY_PT_LAST) {
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: multiple KEY_DATA sub-payloads not supported\n");
+ return AVERROR_PATCHWELCOME;
+ }
+
+ type_kv = enc_data[1];
+ kd_type = (type_kv >> 4) & 0x0F;
+ kv_type = type_kv & 0x0F;
+
+ if (kv_type != 0) {
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: KEY_DATA KV type %u not supported; "
+ "only NULL (0)\n", kv_type);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ if (kd_type != MIKEY_KD_TEK && kd_type != MIKEY_KD_TEK_WITH_SALT) {
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: unsupported KEY_DATA type %u\n", kd_type);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ has_salt = (kd_type == MIKEY_KD_TEK_WITH_SALT);
+ kd_key_len = AV_RB16(enc_data + 2);
+
+ if (!kd_key_len || (int)enc_len < 4 + (int)kd_key_len)
+ goto err_truncated;
+
+ if (kd_key_len > MIKEY_MAX_KEY_LEN) {
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: key too large (%u > %d)\n",
+ kd_key_len, MIKEY_MAX_KEY_LEN);
+ return AVERROR_INVALIDDATA;
+ }
+
+ key_len = kd_key_len;
+ memcpy(key, enc_data + 4, key_len);
+ pos = 4 + key_len;
+
+ if (has_salt) {
+ uint16_t kd_salt_len;
+ if ((int)enc_len < pos + 2)
+ goto err_truncated;
+ kd_salt_len = AV_RB16(enc_data + pos);
+ pos += 2;
+ if (!kd_salt_len || (int)enc_len < pos + (int)kd_salt_len)
+ goto err_truncated;
+ if (kd_salt_len > MIKEY_MAX_SALT_LEN) {
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: salt too large (%u > %d)\n",
+ kd_salt_len, MIKEY_MAX_SALT_LEN);
+ return AVERROR_INVALIDDATA;
+ }
+ salt_len = kd_salt_len;
+ memcpy(salt, enc_data + pos, salt_len);
+ } else {
+ av_log(logctx, AV_LOG_WARNING,
+ "MIKEY: no salt in KEY_DATA, using zero salt\n");
+ salt_len = MIKEY_MAX_SALT_LEN;
+ memset(salt, 0, salt_len);
+ }
+
+ goto done;
+ }
+
+ default:
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: unknown payload type %u\n", pt);
+ return AVERROR_INVALIDDATA;
+ }
+ }
+
+ av_log(logctx, AV_LOG_ERROR, "MIKEY: no KEMAC payload found\n");
+ return AVERROR_INVALIDDATA;
+
+err_truncated:
+ av_log(logctx, AV_LOG_ERROR, "MIKEY: message truncated\n");
+ return AVERROR_INVALIDDATA;
+
+done:
+ /* Derive SRTP suite name from key length */
+ if (key_len == 16) {
+ snprintf(suite_out, suite_size, "AES_CM_128_HMAC_SHA1_80");
+ } else {
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: unsupported key length %d\n", key_len);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ /*
+ * ff_srtp_set_crypto() expects params as base64(master_key || master_salt),
+ * i.e. 16 + 14 = 30 raw bytes -> 40 base64 characters.
+ */
+ memcpy(combined, key, key_len);
+ memcpy(combined + key_len, salt, salt_len);
+
+ if (!av_base64_encode(params_out, params_size, combined, key_len + salt_len)) {
+ av_log(logctx, AV_LOG_ERROR,
+ "MIKEY: params output buffer too small\n");
+ return AVERROR(EINVAL);
+ }
+
+ return 0;
+}
diff --git a/libavformat/mikey.h b/libavformat/mikey.h
new file mode 100644
index 0000000000..6b2df28c4e
--- /dev/null
+++ b/libavformat/mikey.h
@@ -0,0 +1,49 @@
+/*
+ * MIKEY (RFC 3830) PSK-INIT key management for SRTP
+ *
+ * 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 AVFORMAT_MIKEY_H
+#define AVFORMAT_MIKEY_H
+
+#include <stdint.h>
+
+/**
+ * Parse a base64-encoded MIKEY PSK-INIT message from an SDP a=key-mgmt:mikey
+ * attribute and extract SRTP key material for ff_srtp_set_crypto().
+ *
+ * Supported: PSK-INIT (data_type 0), NULL encryption, NULL MAC (RFC 3830).
+ * Any other variant returns AVERROR_PATCHWELCOME.
+ *
+ * @param mikey_b64 NUL-terminated base64 MIKEY PDU.
+ * @param suite_out Output buffer for the SRTP suite name (e.g. "AES_CM_128_HMAC_SHA1_80").
+ * @param suite_size Size of suite_out in bytes.
+ * @param params_out Output buffer for the base64-encoded key || salt string.
+ * @param params_size Size of params_out in bytes.
+ * @param roc_out Initial Roll-Over Counter from the MIKEY CS ID map.
+ * @param ssrc_out SSRC from the MIKEY CS ID map.
+ * @param logctx Logging context (may be NULL).
+ * @return 0 on success, negative AVERROR on failure.
+ */
+int ff_mikey_parse(const char *mikey_b64,
+ char *suite_out, int suite_size,
+ char *params_out, int params_size,
+ uint32_t *roc_out, uint32_t *ssrc_out,
+ void *logctx);
+
+#endif /* AVFORMAT_MIKEY_H */
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index 45b62c4188..2c2841958c 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -56,6 +56,7 @@
#include "tls.h"
#include "rtpenc.h"
#include "mpegts.h"
+#include "mikey.h"
#include "version.h"
/* Default timeout values for read packet in seconds */
@@ -691,6 +692,27 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
p += strspn(p, SPACE_CHARS);
if (av_strstart(p, "inline:", &p))
get_word(rtsp_st->crypto_params, sizeof(rtsp_st->crypto_params), &p);
+ } else if (av_strstart(p, "key-mgmt:", &p) && s->nb_streams > 0) {
+ // RFC 4567
+ char keymgmt_b64[512];
+ rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
+ p += strspn(p, SPACE_CHARS);
+ if (av_strstart(p, "mikey", &p)) {
+ p += strspn(p, SPACE_CHARS);
+ get_word(keymgmt_b64, sizeof(keymgmt_b64), &p);
+ if (ff_mikey_parse(keymgmt_b64,
+ rtsp_st->crypto_suite,
+ sizeof(rtsp_st->crypto_suite),
+ rtsp_st->crypto_params,
+ sizeof(rtsp_st->crypto_params),
+ &rtsp_st->crypto_roc,
+ &rtsp_st->crypto_ssrc, s) < 0)
+ av_log(s, AV_LOG_WARNING,
+ "Failed to parse MIKEY key-mgmt attribute\n");
+ } else {
+ av_log(s, AV_LOG_WARNING,
+ "Unsupported key-mgmt protocol in SDP: %.20s\n", p);
+ }
} else if (av_strstart(p, "source-filter:", &p)) {
int exclude = 0;
get_word(buf1, sizeof(buf1), &p);
@@ -916,10 +938,15 @@ int ff_rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
rtsp_st->dynamic_protocol_context,
rtsp_st->dynamic_handler);
}
- if (rtsp_st->crypto_suite[0])
+ if (rtsp_st->crypto_suite[0]) {
ff_rtp_parse_set_crypto(rtsp_st->transport_priv,
rtsp_st->crypto_suite,
rtsp_st->crypto_params);
+ if (rtsp_st->crypto_roc)
+ rtpctx->srtp.roc = rtsp_st->crypto_roc;
+ if (rtsp_st->crypto_ssrc && !rtpctx->ssrc)
+ rtpctx->ssrc = rtsp_st->crypto_ssrc;
+ }
}
return 0;
@@ -1914,9 +1941,8 @@ redirect:
host, sizeof(host), &port, path, sizeof(path), s->url);
if (!strcmp(proto, "rtsps")) {
- lower_rtsp_proto = "tls";
- default_port = RTSPS_DEFAULT_PORT;
- rt->lower_transport_mask = 1 << RTSP_LOWER_TRANSPORT_TCP;
+ lower_rtsp_proto = "tls";
+ default_port = RTSPS_DEFAULT_PORT;
} else if (!strcmp(proto, "satip")) {
av_strlcpy(proto, "rtsp", sizeof(proto));
rt->server_type = RTSP_SERVER_SATIP;
diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h
index 3c9c2c842d..f824c4e70c 100644
--- a/libavformat/rtsp.h
+++ b/libavformat/rtsp.h
@@ -516,6 +516,8 @@ typedef struct RTSPStream {
char crypto_suite[40];
char crypto_params[100];
+ uint32_t crypto_roc;
+ uint32_t crypto_ssrc;
} RTSPStream;
void ff_rtsp_parse_line(AVFormatContext *s,
--
2.52.0
1
0
PR #23407 opened by Niklas Haas (haasn)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23407
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23407.patch
This suppresses the addition of #line and other directives in the preprocessed
output, which is what we want when we're invoking the hostcc just to preprocess
some files. (Currently, this variable is only used for configure-internal
checks anyways)
On MSVC/Intel, /EP is the equivalent syntax, though we use -EP instead for
consistency.
Signed-off-by: Niklas Haas <git(a)haasn.dev>
# Summary of changes
Split off from #23126 for visibility. That PR needs this change because it relies on using the C preprocessor to auto-generate NASM macros, which requires a "clean" output from the preprocessor (without #line directives and other noise).
From c10c584e5e19ca90e603a45610552570fef74f4f Mon Sep 17 00:00:00 2001
From: Niklas Haas <git(a)haasn.dev>
Date: Sat, 6 Jun 2026 18:50:22 +0200
Subject: [PATCH] configure: add -P to $CC_E flag
This suppresses the addition of #line and other directives in the preprocessed
output, which is what we want when we're invoking the hostcc just to preprocess
some files. (Currently, this variable is only used for configure-internal
checks anyways)
On MSVC/Intel, /EP is the equivalent syntax, though we use -EP instead for
consistency.
Signed-off-by: Niklas Haas <git(a)haasn.dev>
---
configure | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/configure b/configure
index f30f4bfa42..ccb0ab9420 100755
--- a/configure
+++ b/configure
@@ -4521,19 +4521,19 @@ ldflags_filter=echo
AS_C='-c'
AS_O='-o $@'
CC_C='-c'
-CC_E='-E -o $@'
+CC_E='-E -P -o $@'
CC_O='-o $@'
CXX_C='-c'
CXX_O='-o $@'
OBJCC_C='-c'
-OBJCC_E='-E -o $@'
+OBJCC_E='-E -P -o $@'
OBJCC_O='-o $@'
X86ASM_O='-o $@'
LD_O='-o $@'
LD_LIB='-l%'
LD_PATH='-L'
HOSTCC_C='-c'
-HOSTCC_E='-E -o $@'
+HOSTCC_E='-E -P -o $@'
HOSTCC_O='-o $@'
HOSTLD_O='-o $@'
GLSLC_O='-o $@'
@@ -5434,7 +5434,7 @@ probe_cc(){
_ld_o='-Fe$@'
fi
_cc_o='-Fo$@'
- _cc_e='-P'
+ _cc_e='-P -EP'
_flags_filter=icl_flags
_ld_lib='%.lib'
_ld_path='-libpath:'
@@ -5484,7 +5484,7 @@ probe_cc(){
_flags_filter=msvc_flags
fi
_cc_o='-Fo$@'
- _cc_e='-P -Fi$@'
+ _cc_e='-P -EP -Fi$@'
_ld_lib='%.lib'
_ld_path='-libpath:'
_flags='-nologo'
--
2.52.0
1
0
[PR] avformat/rtspdec: send TEARDOWN on close despite user interrupt (PR #23406)
by Thomas Devoogdt 08 Jun '26
by Thomas Devoogdt 08 Jun '26
08 Jun '26
PR #23406 opened by Thomas Devoogdt (ThomasDevoogdt)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23406
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23406.patch
When ffplay exits via SIGTERM/Ctrl-C, the AVFormatContext interrupt
callback is set. The RTSP demuxer skipped TEARDOWN entirely, leaving
the server session alive (~10 s), which caused "453 Not Enough
Bandwidth" on immediate reconnect.
Fix the problem at every layer it can occur:
fftools/ffplay: make sigterm_handler() set a flag instead of calling
exit() directly. The main event loop checks the flag and routes
through do_exit() -> avformat_close_input() so that TEARDOWN is
reached during normal shutdown.
avformat/rtspdec: in rtsp_read_close(), replace the user interrupt
callback with a 500 ms deadline callback on both the TLS URLContext
and its TCP child before sending TEARDOWN. Without patching the TCP
child, GnuTLS/OpenSSL push callbacks receive AVERROR_EXIT from the
TCP write and previously returned 0 ("sent 0 bytes, try again"),
causing an infinite busy-spin. Switch to ff_rtsp_send_cmd() (blocking)
instead of ff_rtsp_send_cmd_async() so the client waits for the
server's 200 OK before closing, guaranteeing the session is freed.
avformat/tls: add ff_tls_get_underlying() to expose the TCP/UDP child
URLContext of a TLS context through a proper API, avoiding direct
access to private priv_data.
avformat/tls_gnutls, tls_openssl: fix the AVERROR_EXIT -> 0 mapping
in the TLS push callbacks. Returning 0 on interrupt signals "sent 0
bytes" to the TLS library and causes a busy-spin; use EINTR / hard
error instead.
Fixes: #23405
Signed-off-by: Thomas Devoogdt <thomas(a)devoogdt.com>
# Summary of changes
Briefly describe what this PR does and why.
<!--
If this PR requires new FATE test samples, attach them to the PR and
list their target paths below (relative to the fate-suite root).
Attached filenames must match the sample's filename:
```fate-samples
# e.g. vorbis/new-sample.ogg
```
-->
From 236cba060fd6120ec804ace01df0b1cf7a19b138 Mon Sep 17 00:00:00 2001
From: Thomas Devoogdt <thomas(a)devoogdt.com>
Date: Mon, 8 Jun 2026 10:58:52 +0200
Subject: [PATCH] avformat/rtspdec: send TEARDOWN on close despite user
interrupt
When ffplay exits via SIGTERM/Ctrl-C, the AVFormatContext interrupt
callback is set. The RTSP demuxer skipped TEARDOWN entirely, leaving
the server session alive (~10 s), which caused "453 Not Enough
Bandwidth" on immediate reconnect.
Fix the problem at every layer it can occur:
fftools/ffplay: make sigterm_handler() set a flag instead of calling
exit() directly. The main event loop checks the flag and routes
through do_exit() -> avformat_close_input() so that TEARDOWN is
reached during normal shutdown.
avformat/rtspdec: in rtsp_read_close(), replace the user interrupt
callback with a 500 ms deadline callback on both the TLS URLContext
and its TCP child before sending TEARDOWN. Without patching the TCP
child, GnuTLS/OpenSSL push callbacks receive AVERROR_EXIT from the
TCP write and previously returned 0 ("sent 0 bytes, try again"),
causing an infinite busy-spin. Switch to ff_rtsp_send_cmd() (blocking)
instead of ff_rtsp_send_cmd_async() so the client waits for the
server's 200 OK before closing, guaranteeing the session is freed.
avformat/tls: add ff_tls_get_underlying() to expose the TCP/UDP child
URLContext of a TLS context through a proper API, avoiding direct
access to private priv_data.
avformat/tls_gnutls, tls_openssl: fix the AVERROR_EXIT -> 0 mapping
in the TLS push callbacks. Returning 0 on interrupt signals "sent 0
bytes" to the TLS library and causes a busy-spin; use EINTR / hard
error instead.
Fixes: #23405
Signed-off-by: Thomas Devoogdt <thomas(a)devoogdt.com>
---
fftools/ffplay.c | 6 +++++-
libavformat/rtspdec.c | 34 ++++++++++++++++++++++++++++++++--
libavformat/tls.c | 7 +++++++
libavformat/tls.h | 5 +++++
libavformat/tls_gnutls.c | 7 ++++---
libavformat/tls_openssl.c | 7 ++++---
6 files changed, 57 insertions(+), 9 deletions(-)
diff --git a/fftools/ffplay.c b/fftools/ffplay.c
index 28a83e079f..46ba85212a 100644
--- a/fftools/ffplay.c
+++ b/fftools/ffplay.c
@@ -361,6 +361,8 @@ static int64_t audio_callback_time;
#define FF_QUIT_EVENT (SDL_USEREVENT + 2)
+static volatile sig_atomic_t request_quit;
+
static SDL_Window *window;
static SDL_Renderer *renderer;
static SDL_RendererInfo renderer_info = {0};
@@ -1372,7 +1374,7 @@ static void do_exit(VideoState *is)
static void sigterm_handler(int sig)
{
- exit(123);
+ request_quit = 1;
}
static void set_default_window_size(int width, int height, AVRational sar)
@@ -3403,6 +3405,8 @@ static void refresh_loop_wait_event(VideoState *is, SDL_Event *event) {
double remaining_time = 0.0;
SDL_PumpEvents();
while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
+ if (request_quit)
+ do_exit(is);
if (!cursor_hidden && av_gettime_relative() - cursor_last_shown > CURSOR_HIDE_DELAY) {
SDL_ShowCursor(0);
cursor_hidden = 1;
diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c
index e0bdf9d4ac..32c38738c4 100644
--- a/libavformat/rtspdec.c
+++ b/libavformat/rtspdec.c
@@ -59,12 +59,42 @@ static const struct RTSPStatusMessage {
{ 0, "NULL" }
};
+static int rtsp_teardown_interrupt_cb(void *opaque)
+{
+ return av_gettime_relative() >= *(int64_t *)opaque;
+}
+
static int rtsp_read_close(AVFormatContext *s)
{
RTSPState *rt = s->priv_data;
- if (!(rt->rtsp_flags & RTSP_FLAG_LISTEN))
- ff_rtsp_send_cmd_async(s, "TEARDOWN", rt->control_uri, NULL);
+ if (!(rt->rtsp_flags & RTSP_FLAG_LISTEN)) {
+ /* Replace the interrupt callback with a short timeout so TEARDOWN
+ * can go out despite a pending Ctrl-C. For RTSPS both the TLS
+ * URLContext and its TCP child need patching (each holds an
+ * independent copy of the interrupt callback). */
+ int64_t deadline = av_gettime_relative() + 500000LL; /* 500 ms */
+ AVIOInterruptCB timeout_cb = { rtsp_teardown_interrupt_cb, &deadline };
+ URLContext *tcp_child = NULL;
+ AVIOInterruptCB saved_tls = { NULL, NULL };
+ AVIOInterruptCB saved_tcp = { NULL, NULL };
+
+ if (rt->rtsp_hd_out) {
+ saved_tls = rt->rtsp_hd_out->interrupt_callback;
+ rt->rtsp_hd_out->interrupt_callback = timeout_cb;
+ /* For TLS, also patch the underlying TCP child. */
+ tcp_child = ff_tls_get_underlying(rt->rtsp_hd_out);
+ if (tcp_child) {
+ saved_tcp = tcp_child->interrupt_callback;
+ tcp_child->interrupt_callback = timeout_cb;
+ }
+ }
+ ff_rtsp_send_cmd(s, "TEARDOWN", rt->control_uri, NULL, &(RTSPMessageHeader){0}, NULL);
+ if (rt->rtsp_hd_out)
+ rt->rtsp_hd_out->interrupt_callback = saved_tls;
+ if (tcp_child)
+ tcp_child->interrupt_callback = saved_tcp;
+ }
ff_rtsp_close_streams(s);
ff_rtsp_close_connections(s);
diff --git a/libavformat/tls.c b/libavformat/tls.c
index 3eab305f56..f027076b78 100644
--- a/libavformat/tls.c
+++ b/libavformat/tls.c
@@ -122,6 +122,13 @@ int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AV
return ret;
}
+URLContext *ff_tls_get_underlying(URLContext *h)
+{
+ if (!h || !h->prot || strcmp(h->prot->name, "tls") != 0)
+ return NULL;
+ return ((TLSShared *)h->priv_data)->tcp;
+}
+
/**
* Read all data from the given URL url and store it in the given buffer bp.
*/
diff --git a/libavformat/tls.h b/libavformat/tls.h
index 971ae5c7a5..5f14bd5fe4 100644
--- a/libavformat/tls.h
+++ b/libavformat/tls.h
@@ -119,6 +119,11 @@ int ff_tls_parse_host(TLSShared *s, char *hostname, int hostname_size, int *port
int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AVDictionary **options);
+/**
+ * Return the underlying TCP/UDP URLContext of a TLS URLContext, or NULL.
+ */
+URLContext *ff_tls_get_underlying(URLContext *h);
+
int ff_url_read_all(const char *url, AVBPrint *bp);
int ff_tls_set_external_socket(URLContext *h, URLContext *sock);
diff --git a/libavformat/tls_gnutls.c b/libavformat/tls_gnutls.c
index aedbc66e56..c40c2cd7f3 100644
--- a/libavformat/tls_gnutls.c
+++ b/libavformat/tls_gnutls.c
@@ -475,9 +475,10 @@ static ssize_t gnutls_url_push(gnutls_transport_ptr_t transport,
int ret = ffurl_write(uc, buf, len);
if (ret >= 0)
return ret;
- if (ret == AVERROR_EXIT)
- return 0;
- if (ret == AVERROR(EAGAIN)) {
+ if (ret == AVERROR_EXIT) {
+ /* Use EINTR, not 0: returning 0 would cause GnuTLS to busy-spin. */
+ errno = EINTR;
+ } else if (ret == AVERROR(EAGAIN)) {
errno = EAGAIN;
} else {
errno = EIO;
diff --git a/libavformat/tls_openssl.c b/libavformat/tls_openssl.c
index 7c1289c595..81540cfeeb 100644
--- a/libavformat/tls_openssl.c
+++ b/libavformat/tls_openssl.c
@@ -570,9 +570,10 @@ static int url_bio_bwrite(BIO *b, const char *buf, int len)
if (ret >= 0)
return ret;
BIO_clear_retry_flags(b);
- if (ret == AVERROR_EXIT)
- return 0;
- if (ret == AVERROR(EAGAIN))
+ if (ret == AVERROR_EXIT) {
+ /* Don't return 0: that signals success and silently drops the data. */
+ c->io_err = ret;
+ } else if (ret == AVERROR(EAGAIN))
BIO_set_retry_write(b);
else
c->io_err = ret;
--
2.52.0
1
0
08 Jun '26
Passing a very large number of objects directly to ar can sometimes
cause an 'Argument list too long' error.
---
compat/windows/makedef | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/compat/windows/makedef b/compat/windows/makedef
index af42f08fd5..963f2b5b55 100755
--- a/compat/windows/makedef
+++ b/compat/windows/makedef
@@ -46,7 +46,9 @@ libname=$(mktemp -u "library").lib
trap 'rm -f -- $libname' EXIT
if [ -n "$AR" ]; then
- $AR rcs ${libname} $@ >/dev/null
+ echo "rcs ${libname} $@" > ${libname}.args
+ $AR @${libname}.args > /dev/null
+ rm -f ${libname}.args
else
machine_flag=""
case "$LDFLAGS" in
--
2.54.0.windows.1
1
0
08 Jun '26
PR #23404 opened by michaelni
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23404
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23404.patch
Fixes: integer overflow
Found-by: Kery (Qi Kery <qikeyu2001(a)outlook.com>)
Signed-off-by: Michael Niedermayer <michael(a)niedermayer.cc>
From 90fb425de5a6455baa463211004b27ca081c203b Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <michael(a)niedermayer.cc>
Date: Mon, 8 Jun 2026 02:30:38 +0200
Subject: [PATCH] avfilter/v360: reject out-of-range output dimensions
Fixes: integer overflow
Found-by: Kery (Qi Kery <qikeyu2001(a)outlook.com>)
Signed-off-by: Michael Niedermayer <michael(a)niedermayer.cc>
---
libavfilter/vf_v360.c | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/libavfilter/vf_v360.c b/libavfilter/vf_v360.c
index 4384fa578b..6695e55462 100644
--- a/libavfilter/vf_v360.c
+++ b/libavfilter/vf_v360.c
@@ -4295,6 +4295,20 @@ static int v360_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
return 0;
}
+static int get_output_dimension(AVFilterContext *ctx, const char *name,
+ float val, int *dim)
+{
+ if (!isfinite(val) || val < 1.f || val > INT16_MAX) {
+ av_log(ctx, AV_LOG_ERROR,
+ "Output %s %g is outside the allowed range [1, %d].\n",
+ name, val, INT16_MAX);
+ return AVERROR(EINVAL);
+ }
+
+ *dim = lrintf(val);
+ return 0;
+}
+
static int config_output(AVFilterLink *outlink)
{
AVFilterContext *ctx = outlink->src;
@@ -4783,11 +4797,17 @@ static int config_output(AVFilterLink *outlink)
if (s->width > 0 && s->height <= 0 && s->h_fov > 0.f && s->v_fov > 0.f &&
s->out == FLAT && s->d_fov == 0.f) {
w = s->width;
- h = w / tanf(s->h_fov * M_PI / 360.f) * tanf(s->v_fov * M_PI / 360.f);
+ err = get_output_dimension(ctx, "height",
+ w / tanf(s->h_fov * M_PI / 360.f) * tanf(s->v_fov * M_PI / 360.f), &h);
+ if (err < 0)
+ return err;
} else if (s->width <= 0 && s->height > 0 && s->h_fov > 0.f && s->v_fov > 0.f &&
s->out == FLAT && s->d_fov == 0.f) {
h = s->height;
- w = h / tanf(s->v_fov * M_PI / 360.f) * tanf(s->h_fov * M_PI / 360.f);
+ err = get_output_dimension(ctx, "width",
+ h / tanf(s->v_fov * M_PI / 360.f) * tanf(s->h_fov * M_PI / 360.f), &w);
+ if (err < 0)
+ return err;
} else if (s->width > 0 && s->height > 0) {
w = s->width;
h = s->height;
@@ -4802,6 +4822,13 @@ static int config_output(AVFilterLink *outlink)
FFSWAP(int, w, h);
}
+ if (w < 1 || w > INT16_MAX || h < 1 || h > INT16_MAX) {
+ av_log(ctx, AV_LOG_ERROR,
+ "Output dimensions %dx%d are outside the allowed range [1, %d].\n",
+ w, h, INT16_MAX);
+ return AVERROR(EINVAL);
+ }
+
s->width = w;
s->height = h;
--
2.52.0
1
0
[PR] avcodec/webvttdec: map WebVTT cue timestamps to ASS {\k} tags (PR #23403)
by Jun Zhao 08 Jun '26
by Jun Zhao 08 Jun '26
08 Jun '26
PR #23403 opened by Jun Zhao (mypopydev)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23403
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23403.patch
Emit ASS {\k} centisecond overrides when burning VTT karaoke cues with
the subtitles filter. Out-of-range, non-monotonic, and malformed
inline timestamps are ignored; cues without valid timestamps are
unchanged.
ASS {\k} karaoke approximates WebVTT timed text, not ::cue(:past/:future)
styling.
Fixes: ticket #23289
Signed-off-by: Jun Zhao <barryjzhao(a)tencent.com>
From 705250a38a57383f115a08e218a041d0cd878786 Mon Sep 17 00:00:00 2001
From: Jun Zhao <barryjzhao(a)tencent.com>
Date: Mon, 8 Jun 2026 00:53:26 +0800
Subject: [PATCH] avcodec/webvttdec: map WebVTT cue timestamps to ASS {\k} tags
Emit ASS {\k} centisecond overrides when burning VTT karaoke cues with
the subtitles filter. Out-of-range, non-monotonic, and malformed
inline timestamps are ignored; cues without valid timestamps are
unchanged.
ASS {\k} karaoke approximates WebVTT timed text, not ::cue(:past/:future)
styling.
Fixes: ticket #23289
Signed-off-by: Jun Zhao <barryjzhao(a)tencent.com>
---
libavcodec/webvttdec.c | 77 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 75 insertions(+), 2 deletions(-)
diff --git a/libavcodec/webvttdec.c b/libavcodec/webvttdec.c
index 90675bc660..89eb9e7fdf 100644
--- a/libavcodec/webvttdec.c
+++ b/libavcodec/webvttdec.c
@@ -48,9 +48,61 @@ static const struct {
{"u", "{\\u1}"}, {"/u", "{\\u0}"},
};
-static int webvtt_event_to_ass(AVBPrint *buf, const char *p)
+/* parse a WebVTT timestamp string (HH:MM:SS.mmm or MM:SS.mmm).
+ * Returns milliseconds or -1 on failure. */
+static int64_t parse_webvtt_timestamp(const char *buf)
+{
+ int h = 0, m = 0, s = 0, ms = 0;
+
+ if (sscanf(buf, "%d:%2d:%2d.%3d", &h, &m, &s, &ms) == 4) {
+ if (m > 59 || s > 59)
+ return -1;
+ return (int64_t)h * 3600000 + m * 60000 + s * 1000 + ms;
+ }
+ if (sscanf(buf, "%2d:%2d.%3d", &m, &s, &ms) == 3) {
+ if (m > 59 || s > 59)
+ return -1;
+ return m * 60000 + s * 1000 + ms;
+ }
+
+ return -1;
+}
+
+static void append_k_cs(AVBPrint *buf, int64_t ms)
+{
+ if (ms > 0)
+ av_bprintf(buf, "{\\k%"PRId64"}", (ms + 5) / 10);
+}
+
+/* validate a cue timestamp tag body: must be digits/colons/periods,
+ * parseable, strictly within (cue_start, cue_end), and after prev_ts.
+ * Returns 1 and writes to *ts_out on success, 0 on failure. */
+static int read_cue_timestamp(const char *body, int len,
+ int64_t cue_start, int64_t cue_end,
+ int64_t prev_ts, int64_t *ts_out)
+{
+ int64_t ts;
+
+ if (len < 1 || !av_isdigit(body[0]))
+ return 0;
+ if ((int)strspn(body, "0123456789:.") != len)
+ return 0;
+
+ ts = parse_webvtt_timestamp(body);
+ if (ts <= cue_start || ts >= cue_end)
+ return 0;
+ if (prev_ts >= 0 && ts <= prev_ts)
+ return 0;
+
+ *ts_out = ts;
+ return 1;
+}
+
+static int webvtt_event_to_ass(AVBPrint *buf, const char *p,
+ int64_t cue_start_ms, int64_t cue_end_ms)
{
int i, again = 0;
+ int64_t prev_ts = -1, ts;
while (*p) {
if (*p == '<') {
@@ -59,6 +111,19 @@ static int webvtt_event_to_ass(AVBPrint *buf, const char *p)
if (!tag_end)
break;
len = tag_end - p + 1;
+
+ /* cue timestamp: emit {\k} for elapsed ms since cue_start
+ * or prev_ts; following text uses this timing */
+ if (len > 2 &&
+ read_cue_timestamp(p + 1, (int)(len - 2),
+ cue_start_ms, cue_end_ms, prev_ts, &ts)) {
+ append_k_cs(buf, ts - (prev_ts >= 0 ? prev_ts : cue_start_ms));
+ prev_ts = ts;
+ p += len;
+ again = 1;
+ continue;
+ }
+
for (i = 0; i < FF_ARRAY_ELEMS(webvtt_valid_tags); i++) {
const char *from = webvtt_valid_tags[i].from;
if(!strncmp(p + 1, from, strlen(from))) {
@@ -91,6 +156,11 @@ static int webvtt_event_to_ass(AVBPrint *buf, const char *p)
av_bprint_chars(buf, *p, 1);
p++;
}
+
+ /* trailing segment: last valid ts to cue end */
+ if (prev_ts >= 0 && cue_end_ms > FFMAX(prev_ts, cue_start_ms))
+ append_k_cs(buf, cue_end_ms - FFMAX(prev_ts, cue_start_ms));
+
return 0;
}
@@ -103,7 +173,10 @@ static int webvtt_decode_frame(AVCodecContext *avctx, AVSubtitle *sub,
AVBPrint buf;
av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
- if (ptr && avpkt->size > 0 && !webvtt_event_to_ass(&buf, ptr))
+ if (ptr && avpkt->size > 0 &&
+ !webvtt_event_to_ass(&buf, ptr,
+ avpkt->pts,
+ avpkt->pts + avpkt->duration))
ret = ff_ass_add_rect(sub, buf.str, s->readorder++, 0, NULL, NULL);
av_bprint_finalize(&buf, NULL);
if (ret < 0)
--
2.52.0
1
0
[PR] tools/target_dec_fuzzer: Bound cumulative get_buffer allocation (PR #23402)
by michaelni 08 Jun '26
by michaelni 08 Jun '26
08 Jun '26
PR #23402 opened by michaelni
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23402
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23402.patch
Fixes: Timeout
Fixes: 509366072/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_H264_fuzzer-4588961581563904
Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael(a)niedermayer.cc>
From 1a642441fb1e3c94d3036b35635c3fddeed9b33e Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <michael(a)niedermayer.cc>
Date: Fri, 5 Jun 2026 00:56:08 +0200
Subject: [PATCH] tools/target_dec_fuzzer: Bound cumulative get_buffer
allocation
Fixes: Timeout
Fixes: 509366072/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_H264_fuzzer-4588961581563904
Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael(a)niedermayer.cc>
---
tools/target_dec_fuzzer.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/tools/target_dec_fuzzer.c b/tools/target_dec_fuzzer.c
index 723f7996d7..9f6df59f02 100644
--- a/tools/target_dec_fuzzer.c
+++ b/tools/target_dec_fuzzer.c
@@ -105,6 +105,9 @@ const uint32_t maxiteration = 8096;
static const uint64_t FUZZ_TAG = 0x4741542D5A5A5546ULL;
+static uint64_t alloc_pixels;
+static uint64_t max_alloc_pixels;
+
static int fuzz_video_get_buffer(AVCodecContext *ctx, AVFrame *frame)
{
ptrdiff_t linesize1[4];
@@ -113,6 +116,11 @@ static int fuzz_video_get_buffer(AVCodecContext *ctx, AVFrame *frame)
int i, ret, w = frame->width, h = frame->height;
avcodec_align_dimensions2(ctx, &w, &h, linesize_align);
+
+ alloc_pixels += (uint64_t)w * h;
+ if (alloc_pixels > max_alloc_pixels)
+ return AVERROR(ENOMEM);
+
ret = av_image_fill_linesizes(frame->linesize, ctx->pix_fmt, w);
if (ret < 0)
return ret;
@@ -355,6 +363,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
maxsamples_per_frame = FFMIN(maxsamples_per_frame, maxsamples);
maxpixels_per_frame = FFMIN(maxpixels_per_frame , maxpixels);
+ alloc_pixels = 0;
+ max_alloc_pixels = maxpixels;
+
AVCodecContext* ctx = avcodec_alloc_context3(&c->p);
AVCodecContext* parser_avctx = avcodec_alloc_context3(NULL);
if (!ctx || !parser_avctx)
--
2.52.0
1
0
[PR] avfilter/convolution: accumulate user matrix products in float (PR #23401)
by michaelni 07 Jun '26
by michaelni 07 Jun '26
07 Jun '26
PR #23401 opened by michaelni
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23401
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23401.patch
The convolution filter accumulates pixel samples multiplied by
user-supplied matrix coefficients. With large coefficients the int
product and accumulator overflow before the result is clipped to the
output range.
Accumulate in float and cast the coefficient so the per-sample product
is computed in float as well. This matches the float based sobel/scharr
paths and the subsequent rdiv/bias scaling
Found-by: Kery (Qi Kery <qikeyu2001(a)outlook.com>)
Signed-off-by: Michael Niedermayer <michael(a)niedermayer.cc>
From e4e6af495afd6606d8d4b2c3bb5bd3e95c79f114 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <michael(a)niedermayer.cc>
Date: Sat, 6 Jun 2026 21:02:34 +0200
Subject: [PATCH] avfilter/convolution: accumulate user matrix products in
float
The convolution filter accumulates pixel samples multiplied by
user-supplied matrix coefficients. With large coefficients the int
product and accumulator overflow before the result is clipped to the
output range.
Accumulate in float and cast the coefficient so the per-sample product
is computed in float as well. This matches the float based sobel/scharr
paths and the subsequent rdiv/bias scaling
Found-by: Kery (Qi Kery <qikeyu2001(a)outlook.com>)
Signed-off-by: Michael Niedermayer <michael(a)niedermayer.cc>
---
libavfilter/vf_convolution.c | 82 +++++++++++++++++++-----------------
1 file changed, 44 insertions(+), 38 deletions(-)
diff --git a/libavfilter/vf_convolution.c b/libavfilter/vf_convolution.c
index 7a27bdba20..7ec4d04287 100644
--- a/libavfilter/vf_convolution.c
+++ b/libavfilter/vf_convolution.c
@@ -322,16 +322,16 @@ static void filter16_3x3(uint8_t *dstp, int width,
int x;
for (x = 0; x < width; x++) {
- int sum = AV_RN16A(&c[0][2 * x]) * matrix[0] +
- AV_RN16A(&c[1][2 * x]) * matrix[1] +
- AV_RN16A(&c[2][2 * x]) * matrix[2] +
- AV_RN16A(&c[3][2 * x]) * matrix[3] +
- AV_RN16A(&c[4][2 * x]) * matrix[4] +
- AV_RN16A(&c[5][2 * x]) * matrix[5] +
- AV_RN16A(&c[6][2 * x]) * matrix[6] +
- AV_RN16A(&c[7][2 * x]) * matrix[7] +
- AV_RN16A(&c[8][2 * x]) * matrix[8];
- sum = (int)(sum * rdiv + bias + 0.5f);
+ float sum = AV_RN16A(&c[0][2 * x]) * (float)matrix[0] +
+ AV_RN16A(&c[1][2 * x]) * (float)matrix[1] +
+ AV_RN16A(&c[2][2 * x]) * (float)matrix[2] +
+ AV_RN16A(&c[3][2 * x]) * (float)matrix[3] +
+ AV_RN16A(&c[4][2 * x]) * (float)matrix[4] +
+ AV_RN16A(&c[5][2 * x]) * (float)matrix[5] +
+ AV_RN16A(&c[6][2 * x]) * (float)matrix[6] +
+ AV_RN16A(&c[7][2 * x]) * (float)matrix[7] +
+ AV_RN16A(&c[8][2 * x]) * (float)matrix[8];
+ sum = sum * rdiv + bias + 0.5f;
dst[x] = av_clip(sum, 0, peak);
}
}
@@ -345,12 +345,13 @@ static void filter16_5x5(uint8_t *dstp, int width,
int x;
for (x = 0; x < width; x++) {
- int i, sum = 0;
+ int i;
+ float sum = 0;
for (i = 0; i < 25; i++)
- sum += AV_RN16A(&c[i][2 * x]) * matrix[i];
+ sum += AV_RN16A(&c[i][2 * x]) * (float)matrix[i];
- sum = (int)(sum * rdiv + bias + 0.5f);
+ sum = sum * rdiv + bias + 0.5f;
dst[x] = av_clip(sum, 0, peak);
}
}
@@ -364,12 +365,13 @@ static void filter16_7x7(uint8_t *dstp, int width,
int x;
for (x = 0; x < width; x++) {
- int i, sum = 0;
+ int i;
+ float sum = 0;
for (i = 0; i < 49; i++)
- sum += AV_RN16A(&c[i][2 * x]) * matrix[i];
+ sum += AV_RN16A(&c[i][2 * x]) * (float)matrix[i];
- sum = (int)(sum * rdiv + bias + 0.5f);
+ sum = sum * rdiv + bias + 0.5f;
dst[x] = av_clip(sum, 0, peak);
}
}
@@ -383,12 +385,13 @@ static void filter16_row(uint8_t *dstp, int width,
int x;
for (x = 0; x < width; x++) {
- int i, sum = 0;
+ int i;
+ float sum = 0;
for (i = 0; i < 2 * radius + 1; i++)
- sum += AV_RN16A(&c[i][2 * x]) * matrix[i];
+ sum += AV_RN16A(&c[i][2 * x]) * (float)matrix[i];
- sum = (int)(sum * rdiv + bias + 0.5f);
+ sum = sum * rdiv + bias + 0.5f;
dst[x] = av_clip(sum, 0, peak);
}
}
@@ -398,7 +401,7 @@ static void filter16_column(uint8_t *dstp, int height,
const uint8_t *c[], int peak, int radius,
int dstride, int stride, int size)
{
- DECLARE_ALIGNED(64, int, sum)[16];
+ DECLARE_ALIGNED(64, float, sum)[16];
uint16_t *dst = (uint16_t *)dstp;
const int width = FFMIN(16, size);
@@ -407,11 +410,11 @@ static void filter16_column(uint8_t *dstp, int height,
memset(sum, 0, sizeof(sum));
for (int i = 0; i < 2 * radius + 1; i++) {
for (int off16 = 0; off16 < width; off16++)
- sum[off16] += AV_RN16A(&c[i][0 + y * stride + off16 * 2]) * matrix[i];
+ sum[off16] += AV_RN16A(&c[i][0 + y * stride + off16 * 2]) * (float)matrix[i];
}
for (int off16 = 0; off16 < width; off16++) {
- sum[off16] = (int)(sum[off16] * rdiv + bias + 0.5f);
+ sum[off16] = sum[off16] * rdiv + bias + 0.5f;
dst[off16] = av_clip(sum[off16], 0, peak);
}
dst += dstride / 2;
@@ -426,12 +429,13 @@ static void filter_7x7(uint8_t *dst, int width,
int x;
for (x = 0; x < width; x++) {
- int i, sum = 0;
+ int i;
+ float sum = 0;
for (i = 0; i < 49; i++)
- sum += c[i][x] * matrix[i];
+ sum += c[i][x] * (float)matrix[i];
- sum = (int)(sum * rdiv + bias + 0.5f);
+ sum = sum * rdiv + bias + 0.5f;
dst[x] = av_clip_uint8(sum);
}
}
@@ -444,12 +448,13 @@ static void filter_5x5(uint8_t *dst, int width,
int x;
for (x = 0; x < width; x++) {
- int i, sum = 0;
+ int i;
+ float sum = 0;
for (i = 0; i < 25; i++)
- sum += c[i][x] * matrix[i];
+ sum += c[i][x] * (float)matrix[i];
- sum = (int)(sum * rdiv + bias + 0.5f);
+ sum = sum * rdiv + bias + 0.5f;
dst[x] = av_clip_uint8(sum);
}
}
@@ -465,10 +470,10 @@ static void filter_3x3(uint8_t *dst, int width,
int x;
for (x = 0; x < width; x++) {
- int sum = c0[x] * matrix[0] + c1[x] * matrix[1] + c2[x] * matrix[2] +
- c3[x] * matrix[3] + c4[x] * matrix[4] + c5[x] * matrix[5] +
- c6[x] * matrix[6] + c7[x] * matrix[7] + c8[x] * matrix[8];
- sum = (int)(sum * rdiv + bias + 0.5f);
+ float sum = c0[x] * (float)matrix[0] + c1[x] * (float)matrix[1] + c2[x] * (float)matrix[2] +
+ c3[x] * (float)matrix[3] + c4[x] * (float)matrix[4] + c5[x] * (float)matrix[5] +
+ c6[x] * (float)matrix[6] + c7[x] * (float)matrix[7] + c8[x] * (float)matrix[8];
+ sum = sum * rdiv + bias + 0.5f;
dst[x] = av_clip_uint8(sum);
}
}
@@ -481,12 +486,13 @@ static void filter_row(uint8_t *dst, int width,
int x;
for (x = 0; x < width; x++) {
- int i, sum = 0;
+ int i;
+ float sum = 0;
for (i = 0; i < 2 * radius + 1; i++)
- sum += c[i][x] * matrix[i];
+ sum += c[i][x] * (float)matrix[i];
- sum = (int)(sum * rdiv + bias + 0.5f);
+ sum = sum * rdiv + bias + 0.5f;
dst[x] = av_clip_uint8(sum);
}
}
@@ -496,18 +502,18 @@ static void filter_column(uint8_t *dst, int height,
const uint8_t *c[], int peak, int radius,
int dstride, int stride, int size)
{
- DECLARE_ALIGNED(64, int, sum)[16];
+ DECLARE_ALIGNED(64, float, sum)[16];
for (int y = 0; y < height; y++) {
memset(sum, 0, sizeof(sum));
for (int i = 0; i < 2 * radius + 1; i++) {
for (int off16 = 0; off16 < 16; off16++)
- sum[off16] += c[i][0 + y * stride + off16] * matrix[i];
+ sum[off16] += c[i][0 + y * stride + off16] * (float)matrix[i];
}
for (int off16 = 0; off16 < 16; off16++) {
- sum[off16] = (int)(sum[off16] * rdiv + bias + 0.5f);
+ sum[off16] = sum[off16] * rdiv + bias + 0.5f;
dst[off16] = av_clip_uint8(sum[off16]);
}
dst += dstride;
--
2.52.0
1
0
[PR] tests/fate/hlsenc: add regression test for mixed stream time base segmenting (PR #23400)
by u6bkep 07 Jun '26
by u6bkep 07 Jun '26
07 Jun '26
PR #23400 opened by u6bkep
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23400
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23400.patch
Follow-up to #22726 (merged as 45cb56c520), which fixed segment-duration
calculation in the HLS muxer when streams have different time bases.
In the review of that PR, the suggestion was made to add a regression test:
> if you respin this, please consider adding a regression test. The current
> HLS FATE coverage in `tests/fate/hlsenc.mak` exercises a number of HLS cases,
> including fMP4, but I did not find a mixed audio+video / mixed-time-base
> segment-splitting case there. [...] reducing it to a portable lavfi-only FATE
> case would make this much harder to regress later.
This adds that test, `fate-hls-mixed-timebase`, using lavfi-only input (no
external samples required).
## What it does
The test reproduces the exact scenario the fix addressed:
1. Generate an mpegts source where the audio stream (`1/48000`) starts 0.5s
before the video stream and timestamps carry a large offset
(`-output_ts_offset 3600`), so `vs->start_pts` is captured from an audio
packet and is non-zero.
2. HLS-mux it with **video passthrough** (`-c:v copy`, time base `1/90000`) +
**audio transcode** (`-c:a aac`, time base `1/48000`) into fMP4 segments at
`-hls_time 3` - the real-world Blu-ray-remux case from the original report.
3. Assert the resulting `#EXTINF` durations via `sed`/`diff`.
## Why this guards the fix
Before the fix, `vs->start_pts` was stored in audio ticks and then subtracted
from video PTS without time-base conversion. The cross-time-base elapsed value
overflowed `-hls_time`, so every keyframe forced a new segment.
Verified against both states of `libavformat/hlsenc.c`:
| build | `#EXTINF` output |
| --------------------- | ------------------------------------------------------- |
| with fix (HEAD) | `3.000000`, `3.000000`, `3.000000`, `1.000000` - passes |
| fix reverted (HEAD~1) | 10 * `1.000000` - test fails |
The full lavfi-only `hlsenc` FATE group still passes.
From c0a9f5308fd40dda0d1d81d392e824145225b331 Mon Sep 17 00:00:00 2001
From: Ben Kepner <u6bkep(a)gmail.com>
Date: Sun, 7 Jun 2026 15:20:00 -0400
Subject: [PATCH] tests/fate/hlsenc: add regression test for mixed stream time
base segmenting
Follow-up to 45cb56c520 ("avformat/hlsenc: fix segment duration with
mixed stream time bases"), adding the regression test requested in
review.
The test generates an mpegts source where audio (1/48000) starts before
video and timestamps carry a large offset, then HLS-muxes it with video
passthrough (1/90000) and audio transcode (1/48000) into fmp4 segments
at -hls_time 3, asserting the resulting EXTINF durations. Input is
lavfi-only, so no external samples are required.
Without the fix, vs->start_pts is captured from the audio packet in
audio ticks and subtracted from video PTS without conversion, so every
keyframe forces a new segment (ten 1s segments instead of ~3s). The test
fails on the pre-fix code and passes with the fix in place.
Signed-off-by: Ben Kepner <u6bkep(a)gmail.com>
---
tests/fate/hlsenc.mak | 25 +++++++++++++++++++++++++
tests/ref/fate/hls-mixed-timebase | 4 ++++
2 files changed, 29 insertions(+)
create mode 100644 tests/ref/fate/hls-mixed-timebase
diff --git a/tests/fate/hlsenc.mak b/tests/fate/hlsenc.mak
index b71fe219a6..7fd407a2d7 100644
--- a/tests/fate/hlsenc.mak
+++ b/tests/fate/hlsenc.mak
@@ -224,6 +224,31 @@ fate-hls-start-number: tests/data/hls_start_number.m3u8
fate-hls-start-number: CMD = sed -n -e /^\#EXT-X-MEDIA-SEQUENCE:/p -e /^[^\#]/p $(TARGET_PATH)/tests/data/hls_start_number.m3u8
fate-hls-start-number: CMP = diff
+# This tests that the HLS muxer splits segments at the right points when the
+# audio and video streams have different time bases (1/48000 and 1/90000) and
+# the first packet seen is audio. The source is built so audio precedes video
+# with a large timestamp offset; the EXTINF durations must honour -hls_time
+# rather than splitting on every keyframe.
+tests/data/hls_mixed_timebase.m3u8: TAG = GEN
+tests/data/hls_mixed_timebase.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data
+ $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \
+ -f lavfi -i "sine=frequency=440:duration=11:sample_rate=48000" \
+ -itsoffset 0.5 -f lavfi -i "testsrc2=size=128x72:rate=24:d=10" \
+ -c:v mpeg2video -g 24 -c:a mp2 -b:a 128k -output_ts_offset 3600 \
+ -flags +bitexact -f mpegts $(TARGET_PATH)/tests/data/hls_mixed_timebase_src.ts 2>/dev/null && \
+ $(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin -copyts \
+ -i $(TARGET_PATH)/tests/data/hls_mixed_timebase_src.ts \
+ -c:v copy -c:a aac -b:a 128k -flags +bitexact \
+ -hls_segment_type fmp4 -hls_fmp4_init_filename hls_mixed_timebase_init.mp4 \
+ -f hls -hls_time 3 -hls_list_size 0 -hls_playlist_type vod \
+ -hls_segment_filename $(TARGET_PATH)/tests/data/hls_mixed_timebase_%d.m4s \
+ $(TARGET_PATH)/tests/data/hls_mixed_timebase.m3u8 2>/dev/null
+
+FATE_HLSENC_LAVFI-$(call ALLYES, SINE_FILTER TESTSRC2_FILTER LAVFI_INDEV MPEG2VIDEO_ENCODER MP2_ENCODER MP2_DECODER AAC_ENCODER HLS_MUXER MP4_MUXER MPEGTS_MUXER MPEGTS_DEMUXER FILE_PROTOCOL) += fate-hls-mixed-timebase
+fate-hls-mixed-timebase: tests/data/hls_mixed_timebase.m3u8
+fate-hls-mixed-timebase: CMD = sed -n -e /^\#EXTINF:/p $(TARGET_PATH)/tests/data/hls_mixed_timebase.m3u8
+fate-hls-mixed-timebase: CMP = diff
+
FATE_HLSENC_LAVFI-yes := $(if $(call FRAMECRC), $(FATE_HLSENC_LAVFI-yes))
FATE_FFMPEG += $(FATE_HLSENC_LAVFI-yes)
diff --git a/tests/ref/fate/hls-mixed-timebase b/tests/ref/fate/hls-mixed-timebase
new file mode 100644
index 0000000000..e9560c65c6
--- /dev/null
+++ b/tests/ref/fate/hls-mixed-timebase
@@ -0,0 +1,4 @@
+#EXTINF:3.000000,
+#EXTINF:3.000000,
+#EXTINF:3.000000,
+#EXTINF:1.000000,
--
2.52.0
1
0