lavfi: remove af_asynts filter

Long overdue for removal, af_aresample should be used instead.

Signed-off-by: Rostislav Pehlivanov <atomnuker@gmail.com>
This commit is contained in:
Rostislav Pehlivanov 2017-03-06 02:46:51 +00:00 committed by Rostislav Pehlivanov
parent d7896e9b42
commit a8fe8d6b4a
8 changed files with 2 additions and 367 deletions

View File

@ -2,6 +2,7 @@ Entries are sorted chronologically from oldest to youngest within each release,
releases are sorted from youngest to oldest. releases are sorted from youngest to oldest.
version <next>: version <next>:
- Removed asyncts filter (use af_aresample instead)
- CrystalHD decoder moved to new decode API - CrystalHD decoder moved to new decode API
- add internal ebur128 library, remove external libebur128 dependency - add internal ebur128 library, remove external libebur128 dependency
- Pro-MPEG CoP #3-R2 FEC protocol - Pro-MPEG CoP #3-R2 FEC protocol

2
configure vendored
View File

@ -3076,7 +3076,6 @@ afftfilt_filter_select="fft"
amovie_filter_deps="avcodec avformat" amovie_filter_deps="avcodec avformat"
aresample_filter_deps="swresample" aresample_filter_deps="swresample"
ass_filter_deps="libass" ass_filter_deps="libass"
asyncts_filter_deps="avresample"
atempo_filter_deps="avcodec" atempo_filter_deps="avcodec"
atempo_filter_select="rdft" atempo_filter_select="rdft"
azmq_filter_deps="libzmq" azmq_filter_deps="libzmq"
@ -6459,7 +6458,6 @@ enabled zlib && add_cppflags -DZLIB_CONST
enabled afftfilt_filter && prepend avfilter_deps "avcodec" enabled afftfilt_filter && prepend avfilter_deps "avcodec"
enabled amovie_filter && prepend avfilter_deps "avformat avcodec" enabled amovie_filter && prepend avfilter_deps "avformat avcodec"
enabled aresample_filter && prepend avfilter_deps "swresample" enabled aresample_filter && prepend avfilter_deps "swresample"
enabled asyncts_filter && prepend avfilter_deps "avresample"
enabled atempo_filter && prepend avfilter_deps "avcodec" enabled atempo_filter && prepend avfilter_deps "avcodec"
enabled cover_rect_filter && prepend avfilter_deps "avformat avcodec" enabled cover_rect_filter && prepend avfilter_deps "avformat avcodec"
enabled ebur128_filter && enabled swresample && prepend avfilter_deps "swresample" enabled ebur128_filter && enabled swresample && prepend avfilter_deps "swresample"

View File

@ -1642,39 +1642,6 @@ Number of occasions (not the number of samples) that the signal attained either
Overall bit depth of audio. Number of bits used for each sample. Overall bit depth of audio. Number of bits used for each sample.
@end table @end table
@section asyncts
Synchronize audio data with timestamps by squeezing/stretching it and/or
dropping samples/adding silence when needed.
This filter is not built by default, please use @ref{aresample} to do squeezing/stretching.
It accepts the following parameters:
@table @option
@item compensate
Enable stretching/squeezing the data to make it match the timestamps. Disabled
by default. When disabled, time gaps are covered with silence.
@item min_delta
The minimum difference between timestamps and audio data (in seconds) to trigger
adding/dropping samples. The default value is 0.1. If you get an imperfect
sync with this filter, try setting this parameter to 0.
@item max_comp
The maximum compensation in samples per second. Only relevant with compensate=1.
The default value is 500.
@item first_pts
Assume that the first PTS should be this value. The time base is 1 / sample
rate. This allows for padding/trimming at the start of the stream. By default,
no assumption is made about the first frame's expected PTS, so no padding or
trimming is done. For example, this could be set to 0 to pad the beginning with
silence if an audio stream starts after the video stream or to trim any samples
with a negative PTS due to encoder delay.
@end table
@section atempo @section atempo
Adjust audio tempo. Adjust audio tempo.

View File

