Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: Marton Balint <cus@passwd.hu>
To: ffmpeg-devel@ffmpeg.org
Cc: Marton Balint <cus@passwd.hu>
Subject: [FFmpeg-devel] [PATCH 4/4] avfilter/af_afade: rework crossfade activate logic
Date: Thu, 24 Jul 2025 01:36:00 +0200
Message-ID: <20250723233604.29380-4-cus@passwd.hu> (raw)
In-Reply-To: <20250723233604.29380-1-cus@passwd.hu>

The new logic should be easier to follow.

It also uses ff_inlink_consume_frame() for all simple passthrough operations
making custom get_audio_buffer callback unnecessary.

Fate changes are because the new logic does not repacketize input audio up
until the crossfade. Content is the same.

Signed-off-by: Marton Balint <cus@passwd.hu>
---
 libavfilter/af_afade.c           | 79 +++++++++++++---------------
 tests/ref/fate/filter-acrossfade | 88 ++++++++++++++++----------------
 2 files changed, 80 insertions(+), 87 deletions(-)

diff --git a/libavfilter/af_afade.c b/libavfilter/af_afade.c
index baf972d17d..d4ea1a7bab 100644
--- a/libavfilter/af_afade.c
+++ b/libavfilter/af_afade.c
@@ -42,9 +42,8 @@ typedef struct AudioFadeContext {
     double silence;
     double unity;
     int overlap;
-    int status[2];
-    int passthrough;
     int64_t pts;
+    int xfade_status;
 
     void (*fade_samples)(uint8_t **dst, uint8_t * const *src,
                          int nb_samples, int channels, int direction,
@@ -598,7 +597,6 @@ static int pass_crossfade(AVFilterContext *ctx)
         out->pts = s->pts;
         s->pts += av_rescale_q(s->nb_samples,
             (AVRational){ 1, outlink->sample_rate }, outlink->time_base);
-        s->passthrough = 1;
         av_frame_free(&cf[0]);
         av_frame_free(&cf[1]);
         return ff_filter_frame(outlink, out);
@@ -638,7 +636,6 @@ static int pass_crossfade(AVFilterContext *ctx)
         out->pts = s->pts;
         s->pts += av_rescale_q(s->nb_samples,
             (AVRational){ 1, outlink->sample_rate }, outlink->time_base);
-        s->passthrough = 1;
         av_frame_free(&cf[1]);
         return ff_filter_frame(outlink, out);
     }
@@ -648,42 +645,50 @@ static int activate(AVFilterContext *ctx)
 {
     AudioFadeContext *s   = ctx->priv;
     AVFilterLink *outlink = ctx->outputs[0];
-    int ret = 0, nb_samples;
 
     FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx);
 
-    if (s->passthrough && s->status[0]) {
+    // Read first input until EOF
+    if (s->xfade_status == 0) {
+        int queued_samples = ff_inlink_queued_samples(ctx->inputs[0]);
+        if (queued_samples > s->nb_samples) {
+            AVFrame *frame = ff_inlink_peek_frame(ctx->inputs[0], 0);
+            if (queued_samples - s->nb_samples >= frame->nb_samples)
+                return pass_frame(ctx->inputs[0], outlink, &s->pts);
+        }
+        if (ff_outlink_get_status(ctx->inputs[0])) {
+            if (queued_samples > s->nb_samples)
+                return pass_samples(ctx->inputs[0], outlink, queued_samples - s->nb_samples, &s->pts);
+            s->xfade_status = 1;
+        } else {
+            FF_FILTER_FORWARD_WANTED(outlink, ctx->inputs[0]);
+        }
+    }
+    // Read second input until enough data is ready or EOF
+    if (s->xfade_status == 1) {
+        if (ff_inlink_queued_samples(ctx->inputs[1]) >= s->nb_samples || ff_outlink_get_status(ctx->inputs[1])) {
+            s->xfade_status = 2;
+        } else {
+            FF_FILTER_FORWARD_WANTED(outlink, ctx->inputs[1]);
+        }
+    }
+    // Do crossfade
+    if (s->xfade_status == 2) {
+        s->xfade_status = 3;
+        // TODO: Do some partial crossfade if not all inputs have enough duration?
+        if (ff_inlink_queued_samples(ctx->inputs[0]) >= s->nb_samples &&
+            ff_inlink_queued_samples(ctx->inputs[1]) >= s->nb_samples)
+            return pass_crossfade(ctx);
+    }
+    // Read second input until EOF
+    if (s->xfade_status == 3) {
         if (ff_inlink_queued_frames(ctx->inputs[1]))
             return pass_frame(ctx->inputs[1], outlink, &s->pts);
         FF_FILTER_FORWARD_STATUS(ctx->inputs[1], outlink);
         FF_FILTER_FORWARD_WANTED(outlink, ctx->inputs[1]);
     }
 
-    nb_samples = ff_inlink_queued_samples(ctx->inputs[0]);
-    if (nb_samples  > s->nb_samples) {
-        nb_samples -= s->nb_samples;
-        s->passthrough = 1;
-        return pass_samples(ctx->inputs[0], outlink, nb_samples, &s->pts);
-    } else if (s->status[0] && nb_samples >= s->nb_samples &&
-               ff_inlink_queued_samples(ctx->inputs[1]) >= s->nb_samples) {
-        return pass_crossfade(ctx);
-    } else if (ff_outlink_frame_wanted(outlink)) {
-        if (!s->status[0] && ff_outlink_get_status(ctx->inputs[0]))
-            s->status[0] = AVERROR_EOF;
-        s->passthrough = !s->status[0];
-        if (ff_outlink_get_status(ctx->inputs[1])) {
-            s->status[1] = AVERROR_EOF;
-            ff_outlink_set_status(outlink, AVERROR_EOF, AV_NOPTS_VALUE);
-            return 0;
-        }
-        if (!s->status[0])
-            ff_inlink_request_frame(ctx->inputs[0]);
-        else
-            ff_inlink_request_frame(ctx->inputs[1]);
-        return 0;
-    }
-
-    return ret;
+    return FFERROR_NOT_READY;
 }
 
 static int acrossfade_config_output(AVFilterLink *outlink)
@@ -709,26 +714,14 @@ static int acrossfade_config_output(AVFilterLink *outlink)
     return 0;
 }
 
