History

avfilter/af_amix: switch to activate

Really fixes hangs and infinite loops.

Paul B Mahol committed 9 years ago

Commit 15e9c4a1 parent 473e18f1 file · +82 −80Browse files

Unified · Split

libavfilter/af_amix.c+82−80
@@ -41,6 +41,7 @@ · 40 unmodified lines
4141
4242 #include "audio.h"
4343 #include "avfilter.h"
44+#include "filters.h"
4445 #include "formats.h"
4546 #include "internal.h"
4647
@@ -151,6 +152,7 @@ static int frame_list_add_frame(FrameList *frame_list, int nb_samples, int64_t p · 104 unmodified lines
151152 return 0;
152153 }
153154
155+/* FIXME: use directly links fifo */
154156
155157 typedef struct MixContext {
156158 const AVClass *class; /**< class for AVOptions */
@@ -263,21 +265,15 @@ static int config_output(AVFilterLink *outlink) · 106 unmodified lines
263265 return 0;
264266 }
265267
266−static int calc_active_inputs(MixContext *s);
267−
268268 /**
269269 * Read samples from the input FIFOs, mix, and write to the output link.
270270 */
271−static int output_frame(AVFilterLink *outlink, int need_request)
271+static int output_frame(AVFilterLink *outlink)
272272 {
273273 AVFilterContext *ctx = outlink->src;
274274 MixContext *s = ctx->priv;
275275 AVFrame *out_buf, *in_buf;
276− int nb_samples, ns, ret, i;
277−
278− ret = calc_active_inputs(s);
279− if (ret < 0)
280− return ret;
276+ int nb_samples, ns, i;
281277
282278 if (s->input_state[0] & INPUT_ON) {
283279 /* first input live: use the corresponding frame size */
@@ -288,7 +284,7 @@ static int output_frame(AVFilterLink *outlink, int need_request) · 4 unmodified lines
288284 if (ns < nb_samples) {
289285 if (!(s->input_state[i] & INPUT_EOF))
290286 /* unclosed input with not enough samples */
291− return need_request ? ff_request_frame(ctx->inputs[i]) : 0;
287+ return 0;
292288 /* closed input to drain */
293289 nb_samples = ns;
294290 }
@@ -303,8 +299,10 @@ static int output_frame(AVFilterLink *outlink, int need_request) · 8 unmodified lines
303299 nb_samples = FFMIN(nb_samples, ns);
304300 }
305301 }
306− if (nb_samples == INT_MAX)
307− return AVERROR_EOF;
302+ if (nb_samples == INT_MAX) {
303+ ff_outlink_set_status(outlink, AVERROR_EOF, s->next_pts);
304+ return 0;
305+ }
308306 }
309307
310308 s->next_pts = frame_list_next_pts(s->frame_list);
@@ -367,27 +365,18 @@ static int output_frame(AVFilterLink *outlink, int need_request) · 56 unmodified lines
367365 static int request_samples(AVFilterContext *ctx, int min_samples)
368366 {
369367 MixContext *s = ctx->priv;
370− int i, ret;
368+ int i;
371369
372370 av_assert0(s->nb_inputs > 1);
373371
374372 for (i = 1; i < s->nb_inputs; i++) {
375− ret = 0;
376373 if (!(s->input_state[i] & INPUT_ON))
377374 continue;
378375 if (av_audio_fifo_size(s->fifos[i]) >= min_samples)
379376 continue;
380− ret = ff_request_frame(ctx->inputs[i]);
381− if (ret == AVERROR_EOF) {
382− s->input_state[i] |= INPUT_EOF;
383− if (av_audio_fifo_size(s->fifos[i]) == 0) {
384− s->input_state[i] = 0;
385− continue;
386− }
387− } else if (ret < 0)
388− return ret;
377+ ff_inlink_request_frame(ctx->inputs[i]);
389378 }
390− return output_frame(ctx->outputs[0], 1);
379+ return output_frame(ctx->outputs[0]);
391380 }
392381
393382 /**
@@ -411,73 +400,87 @@ static int calc_active_inputs(MixContext *s) · 17 unmodified lines
411400 return 0;
412401 }
413402
414−static int request_frame(AVFilterLink *outlink)
403+static int activate(AVFilterContext *ctx)
415404 {
416− AVFilterContext *ctx = outlink->src;
417− MixContext *s = ctx->priv;
418− int ret;
419− int wanted_samples;
420−
421− ret = calc_active_inputs(s);
422− if (ret < 0)
423− return ret;
424−
425− if (!(s->input_state[0] & INPUT_ON))
426− return request_samples(ctx, 1);
427−
428− if (s->frame_list->nb_frames == 0) {
429− ret = ff_request_frame(ctx->inputs[0]);
430− if (ret == AVERROR_EOF) {
431− s->input_state[0] = 0;
432− if (s->nb_inputs == 1)
433− return AVERROR_EOF;
434− return output_frame(ctx->outputs[0], 1);
435− }
436− return ret;
437− }
438− av_assert0(s->frame_list->nb_frames > 0);
405+ AVFilterLink *outlink = ctx->outputs[0];
406+ MixContext *s = ctx->priv;
407+ AVFrame *buf = NULL;
408+ int i, ret;
439409
440− wanted_samples = frame_list_next_frame_size(s->frame_list);
410+ for (i = 0; i < s->nb_inputs; i++) {
411+ AVFilterLink *inlink = ctx->inputs[i];
412+
413+ if ((ret = ff_inlink_consume_frame(ctx->inputs[i], &buf)) > 0) {
414+ if (i == 0) {
415+ int64_t pts = av_rescale_q(buf->pts, inlink->time_base,
416+ outlink->time_base);
417+ ret = frame_list_add_frame(s->frame_list, buf->nb_samples, pts);
418+ if (ret < 0) {
419+ av_frame_free(&buf);
420+ return ret;
421+ }
422+ }
441423
442− return request_samples(ctx, wanted_samples);
443−}
424+ ret = av_audio_fifo_write(s->fifos[i], (void **)buf->extended_data,
425+ buf->nb_samples);
426+ if (ret < 0) {
427+ av_frame_free(&buf);
428+ return ret;
429+ }
444430
445−static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
446−{
447− AVFilterContext *ctx = inlink->dst;
448− MixContext *s = ctx->priv;
449− AVFilterLink *outlink = ctx->outputs[0];
450− int i, ret = 0;
431+ av_frame_free(&buf);
451432
452− for (i = 0; i < ctx->nb_inputs; i++)
453− if (ctx->inputs[i] == inlink)
454− break;
455− if (i >= ctx->nb_inputs) {
456− av_log(ctx, AV_LOG_ERROR, "unknown input link\n");
457− ret = AVERROR(EINVAL);
458− goto fail;
433+ ret = output_frame(outlink);
434+ if (ret < 0)
435+ return ret;
436+ }
459437 }
460438
461− if (i == 0) {
462− int64_t pts = av_rescale_q(buf->pts, inlink->time_base,
463− outlink->time_base);
464− ret = frame_list_add_frame(s->frame_list, buf->nb_samples, pts);
465− if (ret < 0)
466− goto fail;
439+ for (i = 0; i < s->nb_inputs; i++) {
440+ int64_t pts;
441+ int status;
442+
443+ if (ff_inlink_acknowledge_status(ctx->inputs[i], &status, &pts)) {
444+ if (status == AVERROR_EOF) {
445+ if (i == 0) {
446+ s->input_state[i] = 0;
447+ if (s->nb_inputs == 1) {
448+ ff_outlink_set_status(outlink, status, pts);
449+ return 0;
450+ }
451+ } else {
452+ s->input_state[i] |= INPUT_EOF;
453+ if (av_audio_fifo_size(s->fifos[i]) == 0) {
454+ s->input_state[i] = 0;
455+ }
456+ }
457+ }
458+ }
467459 }
468460
469− ret = av_audio_fifo_write(s->fifos[i], (void **)buf->extended_data,
470− buf->nb_samples);
471− if (ret < 0)
472− goto fail;
461+ if (calc_active_inputs(s)) {
462+ ff_outlink_set_status(outlink, AVERROR_EOF, s->next_pts);
463+ return 0;
464+ }
473465
474− av_frame_free(&buf);
475− return output_frame(outlink, 0);
466+ if (ff_outlink_frame_wanted(outlink)) {
467+ int wanted_samples;
476468
477−fail:
478− av_frame_free(&buf);
469+ if (!(s->input_state[0] & INPUT_ON))
470+ return request_samples(ctx, 1);
479471
480− return ret;
472+ if (s->frame_list->nb_frames == 0) {
473+ ff_inlink_request_frame(ctx->inputs[0]);
474+ return 0;
475+ }
476+ av_assert0(s->frame_list->nb_frames > 0);
477+
478+ wanted_samples = frame_list_next_frame_size(s->frame_list);
479+
480+ return request_samples(ctx, wanted_samples);
481+ }
482+
483+ return 0;
481484 }
482485
483486 static av_cold int init(AVFilterContext *ctx)
@@ -494,7 +497,6 @@ static av_cold int init(AVFilterContext *ctx) · 10 unmodified lines
494497 pad.name = av_strdup(name);
495498 if (!pad.name)
496499 return AVERROR(ENOMEM);
497− pad.filter_frame = filter_frame;
498500
499501 if ((ret = ff_insert_inpad(ctx, i, &pad)) < 0) {
500502 av_freep(&pad.name);
@@ -562,7 +564,6 @@ static const AVFilterPad avfilter_af_amix_outputs[] = { · 61 unmodified lines
562564 .name = "default",
563565 .type = AVMEDIA_TYPE_AUDIO,
564566 .config_props = config_output,
565− .request_frame = request_frame
566567 },
567568 { NULL }
568569 };
@@ -574,6 +575,7 @@ AVFilter ff_af_amix = { · 5 unmodified lines
574575 .priv_class = &amix_class,
575576 .init = init,
576577 .uninit = uninit,
578+ .activate = activate,
577579 .query_formats = query_formats,
578580 .inputs = NULL,
579581 .outputs = avfilter_af_amix_outputs,

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