History

avfilter/af_afade: rework crossfade activate logic

The new logic should be easier to follow. It also uses ff_inlink_consume_frame() for all simple passthrough operations making custom get_audio_buffer callback unnecessary. Fate changes are because the new logic does not repacketize input audio up until the crossfade. Content is the same.

Marton Balint committed 1 year ago

Commit 0cc46f11 parent 84d831e2 files · +80 −87Browse files

Showing the changes to libavfilter (1 of 2 files). Show all

Unified · Split

libavfilter/af_afade.c+36−43
@@ -42,9 +42,8 @@ typedef struct AudioFadeContext { · 41 unmodified lines
42 double silence;42 double silence;
43 double unity;43 double unity;
44 int overlap;44 int overlap;
45 int status[2];
46 int passthrough;
47 int64_t pts;45 int64_t pts;
46 int xfade_status;
48 47
49 void (*fade_samples)(uint8_t **dst, uint8_t * const *src,48 void (*fade_samples)(uint8_t **dst, uint8_t * const *src,
50 int nb_samples, int channels, int direction,49 int nb_samples, int channels, int direction,
@@ -598,7 +597,6 @@ static int pass_crossfade(AVFilterContext *ctx) · 547 unmodified lines
598 out->pts = s->pts;597 out->pts = s->pts;
599 s->pts += av_rescale_q(s->nb_samples,598 s->pts += av_rescale_q(s->nb_samples,
600 (AVRational){ 1, outlink->sample_rate }, outlink->time_base);599 (AVRational){ 1, outlink->sample_rate }, outlink->time_base);
601 s->passthrough = 1;
602 av_frame_free(&cf[0]);600 av_frame_free(&cf[0]);
603 av_frame_free(&cf[1]);601 av_frame_free(&cf[1]);
604 return ff_filter_frame(outlink, out);602 return ff_filter_frame(outlink, out);
@@ -638,7 +636,6 @@ static int pass_crossfade(AVFilterContext *ctx) · 33 unmodified lines
638 out->pts = s->pts;636 out->pts = s->pts;
639 s->pts += av_rescale_q(s->nb_samples,637 s->pts += av_rescale_q(s->nb_samples,
640 (AVRational){ 1, outlink->sample_rate }, outlink->time_base);638 (AVRational){ 1, outlink->sample_rate }, outlink->time_base);
641 s->passthrough = 1;
642 av_frame_free(&cf[1]);639 av_frame_free(&cf[1]);
643 return ff_filter_frame(outlink, out);640 return ff_filter_frame(outlink, out);
644 }641 }
@@ -648,42 +645,50 @@ static int activate(AVFilterContext *ctx) · 3 unmodified lines
648{645{
649 AudioFadeContext *s = ctx->priv;646 AudioFadeContext *s = ctx->priv;
650 AVFilterLink *outlink = ctx->outputs[0];647 AVFilterLink *outlink = ctx->outputs[0];
651 int ret = 0, nb_samples;
652 648
653 FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx);649 FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx);
654 650
655 if (s->passthrough && s->status[0]) {651 // Read first input until EOF
652 if (s->xfade_status == 0) {
653 int queued_samples = ff_inlink_queued_samples(ctx->inputs[0]);
654 if (queued_samples > s->nb_samples) {
655 AVFrame *frame = ff_inlink_peek_frame(ctx->inputs[0], 0);
656 if (queued_samples - s->nb_samples >= frame->nb_samples)
657 return pass_frame(ctx->inputs[0], outlink, &s->pts);
658 }
659 if (ff_outlink_get_status(ctx->inputs[0])) {
660 if (queued_samples > s->nb_samples)
661 return pass_samples(ctx->inputs[0], outlink, queued_samples - s->nb_samples, &s->pts);
662 s->xfade_status = 1;
663 } else {
664 FF_FILTER_FORWARD_WANTED(outlink, ctx->inputs[0]);
665 }
666 }
667 // Read second input until enough data is ready or EOF
668 if (s->xfade_status == 1) {
669 if (ff_inlink_queued_samples(ctx->inputs[1]) >= s->nb_samples || ff_outlink_get_status(ctx->inputs[1])) {
670 s->xfade_status = 2;
671 } else {
672 FF_FILTER_FORWARD_WANTED(outlink, ctx->inputs[1]);
673 }
674 }
675 // Do crossfade
676 if (s->xfade_status == 2) {
677 s->xfade_status = 3;
678 // TODO: Do some partial crossfade if not all inputs have enough duration?
679 if (ff_inlink_queued_samples(ctx->inputs[0]) >= s->nb_samples &&
680 ff_inlink_queued_samples(ctx->inputs[1]) >= s->nb_samples)
681 return pass_crossfade(ctx);
682 }
683 // Read second input until EOF
684 if (s->xfade_status == 3) {
656 if (ff_inlink_queued_frames(ctx->inputs[1]))685 if (ff_inlink_queued_frames(ctx->inputs[1]))
657 return pass_frame(ctx->inputs[1], outlink, &s->pts);686 return pass_frame(ctx->inputs[1], outlink, &s->pts);
658 FF_FILTER_FORWARD_STATUS(ctx->inputs[1], outlink);687 FF_FILTER_FORWARD_STATUS(ctx->inputs[1], outlink);
659 FF_FILTER_FORWARD_WANTED(outlink, ctx->inputs[1]);688 FF_FILTER_FORWARD_WANTED(outlink, ctx->inputs[1]);
660 }689 }
661 690
662 nb_samples = ff_inlink_queued_samples(ctx->inputs[0]);691 return FFERROR_NOT_READY;
663 if (nb_samples > s->nb_samples) {
664 nb_samples -= s->nb_samples;
665 s->passthrough = 1;
666 return pass_samples(ctx->inputs[0], outlink, nb_samples, &s->pts);
667 } else if (s->status[0] && nb_samples >= s->nb_samples &&
668 ff_inlink_queued_samples(ctx->inputs[1]) >= s->nb_samples) {
669 return pass_crossfade(ctx);
670 } else if (ff_outlink_frame_wanted(outlink)) {
671 if (!s->status[0] && ff_outlink_get_status(ctx->inputs[0]))
672 s->status[0] = AVERROR_EOF;
673 s->passthrough = !s->status[0];
674 if (ff_outlink_get_status(ctx->inputs[1])) {
675 s->status[1] = AVERROR_EOF;
676 ff_outlink_set_status(outlink, AVERROR_EOF, AV_NOPTS_VALUE);
677 return 0;
678 }
679 if (!s->status[0])
680 ff_inlink_request_frame(ctx->inputs[0]);
681 else
682 ff_inlink_request_frame(ctx->inputs[1]);
683 return 0;
684 }
685
686 return ret;
687}692}
688 693
689static int acrossfade_config_output(AVFilterLink *outlink)694static int acrossfade_config_output(AVFilterLink *outlink)
@@ -709,26 +714,14 @@ static int acrossfade_config_output(AVFilterLink *outlink) · 19 unmodified lines
709 return 0;714 return 0;
710}715}
711 716
712static AVFrame *get_audio_buffer(AVFilterLink *inlink, int nb_samples)
713{
714 AVFilterContext *ctx = inlink->dst;
715 AudioFadeContext *s = ctx->priv;
716
717 return s->passthrough ?
718 ff_null_get_audio_buffer (inlink, nb_samples) :
719 ff_default_get_audio_buffer(inlink, nb_samples);
720}
721
722static const AVFilterPad avfilter_af_acrossfade_inputs[] = {717static const AVFilterPad avfilter_af_acrossfade_inputs[] = {
723 {718 {
724 .name = "crossfade0",719 .name = "crossfade0",
725 .type = AVMEDIA_TYPE_AUDIO,720 .type = AVMEDIA_TYPE_AUDIO,
726 .get_buffer.audio = get_audio_buffer,
727 },721 },
728 {722 {
729 .name = "crossfade1",723 .name = "crossfade1",
730 .type = AVMEDIA_TYPE_AUDIO,724 .type = AVMEDIA_TYPE_AUDIO,
731 .get_buffer.audio = get_audio_buffer,
732 },725 },
733};726};
734 727

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