From 8088b5d69c51b9329ccbc6d1125cf55c54ff6374 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 18 Jan 2018 11:17:03 +0100 Subject: [PATCH] avfilter/af_afade: acrossfade: switch to activate Signed-off-by: Paul B Mahol --- libavfilter/af_afade.c | 215 +++++++++++++++++------------------------ 1 file changed, 87 insertions(+), 128 deletions(-) diff --git a/libavfilter/af_afade.c b/libavfilter/af_afade.c index 4d0b31eac7..285b5b6557 100644 --- a/libavfilter/af_afade.c +++ b/libavfilter/af_afade.c @@ -23,10 +23,14 @@ * fade audio filter */ +#define FF_INTERNAL_FIELDS 1 +#include "framequeue.h" + #include "libavutil/audio_fifo.h" #include "libavutil/opt.h" #include "audio.h" #include "avfilter.h" +#include "filters.h" #include "internal.h" typedef struct AudioFadeContext { @@ -39,6 +43,7 @@ typedef struct AudioFadeContext { int64_t start_time; int overlap; int cf0_eof; + int prev_size; int crossfade_is_over; AVAudioFifo *fifo[2]; int64_t pts; @@ -428,157 +433,127 @@ CROSSFADE(flt, float) CROSSFADE(s16, int16_t) CROSSFADE(s32, int32_t) -static int acrossfade_filter_frame(AVFilterLink *inlink, AVFrame *in) +static int activate(AVFilterContext *ctx) { - AVFilterContext *ctx = inlink->dst; AudioFadeContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; - AVFrame *out, *cf[2] = { NULL }; - int ret = 0, nb_samples; + AVFrame *in = NULL, *out, *cf[2] = { NULL }; + int ret = 0, nb_samples, status; + int64_t pts; if (s->crossfade_is_over) { + ret = ff_inlink_consume_frame(ctx->inputs[1], &in); + if (ret < 0) { + return ret; + } else if (ff_inlink_acknowledge_status(ctx->inputs[1], &status, &pts)) { + ff_outlink_set_status(ctx->outputs[0], status, pts); + return 0; + } else { + if (ff_outlink_frame_wanted(ctx->outputs[0]) && !in) { + ff_inlink_request_frame(ctx->inputs[1]); + return 0; + } + } in->pts = s->pts; s->pts += av_rescale_q(in->nb_samples, (AVRational){ 1, outlink->sample_rate }, outlink->time_base); return ff_filter_frame(outlink, in); - } else if (inlink == ctx->inputs[0]) { - av_audio_fifo_write(s->fifo[0], (void **)in->extended_data, in->nb_samples); + } - nb_samples = av_audio_fifo_size(s->fifo[0]) - s->nb_samples; + if (ff_framequeue_queued_samples(&ctx->inputs[0]->fifo) > s->nb_samples) { + nb_samples = ff_framequeue_queued_samples(&ctx->inputs[0]->fifo) - s->nb_samples; if (nb_samples > 0) { - out = ff_get_audio_buffer(outlink, nb_samples); - if (!out) { - ret = AVERROR(ENOMEM); - goto fail; + ret = ff_inlink_consume_samples(ctx->inputs[0], nb_samples, nb_samples, &in); + if (ret < 0) { + return ret; } - av_audio_fifo_read(s->fifo[0], (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); } - } else if (av_audio_fifo_size(s->fifo[1]) < s->nb_samples) { - if (!s->overlap && av_audio_fifo_size(s->fifo[0]) > 0) { - nb_samples = av_audio_fifo_size(s->fifo[0]); - - cf[0] = ff_get_audio_buffer(outlink, nb_samples); - out = ff_get_audio_buffer(outlink, nb_samples); - if (!out || !cf[0]) { - ret = AVERROR(ENOMEM); - goto fail; - } - av_audio_fifo_read(s->fifo[0], (void **)cf[0]->extended_data, nb_samples); - - s->fade_samples(out->extended_data, cf[0]->extended_data, nb_samples, - outlink->channels, -1, nb_samples - 1, nb_samples, s->curve); - 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) - goto fail; - } - - av_audio_fifo_write(s->fifo[1], (void **)in->extended_data, in->nb_samples); - } else if (av_audio_fifo_size(s->fifo[1]) >= s->nb_samples) { - av_audio_fifo_write(s->fifo[1], (void **)in->extended_data, in->nb_samples); - + in->pts = s->pts; + s->pts += av_rescale_q(in->nb_samples, + (AVRational){ 1, outlink->sample_rate }, outlink->time_base); + return ff_filter_frame(outlink, in); + } else if (ff_framequeue_queued_samples(&ctx->inputs[1]->fifo) >= s->nb_samples) { if (s->overlap) { - cf[0] = ff_get_audio_buffer(outlink, s->nb_samples); - cf[1] = ff_get_audio_buffer(outlink, s->nb_samples); out = ff_get_audio_buffer(outlink, s->nb_samples); - if (!out || !cf[0] || !cf[1]) { + if (!out) + return AVERROR(ENOMEM); + + ret = ff_inlink_consume_samples(ctx->inputs[0], s->nb_samples, s->nb_samples, &cf[0]); + if (ret < 0) { av_frame_free(&out); - ret = AVERROR(ENOMEM); - goto fail; + return ret; } - av_audio_fifo_read(s->fifo[0], (void **)cf[0]->extended_data, s->nb_samples); - av_audio_fifo_read(s->fifo[1], (void **)cf[1]->extended_data, s->nb_samples); + ret = ff_inlink_consume_samples(ctx->inputs[1], s->nb_samples, s->nb_samples, &cf[1]); + if (ret < 0) { + av_frame_free(&out); + return ret; + } s->crossfade_samples(out->extended_data, cf[0]->extended_data, cf[1]->extended_data, - s->nb_samples, in->channels, + s->nb_samples, out->channels, s->curve, s->curve2); out->pts = s->pts; s->pts += av_rescale_q(s->nb_samples, (AVRational){ 1, outlink->sample_rate }, outlink->time_base); - ret = ff_filter_frame(outlink, out); - if (ret < 0) - goto fail; + s->crossfade_is_over = 1; + av_frame_free(&cf[0]); + av_frame_free(&cf[1]); + return ff_filter_frame(outlink, out); } else { out = ff_get_audio_buffer(outlink, s->nb_samples); - cf[1] = ff_get_audio_buffer(outlink, s->nb_samples); - if (!out || !cf[1]) { - ret = AVERROR(ENOMEM); + if (!out) + return AVERROR(ENOMEM); + + ret = ff_inlink_consume_samples(ctx->inputs[0], s->nb_samples, s->nb_samples, &cf[0]); + if (ret < 0) { av_frame_free(&out); - goto fail; + return ret; } - av_audio_fifo_read(s->fifo[1], (void **)cf[1]->extended_data, s->nb_samples); + s->fade_samples(out->extended_data, cf[0]->extended_data, s->nb_samples, + outlink->channels, -1, s->nb_samples - 1, s->nb_samples, s->curve); + out->pts = s->pts; + s->pts += av_rescale_q(s->nb_samples, + (AVRational){ 1, outlink->sample_rate }, outlink->time_base); + av_frame_free(&cf[0]); + ret = ff_filter_frame(outlink, out); + if (ret < 0) + return ret; + + out = ff_get_audio_buffer(outlink, s->nb_samples); + if (!out) + return AVERROR(ENOMEM); + + ret = ff_inlink_consume_samples(ctx->inputs[1], s->nb_samples, s->nb_samples, &cf[1]); + if (ret < 0) { + av_frame_free(&out); + return ret; + } s->fade_samples(out->extended_data, cf[1]->extended_data, s->nb_samples, outlink->channels, 1, 0, s->nb_samples, s->curve2); out->pts = s->pts; s->pts += av_rescale_q(s->nb_samples, (AVRational){ 1, outlink->sample_rate }, outlink->time_base); - ret = ff_filter_frame(outlink, out); - if (ret < 0) - goto fail; + s->crossfade_is_over = 1; + av_frame_free(&cf[1]); + return ff_filter_frame(outlink, out); } - - nb_samples = av_audio_fifo_size(s->fifo[1]); - if (nb_samples > 0) { - out = ff_get_audio_buffer(outlink, nb_samples); - if (!out) { - ret = AVERROR(ENOMEM); - goto fail; - } - - av_audio_fifo_read(s->fifo[1], (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); - } - s->crossfade_is_over = 1; - } - -fail: - av_frame_free(&in); - av_frame_free(&cf[0]); - av_frame_free(&cf[1]); - return ret; -} - -static int acrossfade_request_frame(AVFilterLink *outlink) -{ - AVFilterContext *ctx = outlink->src; - AudioFadeContext *s = ctx->priv; - int ret = 0; - - if (!s->cf0_eof) { - AVFilterLink *cf0 = ctx->inputs[0]; - ret = ff_request_frame(cf0); - if (ret < 0 && ret != AVERROR_EOF) - return ret; - if (ret == AVERROR_EOF) { + } else if (ff_outlink_frame_wanted(ctx->outputs[0])) { + if (!s->cf0_eof && ctx->inputs[0]->status_in) { s->cf0_eof = 1; - ret = 0; } - } else { - AVFilterLink *cf1 = ctx->inputs[1]; - int nb_samples = av_audio_fifo_size(s->fifo[1]); - - ret = ff_request_frame(cf1); - if (ret == AVERROR_EOF && nb_samples > 0) { - AVFrame *out = ff_get_audio_buffer(outlink, nb_samples); - if (!out) - return AVERROR(ENOMEM); - - av_audio_fifo_read(s->fifo[1], (void **)out->extended_data, nb_samples); - ret = ff_filter_frame(outlink, out); + if (ctx->inputs[1]->status_in) { + ff_outlink_set_status(ctx->outputs[0], AVERROR_EOF, AV_NOPTS_VALUE); + return 0; } + if (!s->cf0_eof) + ff_inlink_request_frame(ctx->inputs[0]); + else + ff_inlink_request_frame(ctx->inputs[1]); + return 0; } return ret; @@ -615,32 +590,17 @@ static int acrossfade_config_output(AVFilterLink *outlink) config_output(outlink); - s->fifo[0] = av_audio_fifo_alloc(outlink->format, outlink->channels, s->nb_samples); - s->fifo[1] = av_audio_fifo_alloc(outlink->format, outlink->channels, s->nb_samples); - if (!s->fifo[0] || !s->fifo[1]) - return AVERROR(ENOMEM); - return 0; } -static av_cold void uninit(AVFilterContext *ctx) -{ - AudioFadeContext *s = ctx->priv; - - av_audio_fifo_free(s->fifo[0]); - av_audio_fifo_free(s->fifo[1]); -} - static const AVFilterPad avfilter_af_acrossfade_inputs[] = { { .name = "crossfade0", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = acrossfade_filter_frame, }, { .name = "crossfade1", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = acrossfade_filter_frame, }, { NULL } }; @@ -649,7 +609,6 @@ static const AVFilterPad avfilter_af_acrossfade_outputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .request_frame = acrossfade_request_frame, .config_props = acrossfade_config_output, }, { NULL } @@ -660,7 +619,7 @@ AVFilter ff_af_acrossfade = { .description = NULL_IF_CONFIG_SMALL("Cross fade two input audio streams."), .query_formats = query_formats, .priv_size = sizeof(AudioFadeContext), - .uninit = uninit, + .activate = activate, .priv_class = &acrossfade_class, .inputs = avfilter_af_acrossfade_inputs, .outputs = avfilter_af_acrossfade_outputs,