On Fri, 18 Sep 2015 20:22:05 +0000 Paul B Mahol <one...@gmail.com> wrote:
> Signed-off-by: Paul B Mahol <one...@gmail.com> > --- > configure | 5 + > libavfilter/Makefile | 1 + > libavfilter/af_rubberband.c | 225 > ++++++++++++++++++++++++++++++++++++++++++++ > libavfilter/allfilters.c | 1 + > 4 files changed, 232 insertions(+) > create mode 100644 libavfilter/af_rubberband.c > > diff --git a/configure b/configure > index 839c85d..d2a25bb 100755 > --- a/configure > +++ b/configure > @@ -236,6 +236,7 @@ External library support: > --enable-libopenjpeg enable JPEG 2000 de/encoding via OpenJPEG [no] > --enable-libopus enable Opus de/encoding via libopus [no] > --enable-libpulse enable Pulseaudio input via libpulse [no] > + --enable-librubberband enable rubberband needed for rubberband filter > [no] > --enable-libquvi enable quvi input via libquvi [no] > --enable-librtmp enable RTMP[E] support via librtmp [no] > --enable-libschroedinger enable Dirac de/encoding via libschroedinger [no] > @@ -1405,6 +1406,7 @@ EXTERNAL_LIBRARY_LIST=" > libpulse > libquvi > librtmp > + librubberband > libschroedinger > libshine > libsmbclient > @@ -2789,6 +2791,7 @@ pullup_filter_deps="gpl" > removelogo_filter_deps="avcodec avformat swscale" > repeatfields_filter_deps="gpl" > resample_filter_deps="avresample" > +rubberband_filter_deps="librubberband" > sab_filter_deps="gpl swscale" > scale_filter_deps="swscale" > scale2ref_filter_deps="swscale" > @@ -4661,6 +4664,7 @@ die_license_disabled_gpl() { > > die_license_disabled gpl frei0r > die_license_disabled gpl libcdio > +die_license_disabled gpl librubberband > die_license_disabled gpl libsmbclient > die_license_disabled gpl libutvideo > die_license_disabled gpl libvidstab > @@ -5271,6 +5275,7 @@ enabled libopus && require_pkg_config opus > opus_multistream.h opus_mul > enabled libpulse && require_pkg_config libpulse pulse/pulseaudio.h > pa_context_new > enabled libquvi && require_pkg_config libquvi quvi/quvi.h quvi_init > enabled librtmp && require_pkg_config librtmp librtmp/rtmp.h > RTMP_Socket > +enabled librubberband && require_pkg_config rubberband > rubberband/rubberband-c.h rubberband_new > enabled libschroedinger && require_pkg_config schroedinger-1.0 > schroedinger/schro.h schro_init > enabled libshine && require_pkg_config shine shine/layer3.h > shine_encode_buffer > enabled libsmbclient && { use_pkg_config smbclient libsmbclient.h > smbc_init || > diff --git a/libavfilter/Makefile b/libavfilter/Makefile > index 05effd6..4bbe972 100644 > --- a/libavfilter/Makefile > +++ b/libavfilter/Makefile > @@ -77,6 +77,7 @@ OBJS-$(CONFIG_LOWPASS_FILTER) += af_biquads.o > OBJS-$(CONFIG_PAN_FILTER) += af_pan.o > OBJS-$(CONFIG_REPLAYGAIN_FILTER) += af_replaygain.o > OBJS-$(CONFIG_RESAMPLE_FILTER) += af_resample.o > +OBJS-$(CONFIG_RUBBERBAND_FILTER) += af_rubberband.o > OBJS-$(CONFIG_SIDECHAINCOMPRESS_FILTER) += af_sidechaincompress.o > OBJS-$(CONFIG_SILENCEDETECT_FILTER) += af_silencedetect.o > OBJS-$(CONFIG_SILENCEREMOVE_FILTER) += af_silenceremove.o > diff --git a/libavfilter/af_rubberband.c b/libavfilter/af_rubberband.c > new file mode 100644 > index 0000000..a2cca2c > --- /dev/null > +++ b/libavfilter/af_rubberband.c > @@ -0,0 +1,225 @@ > +/* > + * 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 <rubberband/rubberband-c.h> > + > +#include "libavutil/channel_layout.h" > +#include "libavutil/common.h" > +#include "libavutil/opt.h" > + > +#include "audio.h" > +#include "avfilter.h" > +#include "formats.h" > +#include "internal.h" > + > +typedef struct RubberBandContext { > + const AVClass *class; > + RubberBandState rbs; > + > + double tempo, pitch; > + int transients, detector, phase, window, > + smoothing, formant, pitch, channels; > + int64_t nb_samples_out; > + int flushed; > +} RubberBandContext; > + > +#define OFFSET(x) offsetof(RubberBandContext, x) > +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM > + > +static const AVOption rubberband_options[] = { > + { "tempo", "set tempo scale factor", OFFSET(tempo), > AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.01, 100, A }, > + { "pitch", "set pitch scale factor", OFFSET(pitch), > AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.01, 100, A }, > + { "transients", "set transients", OFFSET(transients), AV_OPT_TYPE_INT, > {.i64=0}, 0, INT_MAX, A, "transients" }, > + { "crisp", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionTransientsCrisp}, 0, 0, A, "transients" }, > + { "mixed", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionTransientsMixed}, 0, 0, A, "transients" }, > + { "smooth", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionTransientsSmooth}, 0, 0, A, "transients" }, > + { "detector", "set detector", OFFSET(detector), AV_OPT_TYPE_INT, > {.i64=0}, 0, INT_MAX, A, "detector" }, > + { "compound", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionDetectorCompound}, 0, 0, A, "detector" }, > + { "percussive", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionDetectorPercussive}, 0, 0, A, "detector" }, > + { "soft", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionDetectorSoft}, 0, 0, A, "detector" }, > + { "phase", "set phase", OFFSET(phase), AV_OPT_TYPE_INT, > {.i64=0}, 0, INT_MAX, A, "phase" }, > + { "laminar", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionPhaseLaminar}, 0, 0, A, "phase" }, > + { "independent", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionPhaseIndependent}, 0, 0, A, "phase" }, > + { "window", "set window", OFFSET(window), AV_OPT_TYPE_INT, > {.i64=0}, 0, INT_MAX, A, "window" }, > + { "standard", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionWindowStandard}, 0, 0, A, "window" }, > + { "short", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionWindowShort}, 0, 0, A, "window" }, > + { "long", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionWindowLong}, 0, 0, A, "window" }, > + { "smoothing", "set smoothing", OFFSET(smoothing), AV_OPT_TYPE_INT, > {.i64=0}, 0, INT_MAX, A, "smoothing" }, > + { "on", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionSmoothingOff}, 0, 0, A, "smoothing" }, > + { "off", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionSmoothingOn}, 0, 0, A, "smoothing" }, > + { "formant", "set formant", OFFSET(formant), AV_OPT_TYPE_INT, > {.i64=0}, 0, INT_MAX, A, "formant" }, > + { "shifted", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionFormantShifted}, 0, 0, A, "formant" }, > + { "preserved", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionFormantPreserved}, 0, 0, A, "formant" }, > + { "pitch", "set pitch", OFFSET(pitch), AV_OPT_TYPE_INT, > {.i64=0}, 0, INT_MAX, A, "pitch" }, > + { "quality", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionPitchHighQuality}, 0, 0, A, "pitch" }, > + { "speed", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionPitchHighSpeed}, 0, 0, A, "pitch" }, > + { "consistency", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionPitchHighConsistency}, 0, 0, A, "pitch" }, > + { "channels", "set channels", OFFSET(channels), AV_OPT_TYPE_INT, > {.i64=0}, 0, INT_MAX, A, "channels" }, > + { "apart", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionChannelsApart}, 0, 0, A, "channels" }, > + { "together", 0, 0, AV_OPT_TYPE_CONST, > {.i64=RubberBandOptionChannelsTogether}, 0, 0, A, "channels" }, > + { NULL }, > +}; > + > +AVFILTER_DEFINE_CLASS(rubberband); > + > +static av_cold void uninit(AVFilterContext *ctx) > +{ > + RubberBandContext *s = ctx->priv; > + > + if (s->rbs) > + rubberband_delete(s->rbs); > +} > + > +static int query_formats(AVFilterContext *ctx) > +{ > + AVFilterFormats *formats = NULL; > + AVFilterChannelLayouts *layouts = NULL; > + static const enum AVSampleFormat sample_fmts[] = { > + AV_SAMPLE_FMT_FLTP, > + AV_SAMPLE_FMT_NONE, > + }; > + int ret; > + > + layouts = ff_all_channel_counts(); > + if (!layouts) > + return AVERROR(ENOMEM); > + ret = ff_set_common_channel_layouts(ctx, layouts); > + if (ret < 0) > + return ret; > + > + formats = ff_make_format_list(sample_fmts); > + if (!formats) > + return AVERROR(ENOMEM); > + ret = ff_set_common_formats(ctx, formats); > + if (ret < 0) > + return ret; > + > + formats = ff_all_samplerates(); > + if (!formats) > + return AVERROR(ENOMEM); > + return ff_set_common_samplerates(ctx, formats); > +} > + > +static int filter_frame(AVFilterLink *inlink, AVFrame *in) > +{ > + RubberBandContext *s = inlink->dst->priv; > + AVFilterLink *outlink = inlink->dst->outputs[0]; > + AVFrame *out; > + int ret = 0, nb_samples; > + > + rubberband_process(s->rbs, (const float *const *)in->data, > in->nb_samples, 0); > + > + nb_samples = rubberband_available(s->rbs); > + if (nb_samples > 0) { > + out = ff_get_audio_buffer(inlink, nb_samples); > + if (!out) { > + av_frame_free(&in); > + return AVERROR(ENOMEM); > + } > + out->pts = av_rescale_q(s->nb_samples_out, > + (AVRational){ 1, outlink->sample_rate }, > + outlink->time_base); > + nb_samples = rubberband_retrieve(s->rbs, (float *const *)out->data, > nb_samples); > + out->nb_samples = nb_samples; > + ret = ff_filter_frame(outlink, out); > + s->nb_samples_out += nb_samples; > + } > + > + av_frame_free(&in); > + return ret; > +} > + > +static int config_output(AVFilterLink *outlink) > +{ > + AVFilterContext *ctx = outlink->src; > + RubberBandContext *s = ctx->priv; > + AVFilterLink *inlink = ctx->inputs[0]; > + int opts = s->transients|s->detector|s->phase|s->window| > + s->smoothing|s->formant|s->pitch|s->channels| > + RubberBandOptionProcessRealTime; > + > + if (s->rbs) > + rubberband_delete(s->rbs); > + s->rbs = rubberband_new(inlink->sample_rate, inlink->channels, opts, 1. > / s->tempo, s->pitch); > + > + ctx->outputs[0]->flags |= FF_LINK_FLAG_REQUEST_LOOP; > + > + return 0; > +} > + > +static int request_frame(AVFilterLink *outlink) > +{ > + AVFilterContext *ctx = outlink->src; > + RubberBandContext *s = ctx->priv; > + AVFilterLink *inlink = ctx->inputs[0]; > + int ret = 0; > + > + ret = ff_request_frame(ctx->inputs[0]); > + > + if (ret == AVERROR_EOF && !s->flushed) { > + int nb_samples; > + > + s->flushed = 1; > + rubberband_process(s->rbs, NULL, 0, 1); > + nb_samples = rubberband_available(s->rbs); > + > + if (nb_samples > 0) { > + AVFrame *out = ff_get_audio_buffer(inlink, nb_samples); > + if (!out) > + return AVERROR(ENOMEM); > + out->pts = av_rescale_q(s->nb_samples_out, > + (AVRational){ 1, outlink->sample_rate }, > + outlink->time_base); > + nb_samples = rubberband_retrieve(s->rbs, (float *const > *)out->data, nb_samples); > + out->nb_samples = nb_samples; > + ret = ff_filter_frame(outlink, out); > + } > + } > + > + return ret; > +} > + So this simply discards the input timestamp? _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel