PR #24041 opened by AYOUB NABIL BOUBAGRAT (ayoubnabil)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24041
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24041.patch

ff_inlink_consume_samples() can return a partial frame when the input
reaches EOF. arnndn still processed FRAME_SIZE samples, reading past
the valid input and potentially turning the final frame into NaNs.
zero-pad the partial input before processing, then trim the output back
to the original sample count.

fixes #23746.


>From a6eca074cd1c7a81b2a8a5f06cdf5a9c3a56a45c Mon Sep 17 00:00:00 2001
From: Ayoub Nabil Boubagrat <[email protected]>
Date: Fri, 7 Aug 2026 13:15:30 +0200
Subject: [PATCH] avfilter/af_arnndn: handle partial frames at EOF

ff_inlink_consume_samples() can return a partial frame when the input
reaches EOF. arnndn still processed FRAME_SIZE samples, reading past
the valid input and potentially turning the final frame into NaNs.

zero-pad the partial input before processing, then trim the output back
to the original sample count.

fixes #23746.

Signed-off-by: Ayoub Nabil Boubagrat 
<[email protected]>
---
 libavfilter/af_arnndn.c | 32 +++++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/libavfilter/af_arnndn.c b/libavfilter/af_arnndn.c
index 6209f1b0e0..ffad40529d 100644
--- a/libavfilter/af_arnndn.c
+++ b/libavfilter/af_arnndn.c
@@ -37,6 +37,7 @@
 #include "libavutil/mem.h"
 #include "libavutil/mem_internal.h"
 #include "libavutil/opt.h"
+#include "libavutil/samplefmt.h"
 #include "libavutil/tx.h"
 #include "avfilter.h"
 #include "audio.h"
@@ -1432,18 +1433,47 @@ static int filter_frame(AVFilterLink *inlink, AVFrame 
*in)
     AVFilterLink *outlink = ctx->outputs[0];
     AVFrame *out = NULL;
     ThreadData td;
+    const int nb_samples = in->nb_samples;
+    int ret;
 
     out = ff_get_audio_buffer(outlink, FRAME_SIZE);
     if (!out) {
         av_frame_free(&in);
         return AVERROR(ENOMEM);
     }
-    av_frame_copy_props(out, in);
+
+    ret = av_frame_copy_props(out, in);
+    if (ret < 0) {
+        av_frame_free(&out);
+        av_frame_free(&in);
+        return ret;
+    }
+
+    if (nb_samples < FRAME_SIZE) {
+        AVFrame *padded = ff_get_audio_buffer(outlink, FRAME_SIZE);
+
+        if (!padded) {
+            av_frame_free(&out);
+            av_frame_free(&in);
+            return AVERROR(ENOMEM);
+        }
+
+        av_samples_copy(padded->extended_data, in->extended_data,
+                        0, 0, nb_samples, in->ch_layout.nb_channels,
+                        in->format);
+        av_samples_set_silence(padded->extended_data, nb_samples,
+                               FRAME_SIZE - nb_samples,
+                               in->ch_layout.nb_channels, in->format);
+
+        av_frame_free(&in);
+        in = padded;
+    }
 
     td.in = in; td.out = out;
     ff_filter_execute(ctx, rnnoise_channels, &td, NULL,
                       FFMIN(outlink->ch_layout.nb_channels, 
ff_filter_get_nb_threads(ctx)));
 
+    out->nb_samples = nb_samples;
     av_frame_free(&in);
     return ff_filter_frame(outlink, out);
 }
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to