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
41 41
42#include "audio.h"42#include "audio.h"
43#include "avfilter.h"43#include "avfilter.h"
44#include "filters.h"
44#include "formats.h"45#include "formats.h"
45#include "internal.h"46#include "internal.h"
46 47
@@ -151,6 +152,7 @@ static int frame_list_add_frame(FrameList *frame_list, int nb_samples, int64_t p · 104 unmodified lines
151 return 0;152 return 0;
152}153}
153 154
155/* FIXME: use directly links fifo */
154 156
155typedef struct MixContext {157typedef struct MixContext {
156 const AVClass *class; /**< class for AVOptions */158 const AVClass *class; /**< class for AVOptions */
@@ -263,21 +265,15 @@ static int config_output(AVFilterLink *outlink) · 106 unmodified lines
263 return 0;265 return 0;
264}266}
265 267
266static int calc_active_inputs(MixContext *s);
267
268/**268/**
269 * Read samples from the input FIFOs, mix, and write to the output link.269 * Read samples from the input FIFOs, mix, and write to the output link.
270 */270 */
271static int output_frame(AVFilterLink *outlink, int need_request)271static int output_frame(AVFilterLink *outlink)
272{272{
273 AVFilterContext *ctx = outlink->src;273 AVFilterContext *ctx = outlink->src;
274 MixContext *s = ctx->priv;274 MixContext *s = ctx->priv;
275 AVFrame *out_buf, *in_buf;275 AVFrame *out_buf, *in_buf;
276 int nb_samples, ns, ret, i;276 int nb_samples, ns, i;
277
278 ret = calc_active_inputs(s);
279 if (ret < 0)
280 return ret;
281 277
282 if (s->input_state[0] & INPUT_ON) {278 if (s->input_state[0] & INPUT_ON) {
283 /* first input live: use the corresponding frame size */279 /* first input live: use the corresponding frame size */
@@ -288,7 +284,7 @@ static int output_frame(AVFilterLink *outlink, int need_request) · 4 unmodified lines
288 if (ns < nb_samples) {284 if (ns < nb_samples) {
289 if (!(s->input_state[i] & INPUT_EOF))285 if (!(s->input_state[i] & INPUT_EOF))
290 /* unclosed input with not enough samples */286 /* unclosed input with not enough samples */
291 return need_request ? ff_request_frame(ctx->inputs[i]) : 0;287 return 0;
292 /* closed input to drain */288 /* closed input to drain */
293 nb_samples = ns;289 nb_samples = ns;
294 }290 }
@@ -303,8 +299,10 @@ static int output_frame(AVFilterLink *outlink, int need_request) · 8 unmodified lines
303 nb_samples = FFMIN(nb_samples, ns);299 nb_samples = FFMIN(nb_samples, ns);
304 }300 }
305 }301 }
306 if (nb_samples == INT_MAX)302 if (nb_samples == INT_MAX) {
307 return AVERROR_EOF;303 ff_outlink_set_status(outlink, AVERROR_EOF, s->next_pts);
304 return 0;
305 }
308 }306 }
309 307
310 s->next_pts = frame_list_next_pts(s->frame_list);308 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
367static int request_samples(AVFilterContext *ctx, int min_samples)365static int request_samples(AVFilterContext *ctx, int min_samples)
368{366{
369 MixContext *s = ctx->priv;367 MixContext *s = ctx->priv;
370 int i, ret;368 int i;
371 369
372 av_assert0(s->nb_inputs > 1);370 av_assert0(s->nb_inputs > 1);
373 371
374 for (i = 1; i < s->nb_inputs; i++) {372 for (i = 1; i < s->nb_inputs; i++) {
375 ret = 0;
376 if (!(s->input_state[i] & INPUT_ON))373 if (!(s->input_state[i] & INPUT_ON))
377 continue;374 continue;
378 if (av_audio_fifo_size(s->fifos[i]) >= min_samples)375 if (av_audio_fifo_size(s->fifos[i]) >= min_samples)
379 continue;376 continue;
380 ret = ff_request_frame(ctx->inputs[i]);377 ff_inlink_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;
389 }378 }
390 return output_frame(ctx->outputs[0], 1);379 return output_frame(ctx->outputs[0]);
391}380}
392 381
393/**382/**
@@ -411,73 +400,87 @@ static int calc_active_inputs(MixContext *s) · 17 unmodified lines
411 return 0;400 return 0;
412}401}
413 402
414static int request_frame(AVFilterLink *outlink)403static int activate(AVFilterContext *ctx)
415{404{
416 AVFilterContext *ctx = outlink->src;405 AVFilterLink *outlink = ctx->outputs[0];
417 MixContext *s = ctx->priv;406 MixContext *s = ctx->priv;
418 int ret;407 AVFrame *buf = NULL;
419 int wanted_samples;408 int i, ret;
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);
439 409
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 }
441 423
442 return request_samples(ctx, wanted_samples);424 ret = av_audio_fifo_write(s->fifos[i], (void **)buf->extended_data,
443}425 buf->nb_samples);
426 if (ret < 0) {
427 av_frame_free(&buf);
428 return ret;
429 }
444 430
445static int filter_frame(AVFilterLink *inlink, AVFrame *buf)431 av_frame_free(&buf);
446{
447 AVFilterContext *ctx = inlink->dst;
448 MixContext *s = ctx->priv;
449 AVFilterLink *outlink = ctx->outputs[0];
450 int i, ret = 0;
451 432
452 for (i = 0; i < ctx->nb_inputs; i++)433 ret = output_frame(outlink);
453 if (ctx->inputs[i] == inlink)434 if (ret < 0)
454 break;435 return ret;
455 if (i >= ctx->nb_inputs) {436 }
456 av_log(ctx, AV_LOG_ERROR, "unknown input link\n");
457 ret = AVERROR(EINVAL);
458 goto fail;
459 }437 }
460 438
461 if (i == 0) {439 for (i = 0; i < s->nb_inputs; i++) {
462 int64_t pts = av_rescale_q(buf->pts, inlink->time_base,440 int64_t pts;
463 outlink->time_base);441 int status;
464 ret = frame_list_add_frame(s->frame_list, buf->nb_samples, pts);442
465 if (ret < 0)443 if (ff_inlink_acknowledge_status(ctx->inputs[i], &status, &pts)) {
466 goto fail;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 }
467 }459 }
468 460
469 ret = av_audio_fifo_write(s->fifos[i], (void **)buf->extended_data,461 if (calc_active_inputs(s)) {
470 buf->nb_samples);462 ff_outlink_set_status(outlink, AVERROR_EOF, s->next_pts);
471 if (ret < 0)463 return 0;
472 goto fail;464 }
473 465
474 av_frame_free(&buf);466 if (ff_outlink_frame_wanted(outlink)) {
475 return output_frame(outlink, 0);467 int wanted_samples;
476 468
477fail:469 if (!(s->input_state[0] & INPUT_ON))
478 av_frame_free(&buf);470 return request_samples(ctx, 1);
479 471
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;
481}484}
482 485
483static av_cold int init(AVFilterContext *ctx)486static av_cold int init(AVFilterContext *ctx)
@@ -494,7 +497,6 @@ static av_cold int init(AVFilterContext *ctx) · 10 unmodified lines
494 pad.name = av_strdup(name);497 pad.name = av_strdup(name);
495 if (!pad.name)498 if (!pad.name)
496 return AVERROR(ENOMEM);499 return AVERROR(ENOMEM);
497 pad.filter_frame = filter_frame;
498 500
499 if ((ret = ff_insert_inpad(ctx, i, &pad)) < 0) {501 if ((ret = ff_insert_inpad(ctx, i, &pad)) < 0) {
500 av_freep(&pad.name);502 av_freep(&pad.name);
@@ -562,7 +564,6 @@ static const AVFilterPad avfilter_af_amix_outputs[] = { · 61 unmodified lines
562 .name = "default",564 .name = "default",
563 .type = AVMEDIA_TYPE_AUDIO,565 .type = AVMEDIA_TYPE_AUDIO,
564 .config_props = config_output,566 .config_props = config_output,
565 .request_frame = request_frame
566 },567 },
567 { NULL }568 { NULL }
568};569};
@@ -574,6 +575,7 @@ AVFilter ff_af_amix = { · 5 unmodified lines
574 .priv_class = &amix_class,575 .priv_class = &amix_class,
575 .init = init,576 .init = init,
576 .uninit = uninit,577 .uninit = uninit,
578 .activate = activate,
577 .query_formats = query_formats,579 .query_formats = query_formats,
578 .inputs = NULL,580 .inputs = NULL,
579 .outputs = avfilter_af_amix_outputs,581 .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