You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-04 22:03:09 +02:00
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. Signed-off-by: Marton Balint <cus@passwd.hu>
This commit is contained in:
@ -42,9 +42,8 @@ typedef struct AudioFadeContext {
|
|||||||
double silence;
|
double silence;
|
||||||
double unity;
|
double unity;
|
||||||
int overlap;
|
int overlap;
|
||||||
int status[2];
|
|
||||||
int passthrough;
|
|
||||||
int64_t pts;
|
int64_t pts;
|
||||||
|
int xfade_status;
|
||||||
|
|
||||||
void (*fade_samples)(uint8_t **dst, uint8_t * const *src,
|
void (*fade_samples)(uint8_t **dst, uint8_t * const *src,
|
||||||
int nb_samples, int channels, int direction,
|
int nb_samples, int channels, int direction,
|
||||||
@ -598,7 +597,6 @@ static int pass_crossfade(AVFilterContext *ctx)
|
|||||||
out->pts = s->pts;
|
out->pts = s->pts;
|
||||||
s->pts += av_rescale_q(s->nb_samples,
|
s->pts += av_rescale_q(s->nb_samples,
|
||||||
(AVRational){ 1, outlink->sample_rate }, outlink->time_base);
|
(AVRational){ 1, outlink->sample_rate }, outlink->time_base);
|
||||||
s->passthrough = 1;
|
|
||||||
av_frame_free(&cf[0]);
|
av_frame_free(&cf[0]);
|
||||||
av_frame_free(&cf[1]);
|
av_frame_free(&cf[1]);
|
||||||
return ff_filter_frame(outlink, out);
|
return ff_filter_frame(outlink, out);
|
||||||
@ -638,7 +636,6 @@ static int pass_crossfade(AVFilterContext *ctx)
|
|||||||
out->pts = s->pts;
|
out->pts = s->pts;
|
||||||
s->pts += av_rescale_q(s->nb_samples,
|
s->pts += av_rescale_q(s->nb_samples,
|
||||||
(AVRational){ 1, outlink->sample_rate }, outlink->time_base);
|
(AVRational){ 1, outlink->sample_rate }, outlink->time_base);
|
||||||
s->passthrough = 1;
|
|
||||||
av_frame_free(&cf[1]);
|
av_frame_free(&cf[1]);
|
||||||
return ff_filter_frame(outlink, out);
|
return ff_filter_frame(outlink, out);
|
||||||
}
|
}
|
||||||
@ -648,42 +645,50 @@ static int activate(AVFilterContext *ctx)
|
|||||||
{
|
{
|
||||||
AudioFadeContext *s = ctx->priv;
|
AudioFadeContext *s = ctx->priv;
|
||||||
AVFilterLink *outlink = ctx->outputs[0];
|
AVFilterLink *outlink = ctx->outputs[0];
|
||||||
int ret = 0, nb_samples;
|
|
||||||
|
|
||||||
FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx);
|
FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx);
|
||||||
|
|
||||||
if (s->passthrough && s->status[0]) {
|
// Read first input until EOF
|
||||||
|
if (s->xfade_status == 0) {
|
||||||
|
int queued_samples = ff_inlink_queued_samples(ctx->inputs[0]);
|
||||||
|
if (queued_samples > s->nb_samples) {
|
||||||
|
AVFrame *frame = ff_inlink_peek_frame(ctx->inputs[0], 0);
|
||||||
|
if (queued_samples - s->nb_samples >= frame->nb_samples)
|
||||||
|
return pass_frame(ctx->inputs[0], outlink, &s->pts);
|
||||||
|
}
|
||||||
|
if (ff_outlink_get_status(ctx->inputs[0])) {
|
||||||
|
if (queued_samples > s->nb_samples)
|
||||||
|
return pass_samples(ctx->inputs[0], outlink, queued_samples - s->nb_samples, &s->pts);
|
||||||
|
s->xfade_status = 1;
|
||||||
|
} else {
|
||||||
|
FF_FILTER_FORWARD_WANTED(outlink, ctx->inputs[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Read second input until enough data is ready or EOF
|
||||||
|
if (s->xfade_status == 1) {
|
||||||
|
if (ff_inlink_queued_samples(ctx->inputs[1]) >= s->nb_samples || ff_outlink_get_status(ctx->inputs[1])) {
|
||||||
|
s->xfade_status = 2;
|
||||||
|
} else {
|
||||||
|
FF_FILTER_FORWARD_WANTED(outlink, ctx->inputs[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Do crossfade
|
||||||
|
if (s->xfade_status == 2) {
|
||||||
|
s->xfade_status = 3;
|
||||||
|
// TODO: Do some partial crossfade if not all inputs have enough duration?
|
||||||
|
if (ff_inlink_queued_samples(ctx->inputs[0]) >= s->nb_samples &&
|
||||||
|
ff_inlink_queued_samples(ctx->inputs[1]) >= s->nb_samples)
|
||||||
|
return pass_crossfade(ctx);
|
||||||
|
}
|
||||||
|
// Read second input until EOF
|
||||||
|
if (s->xfade_status == 3) {
|
||||||
if (ff_inlink_queued_frames(ctx->inputs[1]))
|
if (ff_inlink_queued_frames(ctx->inputs[1]))
|
||||||
return pass_frame(ctx->inputs[1], outlink, &s->pts);
|
return pass_frame(ctx->inputs[1], outlink, &s->pts);
|
||||||
FF_FILTER_FORWARD_STATUS(ctx->inputs[1], outlink);
|
FF_FILTER_FORWARD_STATUS(ctx->inputs[1], outlink);
|
||||||
FF_FILTER_FORWARD_WANTED(outlink, ctx->inputs[1]);
|
FF_FILTER_FORWARD_WANTED(outlink, ctx->inputs[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
nb_samples = ff_inlink_queued_samples(ctx->inputs[0]);
|
return FFERROR_NOT_READY;
|
||||||
if (nb_samples > s->nb_samples) {
|
|
||||||
nb_samples -= s->nb_samples;
|
|
||||||
s->passthrough = 1;
|
|
||||||
return pass_samples(ctx->inputs[0], outlink, nb_samples, &s->pts);
|
|
||||||
} else if (s->status[0] && nb_samples >= s->nb_samples &&
|
|
||||||
ff_inlink_queued_samples(ctx->inputs[1]) >= s->nb_samples) {
|
|
||||||
return pass_crossfade(ctx);
|
|
||||||
} else if (ff_outlink_frame_wanted(outlink)) {
|
|
||||||
if (!s->status[0] && ff_outlink_get_status(ctx->inputs[0]))
|
|
||||||
s->status[0] = AVERROR_EOF;
|
|
||||||
s->passthrough = !s->status[0];
|
|
||||||
if (ff_outlink_get_status(ctx->inputs[1])) {
|
|
||||||
s->status[1] = AVERROR_EOF;
|
|
||||||
ff_outlink_set_status(outlink, AVERROR_EOF, AV_NOPTS_VALUE);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!s->status[0])
|
|
||||||
ff_inlink_request_frame(ctx->inputs[0]);
|
|
||||||
else
|
|
||||||
ff_inlink_request_frame(ctx->inputs[1]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int acrossfade_config_output(AVFilterLink *outlink)
|
static int acrossfade_config_output(AVFilterLink *outlink)
|
||||||
@ -709,26 +714,14 @@ static int acrossfade_config_output(AVFilterLink *outlink)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static AVFrame *get_audio_buffer(AVFilterLink *inlink, int nb_samples)
|
|
||||||
{
|
|
||||||
AVFilterContext *ctx = inlink->dst;
|
|
||||||
AudioFadeContext *s = ctx->priv;
|
|
||||||
|
|
||||||
return s->passthrough ?
|
|
||||||
ff_null_get_audio_buffer (inlink, nb_samples) :
|
|
||||||
ff_default_get_audio_buffer(inlink, nb_samples);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const AVFilterPad avfilter_af_acrossfade_inputs[] = {
|
static const AVFilterPad avfilter_af_acrossfade_inputs[] = {
|
||||||
{
|
{
|
||||||
.name = "crossfade0",
|
.name = "crossfade0",
|
||||||
.type = AVMEDIA_TYPE_AUDIO,
|
.type = AVMEDIA_TYPE_AUDIO,
|
||||||
.get_buffer.audio = get_audio_buffer,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "crossfade1",
|
.name = "crossfade1",
|
||||||
.type = AVMEDIA_TYPE_AUDIO,
|
.type = AVMEDIA_TYPE_AUDIO,
|
||||||
.get_buffer.audio = get_audio_buffer,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,50 +3,50 @@
|
|||||||
#codec_id 0: pcm_s16le
|
#codec_id 0: pcm_s16le
|
||||||
#sample_rate 0: 44100
|
#sample_rate 0: 44100
|
||||||
#channel_layout_name 0: stereo
|
#channel_layout_name 0: stereo
|
||||||
0, 0, 0, 1912, 7648, 0x1294dd84
|
0, 0, 0, 4096, 16384, 0x02ebe66b
|
||||||
0, 1912, 1912, 4096, 16384, 0x8d5eec9b
|
0, 4096, 4096, 4096, 16384, 0x35bfe081
|
||||||
0, 6008, 6008, 4096, 16384, 0x9f15e8a9
|
0, 8192, 8192, 4096, 16384, 0x3f90e0a9
|
||||||
0, 10104, 10104, 4096, 16384, 0x5594dd9d
|
0, 12288, 12288, 4096, 16384, 0xd389dc43
|
||||||
0, 14200, 14200, 4096, 16384, 0x5115d9bb
|
0, 16384, 16384, 4096, 16384, 0x9d5add49
|
||||||
0, 18296, 18296, 4096, 16384, 0x0511d717
|
0, 20480, 20480, 4096, 16384, 0x378ee333
|
||||||
0, 22392, 22392, 4096, 16384, 0x9cbdd713
|
0, 24576, 24576, 4096, 16384, 0xabf6df0f
|
||||||
0, 26488, 26488, 4096, 16384, 0x2f13e615
|
0, 28672, 28672, 4096, 16384, 0xedefe76f
|
||||||
0, 30584, 30584, 4096, 16384, 0x415ae9f7
|
0, 32768, 32768, 4096, 16384, 0x02ebe66b
|
||||||
0, 34680, 34680, 4096, 16384, 0x8d5eec9b
|
0, 36864, 36864, 4096, 16384, 0x35bfe081
|
||||||
0, 38776, 38776, 4096, 16384, 0x9f15e8a9
|
0, 40960, 40960, 4096, 16384, 0xdbc2b3b9
|
||||||
0, 42872, 42872, 4096, 16384, 0xd9809dcd
|
0, 45056, 45056, 4096, 16384, 0xe92bd835
|
||||||
0, 46968, 46968, 4096, 16384, 0x7b60ec15
|
0, 49152, 49152, 4096, 16384, 0x1126dca3
|
||||||
0, 51064, 51064, 4096, 16384, 0xe92de3eb
|
0, 53248, 53248, 4096, 16384, 0x9647edcf
|
||||||
0, 55160, 55160, 4096, 16384, 0x063d2c76
|
0, 57344, 57344, 4096, 16384, 0x5cc345aa
|
||||||
0, 59256, 59256, 4096, 16384, 0xacbed331
|
0, 61440, 61440, 4096, 16384, 0x19d7bd51
|
||||||
0, 63352, 63352, 4096, 16384, 0x1137d0c7
|
0, 65536, 65536, 4096, 16384, 0x19eccef7
|
||||||
0, 67448, 67448, 4096, 16384, 0xafbad1d7
|
0, 69632, 69632, 4096, 16384, 0x4b68eeed
|
||||||
0, 71544, 71544, 4096, 16384, 0xb2a0040c
|
0, 73728, 73728, 4096, 16384, 0x0b3d1bfc
|
||||||
0, 75640, 75640, 4096, 16384, 0x83222d0c
|
0, 77824, 77824, 4096, 16384, 0xe9b2e069
|
||||||
0, 79736, 79736, 4096, 16384, 0x97993592
|
0, 81920, 81920, 4096, 16384, 0xcaa5590e
|
||||||
0, 83832, 83832, 4096, 16384, 0x9e4200b2
|
0, 86016, 86016, 4096, 16384, 0x47d0b227
|
||||||
0, 87928, 87928, 4096, 16384, 0xf24c2685
|
0, 90112, 90112, 4096, 16384, 0x446ba7a4
|
||||||
0, 92024, 92024, 4096, 16384, 0x0b23a4c8
|
0, 94208, 94208, 4096, 16384, 0x299b2e17
|
||||||
0, 96120, 96120, 4096, 16384, 0x9105fcde
|
0, 98304, 98304, 4096, 16384, 0xc51affa2
|
||||||
0, 100216, 100216, 4096, 16384, 0xd4b64a6f
|
0, 102400, 102400, 4096, 16384, 0xb4970fcf
|
||||||
0, 104312, 104312, 4096, 16384, 0xef56c48a
|
0, 106496, 106496, 4096, 16384, 0xe48af9fc
|
||||||
0, 108408, 108408, 4096, 16384, 0xb12b9599
|
0, 110592, 110592, 4096, 16384, 0xc2beffbb
|
||||||
0, 112504, 112504, 4096, 16384, 0x18bbeefd
|
0, 114688, 114688, 4096, 16384, 0xb9d99627
|
||||||
0, 116600, 116600, 4096, 16384, 0x3fe2d14b
|
0, 118784, 118784, 4096, 16384, 0xb65a2086
|
||||||
0, 120696, 120696, 4096, 16384, 0xf6d6fdff
|
0, 122880, 122880, 4096, 16384, 0x6386714b
|
||||||
0, 124792, 124792, 4096, 16384, 0x2e538447
|
0, 126976, 126976, 4096, 16384, 0x92a3171e
|
||||||
0, 128888, 128888, 4096, 16384, 0xd8251663
|
0, 131072, 131072, 4096, 16384, 0x78bad1e2
|
||||||
0, 132984, 132984, 4096, 16384, 0xd783c943
|
0, 135168, 135168, 4096, 16384, 0x63301330
|
||||||
0, 137080, 137080, 4096, 16384, 0x3d64f7cf
|
0, 139264, 139264, 4096, 16384, 0xd663b943
|
||||||
0, 141176, 141176, 4096, 16384, 0x80e2c034
|
0, 143360, 143360, 4096, 16384, 0xdcafe377
|
||||||
0, 145272, 145272, 4096, 16384, 0x69a7e254
|
0, 147456, 147456, 4096, 16384, 0xfb2cd701
|
||||||
0, 149368, 149368, 4096, 16384, 0xb3f5efb9
|
0, 151552, 151552, 4096, 16384, 0x91c30201
|
||||||
0, 153464, 153464, 4096, 16384, 0x3975dea3
|
0, 155648, 155648, 4096, 16384, 0xf23da341
|
||||||
0, 157560, 157560, 4096, 16384, 0x7ff7d2c5
|
0, 159744, 159744, 4096, 16384, 0xe8d5fa0a
|
||||||
0, 161656, 161656, 4096, 16384, 0x5476e599
|
0, 163840, 163840, 4096, 16384, 0x519bdfef
|
||||||
0, 165752, 165752, 4096, 16384, 0x30e4f37a
|
0, 167936, 167936, 4096, 16384, 0xf2fcd803
|
||||||
0, 169848, 169848, 4096, 16384, 0x57c1a83c
|
0, 172032, 172032, 4096, 16384, 0xd5ceccbc
|
||||||
0, 173944, 173944, 2456, 9824, 0x498532b3
|
0, 176128, 176128, 272, 1088, 0xa8bc282b
|
||||||
0, 176400, 176400, 88200, 352800, 0x4fb492af
|
0, 176400, 176400, 88200, 352800, 0x4fb492af
|
||||||
0, 264600, 264600, 1912, 7648, 0xf0c93a5a
|
0, 264600, 264600, 1912, 7648, 0xf0c93a5a
|
||||||
0, 266512, 266512, 4096, 16384, 0x85454449
|
0, 266512, 266512, 4096, 16384, 0x85454449
|
||||||
|
Reference in New Issue
Block a user