[FFmpeg-cvslog] avfilter/af_crossfeed: always return same number of samples with block processing

Paul B Mahol git at videolan.org
Fri May 13 16:17:11 EEST 2022


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Fri May 13 11:04:36 2022 +0200| [2c77d9150d101582b75d8a8e57c6001774800be7] | committer: Paul B Mahol

avfilter/af_crossfeed: always return same number of samples with block processing

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=2c77d9150d101582b75d8a8e57c6001774800be7
---

 libavfilter/af_crossfeed.c | 66 +++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 59 insertions(+), 7 deletions(-)

diff --git a/libavfilter/af_crossfeed.c b/libavfilter/af_crossfeed.c
index d7110098e0..9a518e5258 100644
--- a/libavfilter/af_crossfeed.c
+++ b/libavfilter/af_crossfeed.c
@@ -40,6 +40,9 @@ typedef struct CrossfeedContext {
 
     double w1, w2;
 
+    int64_t pts;
+    int nb_samples;
+
     double *mid;
     double *side[3];
 } CrossfeedContext;
@@ -126,7 +129,7 @@ static void filter_samples(double *dst, const double *src,
     *sw2 = w2;
 }
 
-static int filter_frame(AVFilterLink *inlink, AVFrame *in)
+static int filter_frame(AVFilterLink *inlink, AVFrame *in, int eof)
 {
     AVFilterContext *ctx = inlink->dst;
     AVFilterLink *outlink = ctx->outputs[0];
@@ -140,12 +143,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     const double a1 = -s->a1;
     const double a2 = -s->a2;
     AVFrame *out;
+    int drop = 0;
     double *dst;
 
-    if (av_frame_is_writable(in)) {
+    if (av_frame_is_writable(in) && s->block_samples == 0) {
         out = in;
     } else {
-        out = ff_get_audio_buffer(outlink, in->nb_samples);
+        out = ff_get_audio_buffer(outlink, s->block_samples > 0 ? s->block_samples : in->nb_samples);
         if (!out) {
             av_frame_free(&in);
             return AVERROR(ENOMEM);
@@ -154,6 +158,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     }
     dst = (double *)out->data[0];
 
+    if (s->block_samples > 0 && s->pts == AV_NOPTS_VALUE)
+        drop = 1;
+
     if (s->block_samples == 0) {
         double w1 = s->w1;
         double w2 = s->w2;
@@ -177,6 +184,20 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 
         s->w1 = w1;
         s->w2 = w2;
+    } else if (eof) {
+        const double *src = (const double *)in->data[0];
+        double *ssrc = s->side[1] + s->block_samples;
+        double *msrc = s->mid;
+
+        for (int n = 0; n < out->nb_samples; n++, src += 2, dst += 2) {
+            if (ctx->is_disabled) {
+                dst[0] = src[0];
+                dst[1] = src[1];
+            } else {
+                dst[0] = (msrc[n] + ssrc[n]) * level_out;
+                dst[1] = (msrc[n] - ssrc[n]) * level_out;
+            }
+        }
     } else {
         double *mdst = s->mid + s->block_samples;
         double *sdst = s->side[0] + s->block_samples;
@@ -209,7 +230,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
                        b0, b1, b2, a1, a2,
                        &w1, &w2);
 
-        reverse_samples(s->side[1], s->side[2] + s->block_samples, s->block_samples);
+        reverse_samples(s->side[1], s->side[2], s->block_samples * 2);
 
         src = (const double *)in->data[0];
         ssrc = s->side[1];
@@ -229,9 +250,25 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
                 s->block_samples * sizeof(*s->side[0]));
     }
 
+    if (s->block_samples > 0) {
+        int nb_samples = in->nb_samples;
+        int64_t pts = in->pts;
+
+        out->pts = s->pts;
+        out->nb_samples = s->nb_samples;
+        s->pts = pts;
+        s->nb_samples = nb_samples;
+    }
+
     if (out != in)
         av_frame_free(&in);
-    return ff_filter_frame(outlink, out);
+    if (!drop) {
+        return ff_filter_frame(outlink, out);
+    } else {
+        av_frame_free(&out);
+        ff_filter_set_ready(ctx, 10);
+        return 0;
+    }
 }
 
 static int activate(AVFilterContext *ctx)
@@ -240,6 +277,8 @@ static int activate(AVFilterContext *ctx)
     AVFilterLink *outlink = ctx->outputs[0];
     CrossfeedContext *s = ctx->priv;
     AVFrame *in = NULL;
+    int64_t pts;
+    int status;
     int ret;
 
     FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
@@ -252,14 +291,27 @@ static int activate(AVFilterContext *ctx)
     if (ret < 0)
         return ret;
     if (ret > 0)
-        return filter_frame(inlink, in);
+        return filter_frame(inlink, in, 0);
 
     if (s->block_samples > 0 && ff_inlink_queued_samples(inlink) >= s->block_samples) {
         ff_filter_set_ready(ctx, 10);
         return 0;
     }
 
-    FF_FILTER_FORWARD_STATUS(inlink, outlink);
+    if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
+        if (s->block_samples > 0) {
+            AVFrame *in = ff_get_audio_buffer(outlink, s->block_samples);
+            if (!in)
+                return AVERROR(ENOMEM);
+
+            ret = filter_frame(inlink, in, 1);
+        }
+
+        ff_outlink_set_status(outlink, status, pts);
+
+        return ret;
+    }
+
     FF_FILTER_FORWARD_WANTED(outlink, inlink);
 
     return FFERROR_NOT_READY;



More information about the ffmpeg-cvslog mailing list