avfilter/af_silenceremove: avoid returning 1 sample duration frames

This commit is contained in:
Paul B Mahol 2021-09-08 15:15:19 +02:00
parent 3b331468da
commit 8a42ee6697
1 changed files with 38 additions and 18 deletions

View File

@ -23,6 +23,7 @@
#include <float.h> /* DBL_MAX */ #include <float.h> /* DBL_MAX */
#include "libavutil/audio_fifo.h"
#include "libavutil/avassert.h" #include "libavutil/avassert.h"
#include "libavutil/opt.h" #include "libavutil/opt.h"
#include "libavutil/timestamp.h" #include "libavutil/timestamp.h"
@ -103,6 +104,8 @@ typedef struct SilenceRemoveContext {
double (*compute)(struct SilenceRemoveContext *s, AVFrame *frame, int ch, int offset); double (*compute)(struct SilenceRemoveContext *s, AVFrame *frame, int ch, int offset);
void (*copy)(struct SilenceRemoveContext *s, AVFrame *out, AVFrame *in, void (*copy)(struct SilenceRemoveContext *s, AVFrame *out, AVFrame *in,
int ch, int out_offset, int in_offset); int ch, int out_offset, int in_offset);
AVAudioFifo *fifo;
} SilenceRemoveContext; } SilenceRemoveContext;
#define OFFSET(x) offsetof(SilenceRemoveContext, x) #define OFFSET(x) offsetof(SilenceRemoveContext, x)
@ -542,12 +545,16 @@ static int config_input(AVFilterLink *inlink)
return AVERROR_BUG; return AVERROR_BUG;
} }
s->fifo = av_audio_fifo_alloc(inlink->format, inlink->channels, 1024);
if (!s->fifo)
return AVERROR(ENOMEM);
return 0; return 0;
} }
static void flush(SilenceRemoveContext *s, static void flush(SilenceRemoveContext *s,
AVFrame *out, AVFilterLink *outlink, AVFrame *out, AVFilterLink *outlink,
int *nb_samples_written, int *ret, int flush_silence) int *nb_samples_written, int flush_silence)
{ {
AVFrame *silence; AVFrame *silence;
@ -559,22 +566,18 @@ static void flush(SilenceRemoveContext *s,
(AVRational){1, outlink->sample_rate}, (AVRational){1, outlink->sample_rate},
outlink->time_base); outlink->time_base);
*ret = ff_filter_frame(outlink, out); av_audio_fifo_write(s->fifo, (void **)out->extended_data, out->nb_samples);
if (*ret < 0)
return;
*nb_samples_written = 0; *nb_samples_written = 0;
} else {
av_frame_free(&out);
} }
av_frame_free(&out);
if (s->stop_silence_end <= 0 || !flush_silence) if (s->stop_silence_end <= 0 || !flush_silence)
return; return;
silence = ff_get_audio_buffer(outlink, s->stop_silence_end); silence = ff_get_audio_buffer(outlink, s->stop_silence_end);
if (!silence) { if (!silence)
*ret = AVERROR(ENOMEM);
return; return;
}
if (s->stop_silence_offset < s->stop_silence_end) { if (s->stop_silence_offset < s->stop_silence_end) {
av_samples_copy(silence->extended_data, s->stop_silence_hold->extended_data, 0, av_samples_copy(silence->extended_data, s->stop_silence_hold->extended_data, 0,
@ -598,7 +601,8 @@ static void flush(SilenceRemoveContext *s,
(AVRational){1, outlink->sample_rate}, (AVRational){1, outlink->sample_rate},
outlink->time_base); outlink->time_base);
*ret = ff_filter_frame(outlink, silence); av_audio_fifo_write(s->fifo, (void **)silence->extended_data, silence->nb_samples);
av_frame_free(&silence);
} }
static int filter_frame(AVFilterLink *inlink, AVFrame *in) static int filter_frame(AVFilterLink *inlink, AVFrame *in)
@ -727,7 +731,8 @@ silence_trim_flush:
s->start_holdoff_offset += nbs; s->start_holdoff_offset += nbs;
ret = ff_filter_frame(outlink, out); av_audio_fifo_write(s->fifo, (void **)out->extended_data, out->nb_samples);
av_frame_free(&out);
if (s->start_holdoff_offset == s->start_holdoff_end) { if (s->start_holdoff_offset == s->start_holdoff_end) {
s->start_holdoff_offset = 0; s->start_holdoff_offset = 0;
@ -771,7 +776,7 @@ silence_copy:
if (threshold && s->stop_holdoff_end && !s->stop_silence) { if (threshold && s->stop_holdoff_end && !s->stop_silence) {
s->mode = SILENCE_COPY_FLUSH; s->mode = SILENCE_COPY_FLUSH;
flush(s, out, outlink, &nb_samples_written, &ret, 0); flush(s, out, outlink, &nb_samples_written, 0);
goto silence_copy_flush; goto silence_copy_flush;
} else if (threshold) { } else if (threshold) {
for (j = 0; j < outlink->channels; j++) { for (j = 0; j < outlink->channels; j++) {
@ -812,7 +817,7 @@ silence_copy:
if (!s->restart) { if (!s->restart) {
s->mode = SILENCE_STOP; s->mode = SILENCE_STOP;
flush(s, out, outlink, &nb_samples_written, &ret, 1); flush(s, out, outlink, &nb_samples_written, 1);
goto silence_stop; goto silence_stop;
} else { } else {
s->stop_found_periods = 0; s->stop_found_periods = 0;
@ -823,17 +828,17 @@ silence_copy:
s->start_silence_end = 0; s->start_silence_end = 0;
clear_window(s); clear_window(s);
s->mode = SILENCE_TRIM; s->mode = SILENCE_TRIM;
flush(s, out, outlink, &nb_samples_written, &ret, 1); flush(s, out, outlink, &nb_samples_written, 1);
goto silence_trim; goto silence_trim;
} }
} }
s->mode = SILENCE_COPY_FLUSH; s->mode = SILENCE_COPY_FLUSH;
flush(s, out, outlink, &nb_samples_written, &ret, 0); flush(s, out, outlink, &nb_samples_written, 0);
goto silence_copy_flush; goto silence_copy_flush;
} }
} }
} }
flush(s, out, outlink, &nb_samples_written, &ret, 0); flush(s, out, outlink, &nb_samples_written, 0);
} else { } else {
av_samples_copy(out->extended_data, in->extended_data, av_samples_copy(out->extended_data, in->extended_data,
nb_samples_written, nb_samples_written,
@ -845,7 +850,8 @@ silence_copy:
(AVRational){1, outlink->sample_rate}, (AVRational){1, outlink->sample_rate},
outlink->time_base); outlink->time_base);
ret = ff_filter_frame(outlink, out); av_audio_fifo_write(s->fifo, (void **)out->extended_data, out->nb_samples);
av_frame_free(&out);
} }
break; break;
@ -872,7 +878,8 @@ silence_copy_flush:
(AVRational){1, outlink->sample_rate}, (AVRational){1, outlink->sample_rate},
outlink->time_base); outlink->time_base);
ret = ff_filter_frame(outlink, out); av_audio_fifo_write(s->fifo, (void **)out->extended_data, out->nb_samples);
av_frame_free(&out);
if (s->stop_holdoff_offset == s->stop_holdoff_end) { if (s->stop_holdoff_offset == s->stop_holdoff_end) {
s->stop_holdoff_offset = 0; s->stop_holdoff_offset = 0;
@ -892,6 +899,16 @@ silence_stop:
av_frame_free(&in); av_frame_free(&in);
if (av_audio_fifo_size(s->fifo) > 0) {
out = ff_get_audio_buffer(outlink, av_audio_fifo_size(s->fifo));
if (!out)
return AVERROR(ENOMEM);
av_audio_fifo_read(s->fifo, (void **)out->extended_data, out->nb_samples);
out->pts = s->next_pts;
ret = ff_filter_frame(outlink, out);
}
return ret; return ret;
} }
@ -955,6 +972,9 @@ static av_cold void uninit(AVFilterContext *ctx)
av_frame_free(&s->stop_holdoff); av_frame_free(&s->stop_holdoff);
av_frame_free(&s->stop_silence_hold); av_frame_free(&s->stop_silence_hold);
av_frame_free(&s->window); av_frame_free(&s->window);
av_audio_fifo_free(s->fifo);
s->fifo = NULL;
} }
static const AVFilterPad silenceremove_inputs[] = { static const AVFilterPad silenceremove_inputs[] = {