History

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.

Marton Balint committed 2 years ago

Commit fe18ed31 parent b33a5941 file · +28 −42Browse files

Unified · Split

libavfilter/f_loop.c+28−42
@@ -21,6 +21,7 @@ · 20 unmodified lines
2121 #include "config_components.h"
2222
2323 #include "libavutil/audio_fifo.h"
24+#include "libavutil/avassert.h"
2425 #include "libavutil/internal.h"
2526 #include "libavutil/mem.h"
2627 #include "libavutil/opt.h"
@@ -104,7 +105,7 @@ static av_cold void auninit(AVFilterContext *ctx) · 77 unmodified lines
104105 av_audio_fifo_free(s->left);
105106 }
106107
107−static int push_samples(AVFilterContext *ctx, int nb_samples)
108+static int push_samples(AVFilterContext *ctx, int nb_samples, AVFrame **frame)
108109 {
109110 AVFilterLink *outlink = ctx->outputs[0];
110111 LoopContext *s = ctx->priv;
@@ -126,9 +127,7 @@ static int push_samples(AVFilterContext *ctx, int nb_samples) · 15 unmodified lines
126127 i += out->nb_samples;
127128 s->current_sample += out->nb_samples;
128129
129− ret = ff_filter_frame(outlink, out);
130− if (ret < 0)
131− return ret;
130+ *frame = out;
132131
133132 if (s->current_sample >= s->nb_samples) {
134133 s->current_sample = 0;
@@ -136,6 +135,8 @@ static int push_samples(AVFilterContext *ctx, int nb_samples) · 1 unmodified line
136135 if (s->loop > 0)
137136 s->loop--;
138137 }
138+
139+ return 0;
139140 }
140141
141142 return ret;
@@ -182,10 +183,7 @@ static int afilter_frame(AVFilterLink *inlink, AVFrame *frame) · 40 unmodified lines
182183 s->pts += av_rescale_q(ret, (AVRational){1, outlink->sample_rate}, outlink->time_base);
183184 ret = ff_filter_frame(outlink, frame);
184185 } else {
185− int nb_samples = frame->nb_samples;
186−
187− av_frame_free(&frame);
188− ret = push_samples(ctx, nb_samples);
186+ av_assert0(0);
189187 }
190188 } else {
191189 s->ignored_samples += frame->nb_samples;
@@ -197,7 +195,7 @@ static int afilter_frame(AVFilterLink *inlink, AVFrame *frame) · 5 unmodified lines
197195 return ret;
198196 }
199197
200−static int arequest_frame(AVFilterLink *outlink)
198+static int arequest_frame(AVFilterLink *outlink, AVFrame **frame)
201199 {
202200 AVFilterContext *ctx = outlink->src;
203201 LoopContext *s = ctx->priv;
@@ -217,17 +215,11 @@ static int arequest_frame(AVFilterLink *outlink) · 13 unmodified lines
217215 av_audio_fifo_read(s->left, (void **)out->extended_data, nb_samples);
218216 out->pts = s->pts;
219217 s->pts += av_rescale_q(nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base);
220− ret = ff_filter_frame(outlink, out);
221− if (ret < 0)
222− return ret;
218+ *frame = out;
223219 }
224− ret = ff_request_frame(ctx->inputs[0]);
220+ return 0;
225221 } else {
226− ret = push_samples(ctx, 1024);
227− }
228−
229− if (s->eof && s->nb_samples > 0 && s->loop != 0) {
230− ret = push_samples(ctx, 1024);
222+ ret = push_samples(ctx, 1024, frame);
231223 }
232224
233225 return ret;
@@ -245,37 +237,31 @@ static int aactivate(AVFilterContext *ctx) · 11 unmodified lines
245237
246238 update_time(ctx, inlink->time_base);
247239
248− if (!s->eof && (s->nb_samples < s->size || !s->loop || !s->size)) {
249− const int in_nb_samples = FFMIN(1024, s->size - s->nb_samples);
250− if (in_nb_samples == 0)
251− ret = ff_inlink_consume_frame(inlink, &frame);
252− else
253− ret = ff_inlink_consume_samples(inlink, in_nb_samples, in_nb_samples, &frame);
254− if (ret < 0)
255− return ret;
256− if (ret > 0)
257− return afilter_frame(inlink, frame);
258− }
240+retry:
241+ ret = arequest_frame(outlink, &frame);
242+ if (ret < 0)
243+ return ret;
244+ if (frame)
245+ return ff_filter_frame(outlink, frame);
259246
260− if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &s->eof_pts)) {
261− if (status == AVERROR_EOF) {
247+ ret = ff_inlink_consume_frame(inlink, &frame);
248+ if (ret < 0)
249+ return ret;
250+ if (ret > 0)
251+ return afilter_frame(inlink, frame);
252+
253+ ret = ff_inlink_acknowledge_status(inlink, &status, &s->eof_pts);
254+ if (ret) {
255+ if (status == AVERROR_EOF && !s->eof) {
262256 s->size = s->nb_samples;
263257 s->eof = 1;
258+ goto retry;
264259 }
265− }
266−
267− if (s->eof && (!s->loop || !s->size)) {
268− ff_outlink_set_status(outlink, AVERROR_EOF, s->eof_pts + s->pts_offset);
260+ ff_outlink_set_status(outlink, status, s->eof_pts);
269261 return 0;
270262 }
271263
272− if (!s->eof && (!s->size ||
273− (s->nb_samples < s->size) ||
274− (s->nb_samples >= s->size && s->loop == 0))) {
275− FF_FILTER_FORWARD_WANTED(outlink, inlink);
276− } else if (s->loop && s->nb_samples == s->size) {
277− return arequest_frame(outlink);
278− }
264+ FF_FILTER_FORWARD_WANTED(outlink, inlink);
279265
280266 return FFERROR_NOT_READY;
281267 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t