Commit 941ad47ced for ffmpeg
commit 941ad47ced0f4c00b61e428424e444cf4831d52a
Author: romainhedouin <romain.hedouin@epitech.eu>
Date: Fri Oct 16 22:37:20 2026 +0200
avfilter/vf_nnedi: write each output line as soon as it is computed
Compute and write one line at a time instead of filling a float buffer
for the whole slice first. The read and write helpers now work on one
line, so they no longer need strides and a height.
The output is unchanged.
Found during a code review sweep of ffmpeg using an LLM.
Signed-off-by: romainhedouin <romain.hedouin@epitech.eu>
diff --git a/libavfilter/vf_nnedi.c b/libavfilter/vf_nnedi.c
index 879318b48f..bad1b669cd 100644
--- a/libavfilter/vf_nnedi.c
+++ b/libavfilter/vf_nnedi.c
@@ -103,11 +103,9 @@ typedef struct NNEDIContext {
float **output_buf;
void (*read)(const uint8_t *src, float *dst,
- int src_stride, int dst_stride,
- int width, int height, float scale);
+ int width, float scale);
void (*write)(const float *src, uint8_t *dst,
- int src_stride, int dst_stride,
- int width, int height, int depth, float scale);
+ int width, int depth, float scale);
void (*prescreen[2])(AVFilterContext *ctx,
const void *src, ptrdiff_t src_stride,
uint8_t *prescreen, int N,
@@ -440,77 +438,47 @@ static void predictor(AVFilterContext *ctx,
}
static void read_bytes(const uint8_t *src, float *dst,
- int src_stride, int dst_stride,
- int width, int height, float scale)
+ int width, float scale)
{
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < 32; x++)
- dst[-x - 1] = src[FFMIN(x, width - 1)];
+ for (int x = 0; x < 32; x++)
+ dst[-x - 1] = src[FFMIN(x, width - 1)];
- for (int x = 0; x < width; x++)
- dst[x] = src[x];
+ for (int x = 0; x < width; x++)
+ dst[x] = src[x];
- for (int x = 0; x < 32; x++)
- dst[width + x] = src[FFMAX(width - x - 1, 0)];
-
- dst += dst_stride;
- src += src_stride;
- }
+ for (int x = 0; x < 32; x++)
+ dst[width + x] = src[FFMAX(width - x - 1, 0)];
}
static void read_words(const uint8_t *srcp, float *dst,
- int src_stride, int dst_stride,
- int width, int height, float scale)
+ int width, float scale)
{
const uint16_t *src = (const uint16_t *)srcp;
- src_stride /= 2;
+ for (int x = 0; x < 32; x++)
+ dst[-x - 1] = src[FFMIN(x, width - 1)] * scale;
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < 32; x++)
- dst[-x - 1] = src[FFMIN(x, width - 1)] * scale;
+ for (int x = 0; x < width; x++)
+ dst[x] = src[x] * scale;
- for (int x = 0; x < width; x++)
- dst[x] = src[x] * scale;
-
- for (int x = 0; x < 32; x++)
- dst[width + x] = src[FFMAX(width - x - 1, 0)] * scale;
-
- dst += dst_stride;
- src += src_stride;
- }
+ for (int x = 0; x < 32; x++)
+ dst[width + x] = src[FFMAX(width - x - 1, 0)] * scale;
}
static void write_bytes(const float *src, uint8_t *dst,
- int src_stride, int dst_stride,
- int width, int height, int depth,
- float scale)
+ int width, int depth, float scale)
{
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++)
- dst[x] = av_clip_uint8(src[x]);
-
- dst += dst_stride;
- src += src_stride;
- }
+ for (int x = 0; x < width; x++)
+ dst[x] = av_clip_uint8(src[x]);
}
static void write_words(const float *src, uint8_t *dstp,
- int src_stride, int dst_stride,
- int width, int height, int depth,
- float scale)
+ int width, int depth, float scale)
{
uint16_t *dst = (uint16_t *)dstp;
- dst_stride /= 2;
-
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++)
- dst[x] = av_clip_uintp2_c(src[x] * scale, depth);
-
- dst += dst_stride;
- src += src_stride;
- }
+ for (int x = 0; x < width; x++)
+ dst[x] = av_clip_uintp2_c(src[x] * scale, depth);
}
static void interpolation(const void *src, ptrdiff_t src_stride,
@@ -559,11 +527,11 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
const int src_linesize = in->linesize[p];
const int dst_linesize = out->linesize[p];
uint8_t *prescreen_buf = s->prescreen_buf[jobnr];
- float *srcbuf = s->input_buf[jobnr];
+ float *srcbuf = s->input_buf[jobnr] + 32;
const int srcbuf_stride = width + 64;
float *dstbuf = s->output_buf[jobnr];
- const int dstbuf_stride = width;
- const int slice_height = (slice_end - slice_start + tff) / 2;
+ const int y0 = slice_start + !tff;
+ const int nb_lines = (slice_end - y0 + 1) / 2;
// first and last line of the field that is kept
const int first = FFMIN(tff, height - 1);
const int last = FFMAX(height - 1 - ((height - 1 - tff) & 1), 0);
@@ -590,45 +558,32 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
out_line += dst_linesize * 2;
}
- if (!slice_height)
- continue;
-
- y_out = slice_start + ((!tff) ^ (slice_start & 1));
- out_line = dst_data + (y_out * dst_linesize);
+ for (int i = 0; i < nb_lines + 5; i++) {
+ const int y = av_clip(y0 - 5 + 2 * i, first, last);
- for (int i = 0; i < slice_height + 5; i++) {
- const int y = av_clip(y_out - 5 + 2 * i, first, last);
-
- s->read(src_data + y * src_linesize, srcbuf + 32 + i * srcbuf_stride,
- src_linesize * 2, srcbuf_stride, width, 1, in_scale);
+ s->read(src_data + y * src_linesize, srcbuf + i * srcbuf_stride,
+ width, in_scale);
}
- srcbuf += 3 * srcbuf_stride;
if (!s->pscrn)
memset(prescreen_buf, 0, width);
- for (int y = 0; y < 2 * slice_height; y += 2) {
+ for (int i = 0; i < nb_lines; i++) {
+ const float *src = srcbuf + (i + 3) * srcbuf_stride;
+
if (s->pscrn > 0)
- s->prescreen[s->pscrn > 1](ctx, srcbuf + (y / 2) * srcbuf_stride + 32,
- srcbuf_stride, prescreen_buf, width,
- &s->prescreener[s->pscrn - 1]);
-
- predictor(ctx,
- srcbuf + (y / 2) * srcbuf_stride + 32,
- srcbuf_stride,
- dstbuf + (y / 2) * dstbuf_stride,
- prescreen_buf, width,
+ s->prescreen[s->pscrn > 1](ctx, src, srcbuf_stride, prescreen_buf, width,
+ &s->prescreener[s->pscrn - 1]);
+
+ predictor(ctx, src, srcbuf_stride, dstbuf, prescreen_buf, width,
&s->coeffs[s->etype][s->nnsparam][s->nsize], s->qual == 2);
if (s->pscrn > 0)
- interpolation(srcbuf + (y / 2) * srcbuf_stride + 32,
- srcbuf_stride,
- dstbuf + (y / 2) * dstbuf_stride,
- prescreen_buf, width);
- }
+ interpolation(src, srcbuf_stride, dstbuf, prescreen_buf, width);
- s->write(dstbuf, out_line, dstbuf_stride, dst_linesize * 2,
- width, slice_height, depth, out_scale);
+ s->write(dstbuf, dst_data + (y0 + 2 * i) * dst_linesize,
+ width, depth, out_scale);
+ }
}
return 0;