@ -67,7 +67,6 @@ OBJS-$(CONFIG_ASIDEDATA_FILTER) += f_sidedata.o
OBJS-$(CONFIG_ASPLIT_FILTER) += split.o OBJS-$(CONFIG_ASPLIT_FILTER) += split.o
OBJS-$(CONFIG_ASTATS_FILTER) += af_astats.o OBJS-$(CONFIG_ASTATS_FILTER) += af_astats.o
OBJS-$(CONFIG_ASTREAMSELECT_FILTER) += f_streamselect.o OBJS-$(CONFIG_ASTREAMSELECT_FILTER) += f_streamselect.o
OBJS-$(CONFIG_ASYNCTS_FILTER) += af_asyncts.o
OBJS-$(CONFIG_ATEMPO_FILTER) += af_atempo.o OBJS-$(CONFIG_ATEMPO_FILTER) += af_atempo.o
OBJS-$(CONFIG_ATRIM_FILTER) += trim.o OBJS-$(CONFIG_ATRIM_FILTER) += trim.o
OBJS-$(CONFIG_AZMQ_FILTER) += f_zmq.o OBJS-$(CONFIG_AZMQ_FILTER) += f_zmq.o

View File

@ -1,323 +0,0 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdint.h>
#include "libavresample/avresample.h"
#include "libavutil/attributes.h"
#include "libavutil/audio_fifo.h"
#include "libavutil/common.h"
#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
#include "libavutil/samplefmt.h"
#include "audio.h"
#include "avfilter.h"
#include "internal.h"
typedef struct ASyncContext {
const AVClass *class;
AVAudioResampleContext *avr;
int64_t pts; ///< timestamp in samples of the first sample in fifo
int min_delta; ///< pad/trim min threshold in samples
int first_frame; ///< 1 until filter_frame() has processed at least 1 frame with a pts != AV_NOPTS_VALUE
int64_t first_pts; ///< user-specified first expected pts, in samples
int comp; ///< current resample compensation
/* options */
int resample;
float min_delta_sec;
int max_comp;
/* set by filter_frame() to signal an output frame to request_frame() */
int got_output;
} ASyncContext;
#define OFFSET(x) offsetof(ASyncContext, x)
#define A AV_OPT_FLAG_AUDIO_PARAM
#define F AV_OPT_FLAG_FILTERING_PARAM
static const AVOption asyncts_options[] = {
{ "compensate", "Stretch/squeeze the data to make it match the timestamps", OFFSET(resample), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, A|F },
{ "min_delta", "Minimum difference between timestamps and audio data "
"(in seconds) to trigger padding/trimmin the data.", OFFSET(min_delta_sec), AV_OPT_TYPE_FLOAT, { .dbl = 0.1 }, 0, INT_MAX, A|F },
{ "max_comp", "Maximum compensation in samples per second.", OFFSET(max_comp), AV_OPT_TYPE_INT, { .i64 = 500 }, 0, INT_MAX, A|F },
{ "first_pts", "Assume the first pts should be this value.", OFFSET(first_pts), AV_OPT_TYPE_INT64, { .i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, A|F },
{ NULL }
};
AVFILTER_DEFINE_CLASS(asyncts);
static av_cold int init(AVFilterContext *ctx)
{
ASyncContext *s = ctx->priv;
s->pts = AV_NOPTS_VALUE;
s->first_frame = 1;
return 0;
}
static av_cold void uninit(AVFilterContext *ctx)
{
ASyncContext *s = ctx->priv;
if (s->avr) {
avresample_close(s->avr);
avresample_free(&s->avr);
}
}
static int config_props(AVFilterLink *link)
{
ASyncContext *s = link->src->priv;
int ret;
s->min_delta = s->min_delta_sec * link->sample_rate;
link->time_base = (AVRational){1, link->sample_rate};
s->avr = avresample_alloc_context();
if (!s->avr)
return AVERROR(ENOMEM);
av_opt_set_int(s->avr, "in_channel_layout", link->channel_layout, 0);
av_opt_set_int(s->avr, "out_channel_layout", link->channel_layout, 0);
av_opt_set_int(s->avr, "in_sample_fmt", link->format, 0);
av_opt_set_int(s->avr, "out_sample_fmt", link->format, 0);
av_opt_set_int(s->avr, "in_sample_rate", link->sample_rate, 0);
av_opt_set_int(s->avr, "out_sample_rate", link->sample_rate, 0);
if (s->resample)
av_opt_set_int(s->avr, "force_resampling", 1, 0);
if ((ret = avresample_open(s->avr)) < 0)
return ret;
return 0;
}
/* get amount of data currently buffered, in samples */
static int64_t get_delay(ASyncContext *s)
{
return avresample_available(s->avr) + avresample_get_delay(s->avr);
}
static void handle_trimming(AVFilterContext *ctx)
{
ASyncContext *s = ctx->priv;
if (s->pts < s->first_pts) {
int delta = FFMIN(s->first_pts - s->pts, avresample_available(s->avr));
av_log(ctx, AV_LOG_VERBOSE, "Trimming %d samples from start\n",
delta);
avresample_read(s->avr, NULL, delta);
s->pts += delta;
} else if (s->first_frame)
s->pts = s->first_pts;
}
static int request_frame(AVFilterLink *link)
{
AVFilterContext *ctx = link->src;
ASyncContext *s = ctx->priv;
int ret = 0;
int nb_samples;
s->got_output = 0;
ret = ff_request_frame(ctx->inputs[0]);
/* flush the fifo */
if (ret == AVERROR_EOF) {
if (s->first_pts != AV_NOPTS_VALUE)
handle_trimming(ctx);
if (nb_samples = get_delay(s)) {
AVFrame *buf = ff_get_audio_buffer(link, nb_samples);
if (!buf)
return AVERROR(ENOMEM);
ret = avresample_convert(s->avr, buf->extended_data,
buf->linesize[0], nb_samples, NULL, 0, 0);
if (ret <= 0) {
av_frame_free(&buf);
return (ret < 0) ? ret : AVERROR_EOF;
}
buf->pts = s->pts;
return ff_filter_frame(link, buf);
}
}
return ret;
}
static int write_to_fifo(ASyncContext *s, AVFrame *buf)
{
int ret = avresample_convert(s->avr, NULL, 0, 0, buf->extended_data,
buf->linesize[0], buf->nb_samples);
av_frame_free(&buf);
return ret;
}
static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
{
AVFilterContext *ctx = inlink->dst;
ASyncContext *s = ctx->priv;
AVFilterLink *outlink = ctx->outputs[0];
int nb_channels = av_get_channel_layout_nb_channels(buf->channel_layout);
int64_t pts = (buf->pts == AV_NOPTS_VALUE) ? buf->pts :
av_rescale_q(buf->pts, inlink->time_base, outlink->time_base);
int out_size, ret;
int64_t delta;
int64_t new_pts;
/* buffer data until we get the next timestamp */
if (s->pts == AV_NOPTS_VALUE || pts == AV_NOPTS_VALUE) {
if (pts != AV_NOPTS_VALUE) {
s->pts = pts - get_delay(s);
}
return write_to_fifo(s, buf);
}
if (s->first_pts != AV_NOPTS_VALUE) {
handle_trimming(ctx);
if (!avresample_available(s->avr))
return write_to_fifo(s, buf);
}
/* when we have two timestamps, compute how many samples would we have
* to add/remove to get proper sync between data and timestamps */
delta = pts - s->pts - get_delay(s);
out_size = avresample_available(s->avr);
if (llabs(delta) > s->min_delta ||
(s->first_frame && delta && s->first_pts != AV_NOPTS_VALUE)) {
av_log(ctx, AV_LOG_VERBOSE, "Discontinuity - %"PRId64" samples.\n", delta);
out_size = av_clipl_int32((int64_t)out_size + delta);
} else {
if (s->resample) {
// adjust the compensation if delta is non-zero
int delay = get_delay(s);
int comp = s->comp + av_clip(delta * inlink->sample_rate / delay,
-s->max_comp, s->max_comp);
if (comp != s->comp) {
av_log(ctx, AV_LOG_VERBOSE, "Compensating %d samples per second.\n", comp);
if (avresample_set_compensation(s->avr, comp, inlink->sample_rate) == 0) {
s->comp = comp;
}
}
}
// adjust PTS to avoid monotonicity errors with input PTS jitter
pts -= delta;
delta = 0;
}
if (out_size > 0) {
AVFrame *buf_out = ff_get_audio_buffer(outlink, out_size);
if (!buf_out) {
ret = AVERROR(ENOMEM);
goto fail;
}
if (s->first_frame && delta > 0) {
int planar = av_sample_fmt_is_planar(buf_out->format);
int planes = planar ? nb_channels : 1;
int block_size = av_get_bytes_per_sample(buf_out->format) *
(planar ? 1 : nb_channels);
int ch;
av_samples_set_silence(buf_out->extended_data, 0, delta,
nb_channels, buf->format);
for (ch = 0; ch < planes; ch++)
buf_out->extended_data[ch] += delta * block_size;
avresample_read(s->avr, buf_out->extended_data, out_size);
for (ch = 0; ch < planes; ch++)
buf_out->extended_data[ch] -= delta * block_size;
} else {
avresample_read(s->avr, buf_out->extended_data, out_size);
if (delta > 0) {
av_samples_set_silence(buf_out->extended_data, out_size - delta,
delta, nb_channels, buf->format);
}
}
buf_out->pts = s->pts;
ret = ff_filter_frame(outlink, buf_out);
if (ret < 0)
goto fail;
s->got_output = 1;
} else if (avresample_available(s->avr)) {
av_log(ctx, AV_LOG_WARNING, "Non-monotonous timestamps, dropping "
"whole buffer.\n");
}
/* drain any remaining buffered data */
avresample_read(s->avr, NULL, avresample_available(s->avr));
new_pts = pts - avresample_get_delay(s->avr);
/* check for s->pts monotonicity */
if (new_pts > s->pts) {
s->pts = new_pts;
ret = avresample_convert(s->avr, NULL, 0, 0, buf->extended_data,
buf->linesize[0], buf->nb_samples);
} else {
av_log(ctx, AV_LOG_WARNING, "Non-monotonous timestamps, dropping "
"whole buffer.\n");
ret = 0;
}
s->first_frame = 0;
fail:
av_frame_free(&buf);
return ret;
}
static const AVFilterPad avfilter_af_asyncts_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
.filter_frame = filter_frame
},
{ NULL }
};
static const AVFilterPad avfilter_af_asyncts_outputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
.config_props = config_props,
.request_frame = request_frame
},
{ NULL }
};
AVFilter ff_af_asyncts = {
.name = "asyncts",
.description = NULL_IF_CONFIG_SMALL("Sync audio data to timestamps."),
.init = init,
.uninit = uninit,
.priv_size = sizeof(ASyncContext),
.priv_class = &asyncts_class,
.query_formats = ff_query_formats_all_layouts,
.inputs = avfilter_af_asyncts_inputs,
.outputs = avfilter_af_asyncts_outputs,
};

