On 9/20/15, wm4 <nfx...@googlemail.com> wrote: > 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? >
Well, I will check if this can be done. _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel > _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel