mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
avfilter/f_loop: fix aloop activate logic
The logic did not follow the documented behaviour and that caused skipping of
some audio in the loop and in the leftover buffer.
Example command line which should produce a smooth sine wave for the whole
duration of the output:
ffmpeg -f lavfi -i "sine=r=48000:f=480:d=4" -af "aloop=loop=4:start=48000:size=48000" out.wav
Fixes ticket #11283.
Signed-off-by: Marton Balint <cus@passwd.hu>
(cherry picked from commit fe18ed3f2a
)
This commit is contained in:
parent
ff0f25a154
commit
cde3c5fc0c
@ -21,6 +21,7 @@
|
|||||||
#include "config_components.h"
|
#include "config_components.h"
|
||||||
|
|
||||||
#include "libavutil/audio_fifo.h"
|
#include "libavutil/audio_fifo.h"
|
||||||
|
#include "libavutil/avassert.h"
|
||||||
#include "libavutil/fifo.h"
|
#include "libavutil/fifo.h"
|
||||||
#include "libavutil/internal.h"
|
#include "libavutil/internal.h"
|
||||||
#include "libavutil/opt.h"
|
#include "libavutil/opt.h"
|
||||||
@ -90,7 +91,7 @@ static av_cold void auninit(AVFilterContext *ctx)
|
|||||||
av_audio_fifo_free(s->left);
|
av_audio_fifo_free(s->left);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push_samples(AVFilterContext *ctx, int nb_samples)
|
static int push_samples(AVFilterContext *ctx, int nb_samples, AVFrame **frame)
|
||||||
{
|
{
|
||||||
AVFilterLink *outlink = ctx->outputs[0];
|
AVFilterLink *outlink = ctx->outputs[0];
|
||||||
LoopContext *s = ctx->priv;
|
LoopContext *s = ctx->priv;
|
||||||
@ -112,9 +113,7 @@ static int push_samples(AVFilterContext *ctx, int nb_samples)
|
|||||||
i += out->nb_samples;
|
i += out->nb_samples;
|
||||||
s->current_sample += out->nb_samples;
|
s->current_sample += out->nb_samples;
|
||||||
|
|
||||||
ret = ff_filter_frame(outlink, out);
|
*frame = out;
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (s->current_sample >= s->nb_samples) {
|
if (s->current_sample >= s->nb_samples) {
|
||||||
s->duration = s->pts;
|
s->duration = s->pts;
|
||||||
@ -123,6 +122,8 @@ static int push_samples(AVFilterContext *ctx, int nb_samples)
|
|||||||
if (s->loop > 0)
|
if (s->loop > 0)
|
||||||
s->loop--;
|
s->loop--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -162,10 +163,7 @@ static int afilter_frame(AVFilterLink *inlink, AVFrame *frame)
|
|||||||
s->pts += av_rescale_q(ret, (AVRational){1, outlink->sample_rate}, outlink->time_base);
|
s->pts += av_rescale_q(ret, (AVRational){1, outlink->sample_rate}, outlink->time_base);
|
||||||
ret = ff_filter_frame(outlink, frame);
|
ret = ff_filter_frame(outlink, frame);
|
||||||
} else {
|
} else {
|
||||||
int nb_samples = frame->nb_samples;
|
av_assert0(0);
|
||||||
|
|
||||||
av_frame_free(&frame);
|
|
||||||
ret = push_samples(ctx, nb_samples);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s->ignored_samples += frame->nb_samples;
|
s->ignored_samples += frame->nb_samples;
|
||||||
@ -177,7 +175,7 @@ static int afilter_frame(AVFilterLink *inlink, AVFrame *frame)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int arequest_frame(AVFilterLink *outlink)
|
static int arequest_frame(AVFilterLink *outlink, AVFrame **frame)
|
||||||
{
|
{
|
||||||
AVFilterContext *ctx = outlink->src;
|
AVFilterContext *ctx = outlink->src;
|
||||||
LoopContext *s = ctx->priv;
|
LoopContext *s = ctx->priv;
|
||||||
@ -197,17 +195,11 @@ static int arequest_frame(AVFilterLink *outlink)
|
|||||||
av_audio_fifo_read(s->left, (void **)out->extended_data, nb_samples);
|
av_audio_fifo_read(s->left, (void **)out->extended_data, nb_samples);
|
||||||
out->pts = s->pts;
|
out->pts = s->pts;
|
||||||
s->pts += av_rescale_q(nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base);
|
s->pts += av_rescale_q(nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base);
|
||||||
ret = ff_filter_frame(outlink, out);
|
*frame = out;
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
ret = ff_request_frame(ctx->inputs[0]);
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
ret = push_samples(ctx, 1024);
|
ret = push_samples(ctx, 1024, frame);
|
||||||
}
|
|
||||||
|
|
||||||
if (s->eof && s->nb_samples > 0 && s->loop != 0) {
|
|
||||||
ret = push_samples(ctx, 1024);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -224,33 +216,31 @@ static int aactivate(AVFilterContext *ctx)
|
|||||||
|
|
||||||
FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
|
FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
|
||||||
|
|
||||||
if (!s->eof && (s->nb_samples < s->size || !s->loop || !s->size)) {
|
retry:
|
||||||
ret = ff_inlink_consume_frame(inlink, &frame);
|
ret = arequest_frame(outlink, &frame);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if (ret > 0)
|
if (frame)
|
||||||
return afilter_frame(inlink, frame);
|
return ff_filter_frame(outlink, frame);
|
||||||
}
|
|
||||||
|
|
||||||
if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) {
|
ret = ff_inlink_consume_frame(inlink, &frame);
|
||||||
if (status == AVERROR_EOF) {
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
if (ret > 0)
|
||||||
|
return afilter_frame(inlink, frame);
|
||||||
|
|
||||||
|
ret = ff_inlink_acknowledge_status(inlink, &status, &pts);
|
||||||
|
if (ret) {
|
||||||
|
if (status == AVERROR_EOF && !s->eof) {
|
||||||
s->size = s->nb_samples;
|
s->size = s->nb_samples;
|
||||||
s->eof = 1;
|
s->eof = 1;
|
||||||
|
goto retry;
|
||||||
}
|
}
|
||||||
}
|
ff_outlink_set_status(outlink, status, pts);
|
||||||
|
|
||||||
if (s->eof && (!s->loop || !s->size)) {
|
|
||||||
ff_outlink_set_status(outlink, AVERROR_EOF, s->duration);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s->eof && (!s->size ||
|
FF_FILTER_FORWARD_WANTED(outlink, inlink);
|
||||||
(s->nb_samples < s->size) ||
|
|
||||||
(s->nb_samples >= s->size && s->loop == 0))) {
|
|
||||||
FF_FILTER_FORWARD_WANTED(outlink, inlink);
|
|
||||||
} else if (s->loop && s->nb_samples == s->size) {
|
|
||||||
return arequest_frame(outlink);
|
|
||||||
}
|
|
||||||
|
|
||||||
return FFERROR_NOT_READY;
|
return FFERROR_NOT_READY;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user