View File

@ -79,7 +79,6 @@ static void register_all(void)
REGISTER_FILTER(ASPLIT, asplit, af); REGISTER_FILTER(ASPLIT, asplit, af);
REGISTER_FILTER(ASTATS, astats, af); REGISTER_FILTER(ASTATS, astats, af);
REGISTER_FILTER(ASTREAMSELECT, astreamselect, af); REGISTER_FILTER(ASTREAMSELECT, astreamselect, af);
REGISTER_FILTER(ASYNCTS, asyncts, af);
REGISTER_FILTER(ATEMPO, atempo, af); REGISTER_FILTER(ATEMPO, atempo, af);
REGISTER_FILTER(ATRIM, atrim, af); REGISTER_FILTER(ATRIM, atrim, af);
REGISTER_FILTER(AZMQ, azmq, af); REGISTER_FILTER(AZMQ, azmq, af);

View File

@ -31,7 +31,7 @@
#define LIBAVFILTER_VERSION_MAJOR 6 #define LIBAVFILTER_VERSION_MAJOR 6
#define LIBAVFILTER_VERSION_MINOR 78 #define LIBAVFILTER_VERSION_MINOR 78
#define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_MICRO 101
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
LIBAVFILTER_VERSION_MINOR, \ LIBAVFILTER_VERSION_MINOR, \

