aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarton Balint <cus@passwd.hu>2024-11-04 00:43:06 +0100
committerMarton Balint <cus@passwd.hu>2024-11-11 21:56:34 +0100
commitfe18ed3f2a9221af0beaec7b04b7804849db1f2f (patch)
treeae03b0f32f723083089797a055a6885aa5edb14a
parentb33a59416072ad31a5840f33f9975d88acf45add (diff)
downloadffmpeg-fe18ed3f2a9221af0beaec7b04b7804849db1f2f.tar.gz
avfilter/f_loop: fix aloop activate logic
The logic did not follow the documented behaviour and that caused skipping of some audio in the loop and in the leftover buffer. Example command line which should produce a smooth sine wave for the whole duration of the output: ffmpeg -f lavfi -i "sine=r=48000:f=480:d=4" -af "aloop=loop=4:start=48000:size=48000" out.wav Fixes ticket #11283. Signed-off-by: Marton Balint <cus@passwd.hu>
-rw-r--r--libavfilter/f_loop.c70
1 files changed, 28 insertions, 42 deletions
diff --git a/libavfilter/f_loop.c b/libavfilter/f_loop.c
index 3372c77fee..4e5e8d0e79 100644
--- a/libavfilter/f_loop.c
+++ b/libavfilter/f_loop.c
@@ -21,6 +21,7 @@
#include "config_components.h"
#include "libavutil/audio_fifo.h"
+#include "libavutil/avassert.h"
#include "libavutil/internal.h"
#include "libavutil/mem.h"
#include "libavutil/opt.h"
@@ -104,7 +105,7 @@ static av_cold void auninit(AVFilterContext *ctx)
av_audio_fifo_free(s->left);
}
-static int push_samples(AVFilterContext *ctx, int nb_samples)
+static int push_samples(AVFilterContext *ctx, int nb_samples, AVFrame **frame)
{
AVFilterLink *outlink = ctx->outputs[0];
LoopContext *s = ctx->priv;
@@ -126,9 +127,7 @@ static int push_samples(AVFilterContext *ctx, int nb_samples)
i += out->nb_samples;
s->current_sample += out->nb_samples;
- ret = ff_filter_frame(outlink, out);
- if (ret < 0)
- return ret;
+ *frame = out;
if (s->current_sample >= s->nb_samples) {
s->current_sample = 0;
@@ -136,6 +135,8 @@ static int push_samples(AVFilterContext *ctx, int nb_samples)
if (s->loop > 0)
s->loop--;
}
+
+ return 0;
}
return ret;
@@ -182,10 +183,7 @@ static int afilter_frame(AVFilterLink *inlink, AVFrame *frame)
s->pts += av_rescale_q(ret, (AVRational){1, outlink->sample_rate}, outlink->time_base);
ret = ff_filter_frame(outlink, frame);
} else {
- int nb_samples = frame->nb_samples;
-
- av_frame_free(&frame);
- ret = push_samples(ctx, nb_samples);
+ av_assert0(0);
}
} else {
s->ignored_samples += frame->nb_samples;
@@ -197,7 +195,7 @@ static int afilter_frame(AVFilterLink *inlink, AVFrame *frame)
return ret;
}
-static int arequest_frame(AVFilterLink *outlink)
+static int arequest_frame(AVFilterLink *outlink, AVFrame **frame)
{
AVFilterContext *ctx = outlink->src;
LoopContext *s = ctx->priv;
@@ -217,17 +215,11 @@ static int arequest_frame(AVFilterLink *outlink)
av_audio_fifo_read(s->left, (void **)out->extended_data, nb_samples);
out->pts = s->pts;
s->pts += av_rescale_q(nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base);
- ret = ff_filter_frame(outlink, out);
- if (ret < 0)
- return ret;
+ *frame = out;
}
- ret = ff_request_frame(ctx->inputs[0]);
+ return 0;
} else {
- ret = push_samples(ctx, 1024);
- }
-
- if (s->eof && s->nb_samples > 0 && s->loop != 0) {
- ret = push_samples(ctx, 1024);
+ ret = push_samples(ctx, 1024, frame);
}
return ret;
@@ -245,37 +237,31 @@ static int aactivate(AVFilterContext *ctx)
update_time(ctx, inlink->time_base);
- if (!s->eof && (s->nb_samples < s->size || !s->loop || !s->size)) {
- const int in_nb_samples = FFMIN(1024, s->size - s->nb_samples);
- if (in_nb_samples == 0)
- ret = ff_inlink_consume_frame(inlink, &frame);
- else
- ret = ff_inlink_consume_samples(inlink, in_nb_samples, in_nb_samples, &frame);
- if (ret < 0)
- return ret;
- if (ret > 0)
- return afilter_frame(inlink, frame);
- }
+retry:
+ ret = arequest_frame(outlink, &frame);
+ if (ret < 0)
+ return ret;
+ if (frame)
+ return ff_filter_frame(outlink, frame);
- if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &s->eof_pts)) {
- if (status == AVERROR_EOF) {
+ ret = ff_inlink_consume_frame(inlink, &frame);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ return afilter_frame(inlink, frame);
+
+ ret = ff_inlink_acknowledge_status(inlink, &status, &s->eof_pts);
+ if (ret) {
+ if (status == AVERROR_EOF && !s->eof) {
s->size = s->nb_samples;
s->eof = 1;
+ goto retry;
}
- }
-
- if (s->eof && (!s->loop || !s->size)) {
- ff_outlink_set_status(outlink, AVERROR_EOF, s->eof_pts + s->pts_offset);
+ ff_outlink_set_status(outlink, status, s->eof_pts);
return 0;
}
- if (!s->eof && (!s->size ||
- (s->nb_samples < s->size) ||
- (s->nb_samples >= s->size && s->loop == 0))) {
- FF_FILTER_FORWARD_WANTED(outlink, inlink);
- } else if (s->loop && s->nb_samples == s->size) {
- return arequest_frame(outlink);
- }
+ FF_FILTER_FORWARD_WANTED(outlink, inlink);
return FFERROR_NOT_READY;
}