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
21#include "config_components.h"21#include "config_components.h"
22 22
23#include "libavutil/audio_fifo.h"23#include "libavutil/audio_fifo.h"
24#include "libavutil/avassert.h"
24#include "libavutil/internal.h"25#include "libavutil/internal.h"
25#include "libavutil/mem.h"26#include "libavutil/mem.h"
26#include "libavutil/opt.h"27#include "libavutil/opt.h"
@@ -104,7 +105,7 @@ static av_cold void auninit(AVFilterContext *ctx) · 77 unmodified lines
104 av_audio_fifo_free(s->left);105 av_audio_fifo_free(s->left);
105}106}
106 107
107static int push_samples(AVFilterContext *ctx, int nb_samples)108static int push_samples(AVFilterContext *ctx, int nb_samples, AVFrame **frame)
108{109{
109 AVFilterLink *outlink = ctx->outputs[0];110 AVFilterLink *outlink = ctx->outputs[0];
110 LoopContext *s = ctx->priv;111 LoopContext *s = ctx->priv;
@@ -126,9 +127,7 @@ static int push_samples(AVFilterContext *ctx, int nb_samples) · 15 unmodified lines
126 i += out->nb_samples;127 i += out->nb_samples;
127 s->current_sample += out->nb_samples;128 s->current_sample += out->nb_samples;
128 129
129 ret = ff_filter_frame(outlink, out);130 *frame = out;
130 if (ret < 0)
131 return ret;
132 131
133 if (s->current_sample >= s->nb_samples) {132 if (s->current_sample >= s->nb_samples) {
134 s->current_sample = 0;133 s->current_sample = 0;
@@ -136,6 +135,8 @@ static int push_samples(AVFilterContext *ctx, int nb_samples) · 1 unmodified line
136 if (s->loop > 0)135 if (s->loop > 0)
137 s->loop--;136 s->loop--;
138 }137 }
138
139 return 0;
139 }140 }
140 141
141 return ret;142 return ret;
@@ -182,10 +183,7 @@ static int afilter_frame(AVFilterLink *inlink, AVFrame *frame) · 40 unmodified lines
182 s->pts += av_rescale_q(ret, (AVRational){1, outlink->sample_rate}, outlink->time_base);183 s->pts += av_rescale_q(ret, (AVRational){1, outlink->sample_rate}, outlink->time_base);
183 ret = ff_filter_frame(outlink, frame);184 ret = ff_filter_frame(outlink, frame);
184 } else {185 } else {
185 int nb_samples = frame->nb_samples;186 av_assert0(0);
186
187 av_frame_free(&frame);
188 ret = push_samples(ctx, nb_samples);
189 }187 }
190 } else {188 } else {
191 s->ignored_samples += frame->nb_samples;189 s->ignored_samples += frame->nb_samples;
@@ -197,7 +195,7 @@ static int afilter_frame(AVFilterLink *inlink, AVFrame *frame) · 5 unmodified lines
197 return ret;195 return ret;
198}196}
199 197
200static int arequest_frame(AVFilterLink *outlink)198static int arequest_frame(AVFilterLink *outlink, AVFrame **frame)
201{199{
202 AVFilterContext *ctx = outlink->src;200 AVFilterContext *ctx = outlink->src;
203 LoopContext *s = ctx->priv;201 LoopContext *s = ctx->priv;
@@ -217,17 +215,11 @@ static int arequest_frame(AVFilterLink *outlink) · 13 unmodified lines
217 av_audio_fifo_read(s->left, (void **)out->extended_data, nb_samples);215 av_audio_fifo_read(s->left, (void **)out->extended_data, nb_samples);
218 out->pts = s->pts;216 out->pts = s->pts;
219 s->pts += av_rescale_q(nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base);217 s->pts += av_rescale_q(nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base);
220 ret = ff_filter_frame(outlink, out);218 *frame = out;
221 if (ret < 0)
222 return ret;
223 }219 }
224 ret = ff_request_frame(ctx->inputs[0]);220 return 0;
225 } else {221 } else {
226 ret = push_samples(ctx, 1024);222 ret = push_samples(ctx, 1024, frame);
227 }
228
229 if (s->eof && s->nb_samples > 0 && s->loop != 0) {
230 ret = push_samples(ctx, 1024);
231 }223 }
232 224
233 return ret;225 return ret;
@@ -245,37 +237,31 @@ static int aactivate(AVFilterContext *ctx) · 11 unmodified lines
245 237
246 update_time(ctx, inlink->time_base);238 update_time(ctx, inlink->time_base);
247 239
248 if (!s->eof && (s->nb_samples < s->size || !s->loop || !s->size)) {240retry:
249 const int in_nb_samples = FFMIN(1024, s->size - s->nb_samples);241 ret = arequest_frame(outlink, &frame);
250 if (in_nb_samples == 0)242 if (ret < 0)
251 ret = ff_inlink_consume_frame(inlink, &frame);243 return ret;
252 else244 if (frame)
253 ret = ff_inlink_consume_samples(inlink, in_nb_samples, in_nb_samples, &frame);245 return ff_filter_frame(outlink, frame);
254 if (ret < 0)
255 return ret;
256 if (ret > 0)
257 return afilter_frame(inlink, frame);
258 }
259 246
260 if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &s->eof_pts)) {247 ret = ff_inlink_consume_frame(inlink, &frame);
261 if (status == AVERROR_EOF) {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) {
262 s->size = s->nb_samples;256 s->size = s->nb_samples;
263 s->eof = 1;257 s->eof = 1;
258 goto retry;
264 }259 }
265 }260 ff_outlink_set_status(outlink, status, s->eof_pts);
266
267 if (s->eof && (!s->loop || !s->size)) {
268 ff_outlink_set_status(outlink, AVERROR_EOF, s->eof_pts + s->pts_offset);
269 return 0;261 return 0;
270 }262 }
271 263
272 if (!s->eof && (!s->size ||264 FF_FILTER_FORWARD_WANTED(outlink, inlink);
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 }
279 265
280 return FFERROR_NOT_READY;266 return FFERROR_NOT_READY;
281}267}

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