-static AVFrame *get_audio_buffer(AVFilterLink *inlink, int nb_samples)
-{
-    AVFilterContext *ctx = inlink->dst;
-    AudioFadeContext *s = ctx->priv;
-
-    return s->passthrough ?
-        ff_null_get_audio_buffer   (inlink, nb_samples) :
-        ff_default_get_audio_buffer(inlink, nb_samples);
-}
-
 static const AVFilterPad avfilter_af_acrossfade_inputs[] = {
     {
         .name         = "crossfade0",
         .type         = AVMEDIA_TYPE_AUDIO,
-        .get_buffer.audio = get_audio_buffer,
     },
     {
         .name         = "crossfade1",
         .type         = AVMEDIA_TYPE_AUDIO,
-        .get_buffer.audio = get_audio_buffer,
     },
 };
 
diff --git a/tests/ref/fate/filter-acrossfade b/tests/ref/fate/filter-acrossfade
index f80aa10b55..92231bec7d 100644
--- a/tests/ref/fate/filter-acrossfade
+++ b/tests/ref/fate/filter-acrossfade
@@ -3,50 +3,50 @@
 #codec_id 0: pcm_s16le
 #sample_rate 0: 44100
 #channel_layout_name 0: stereo
-0,          0,          0,     1912,     7648, 0x1294dd84
-0,       1912,       1912,     4096,    16384, 0x8d5eec9b
-0,       6008,       6008,     4096,    16384, 0x9f15e8a9
-0,      10104,      10104,     4096,    16384, 0x5594dd9d
-0,      14200,      14200,     4096,    16384, 0x5115d9bb
-0,      18296,      18296,     4096,    16384, 0x0511d717
-0,      22392,      22392,     4096,    16384, 0x9cbdd713
-0,      26488,      26488,     4096,    16384, 0x2f13e615
-0,      30584,      30584,     4096,    16384, 0x415ae9f7
-0,      34680,      34680,     4096,    16384, 0x8d5eec9b
-0,      38776,      38776,     4096,    16384, 0x9f15e8a9
-0,      42872,      42872,     4096,    16384, 0xd9809dcd
-0,      46968,      46968,     4096,    16384, 0x7b60ec15
-0,      51064,      51064,     4096,    16384, 0xe92de3eb
-0,      55160,      55160,     4096,    16384, 0x063d2c76
-0,      59256,      59256,     4096,    16384, 0xacbed331
-0,      63352,      63352,     4096,    16384, 0x1137d0c7
-0,      67448,      67448,     4096,    16384, 0xafbad1d7
-0,      71544,      71544,     4096,    16384, 0xb2a0040c
-0,      75640,      75640,     4096,    16384, 0x83222d0c
-0,      79736,      79736,     4096,    16384, 0x97993592
-0,      83832,      83832,     4096,    16384, 0x9e4200b2
-0,      87928,      87928,     4096,    16384, 0xf24c2685
-0,      92024,      92024,     4096,    16384, 0x0b23a4c8
-0,      96120,      96120,     4096,    16384, 0x9105fcde
-0,     100216,     100216,     4096,    16384, 0xd4b64a6f
-0,     104312,     104312,     4096,    16384, 0xef56c48a
-0,     108408,     108408,     4096,    16384, 0xb12b9599
-0,     112504,     112504,     4096,    16384, 0x18bbeefd
-0,     116600,     116600,     4096,    16384, 0x3fe2d14b
-0,     120696,     120696,     4096,    16384, 0xf6d6fdff
-0,     124792,     124792,     4096,    16384, 0x2e538447
-0,     128888,     128888,     4096,    16384, 0xd8251663
-0,     132984,     132984,     4096,    16384, 0xd783c943
-0,     137080,     137080,     4096,    16384, 0x3d64f7cf
-0,     141176,     141176,     4096,    16384, 0x80e2c034
-0,     145272,     145272,     4096,    16384, 0x69a7e254
-0,     149368,     149368,     4096,    16384, 0xb3f5efb9
-0,     153464,     153464,     4096,    16384, 0x3975dea3
-0,     157560,     157560,     4096,    16384, 0x7ff7d2c5
-0,     161656,     161656,     4096,    16384, 0x5476e599
-0,     165752,     165752,     4096,    16384, 0x30e4f37a
-0,     169848,     169848,     4096,    16384, 0x57c1a83c
-0,     173944,     173944,     2456,     9824, 0x498532b3
+0,          0,          0,     4096,    16384, 0x02ebe66b
+0,       4096,       4096,     4096,    16384, 0x35bfe081
+0,       8192,       8192,     4096,    16384, 0x3f90e0a9
+0,      12288,      12288,     4096,    16384, 0xd389dc43
+0,      16384,      16384,     4096,    16384, 0x9d5add49
+0,      20480,      20480,     4096,    16384, 0x378ee333
+0,      24576,      24576,     4096,    16384, 0xabf6df0f
+0,      28672,      28672,     4096,    16384, 0xedefe76f
+0,      32768,      32768,     4096,    16384, 0x02ebe66b
+0,      36864,      36864,     4096,    16384, 0x35bfe081
+0,      40960,      40960,     4096,    16384, 0xdbc2b3b9
+0,      45056,      45056,     4096,    16384, 0xe92bd835
+0,      49152,      49152,     4096,    16384, 0x1126dca3
+0,      53248,      53248,     4096,    16384, 0x9647edcf
+0,      57344,      57344,     4096,    16384, 0x5cc345aa
+0,      61440,      61440,     4096,    16384, 0x19d7bd51
+0,      65536,      65536,     4096,    16384, 0x19eccef7
+0,      69632,      69632,     4096,    16384, 0x4b68eeed
+0,      73728,      73728,     4096,    16384, 0x0b3d1bfc
+0,      77824,      77824,     4096,    16384, 0xe9b2e069
+0,      81920,      81920,     4096,    16384, 0xcaa5590e
+0,      86016,      86016,     4096,    16384, 0x47d0b227
+0,      90112,      90112,     4096,    16384, 0x446ba7a4
+0,      94208,      94208,     4096,    16384, 0x299b2e17
+0,      98304,      98304,     4096,    16384, 0xc51affa2
+0,     102400,     102400,     4096,    16384, 0xb4970fcf
+0,     106496,     106496,     4096,    16384, 0xe48af9fc
+0,     110592,     110592,     4096,    16384, 0xc2beffbb
+0,     114688,     114688,     4096,    16384, 0xb9d99627
+0,     118784,     118784,     4096,    16384, 0xb65a2086
+0,     122880,     122880,     4096,    16384, 0x6386714b
+0,     126976,     126976,     4096,    16384, 0x92a3171e
+0,     131072,     131072,     4096,    16384, 0x78bad1e2
+0,     135168,     135168,     4096,    16384, 0x63301330
+0,     139264,     139264,     4096,    16384, 0xd663b943
+0,     143360,     143360,     4096,    16384, 0xdcafe377
+0,     147456,     147456,     4096,    16384, 0xfb2cd701
+0,     151552,     151552,     4096,    16384, 0x91c30201
+0,     155648,     155648,     4096,    16384, 0xf23da341
+0,     159744,     159744,     4096,    16384, 0xe8d5fa0a
+0,     163840,     163840,     4096,    16384, 0x519bdfef
+0,     167936,     167936,     4096,    16384, 0xf2fcd803
+0,     172032,     172032,     4096,    16384, 0xd5ceccbc
+0,     176128,     176128,      272,     1088, 0xa8bc282b
 0,     176400,     176400,    88200,   352800, 0x4fb492af
 0,     264600,     264600,     1912,     7648, 0xf0c93a5a
 0,     266512,     266512,     4096,    16384, 0x85454449
-- 
2.43.0

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

      parent reply	other threads:[~2025-07-23 23:36 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-23 23:35 [FFmpeg-devel] [PATCH 1/4] avfilter/trim: consume all available frames and avoid activate reschedule Marton Balint
2025-07-23 23:35 ` [FFmpeg-devel] [PATCH 2/4] avfilter/af_afade: factorize functions generating frames Marton Balint
2025-07-23 23:35 ` [FFmpeg-devel] [PATCH 3/4] avfilter/af_afade: fix check_input for empty streams Marton Balint
2025-07-23 23:36 ` Marton Balint [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250723233604.29380-4-cus@passwd.hu \
    --to=cus@passwd.hu \
    --cc=ffmpeg-devel@ffmpeg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git