View File

@ -187,12 +187,6 @@ $(FATE_AMIX): SRC1 = $(TARGET_PATH)/tests/data/asynth-44100-2-2.wav
$(FATE_AMIX): CMP = oneoff $(FATE_AMIX): CMP = oneoff
$(FATE_AMIX): CMP_UNIT = f32 $(FATE_AMIX): CMP_UNIT = f32
FATE_AFILTER_SAMPLES-$(call FILTERDEMDECMUX, ASYNCTS, FLV, NELLYMOSER, PCM_S16LE) += fate-filter-asyncts
fate-filter-asyncts: SRC = $(TARGET_SAMPLES)/nellymoser/nellymoser-discont.flv
fate-filter-asyncts: CMD = pcm -analyzeduration 10000000 -i $(SRC) -af asyncts
fate-filter-asyncts: CMP = oneoff
fate-filter-asyncts: REF = $(SAMPLES)/nellymoser/nellymoser-discont-async-v3.pcm
FATE_AFILTER_SAMPLES-$(CONFIG_ARESAMPLE_FILTER) += fate-filter-aresample FATE_AFILTER_SAMPLES-$(CONFIG_ARESAMPLE_FILTER) += fate-filter-aresample
fate-filter-aresample: SRC = $(TARGET_SAMPLES)/nellymoser/nellymoser-discont.flv fate-filter-aresample: SRC = $(TARGET_SAMPLES)/nellymoser/nellymoser-discont.flv
fate-filter-aresample: CMD = pcm -analyzeduration 10000000 -i $(SRC) -af aresample=min_comp=0.001:min_hard_comp=0.1:first_pts=0 fate-filter-aresample: CMD = pcm -analyzeduration 10000000 -i $(SRC) -af aresample=min_comp=0.001:min_hard_comp=0.1:first_pts=0