Deprecated in c29038f3041a4080342b2e333c1967d136749c0f. The resample filter based upon this library has been removed as well.
Showing the changes to libavfilter (3 of 59 files). Show all
Unified · Split
| @@ -135,7 +135,6 @@ OBJS-$(CONFIG_LV2_FILTER) += af_lv2.o · 134 unmodified lines | |||
| 135 | OBJS-$(CONFIG_MCOMPAND_FILTER) += af_mcompand.o | 135 | OBJS-$(CONFIG_MCOMPAND_FILTER) += af_mcompand.o |
| 136 | OBJS-$(CONFIG_PAN_FILTER) += af_pan.o | 136 | OBJS-$(CONFIG_PAN_FILTER) += af_pan.o |
| 137 | OBJS-$(CONFIG_REPLAYGAIN_FILTER) += af_replaygain.o | 137 | OBJS-$(CONFIG_REPLAYGAIN_FILTER) += af_replaygain.o |
| 138 | OBJS-$(CONFIG_RESAMPLE_FILTER) += af_resample.o | ||
| 139 | OBJS-$(CONFIG_RUBBERBAND_FILTER) += af_rubberband.o | 138 | OBJS-$(CONFIG_RUBBERBAND_FILTER) += af_rubberband.o |
| 140 | OBJS-$(CONFIG_SIDECHAINCOMPRESS_FILTER) += af_sidechaincompress.o | 139 | OBJS-$(CONFIG_SIDECHAINCOMPRESS_FILTER) += af_sidechaincompress.o |
| 141 | OBJS-$(CONFIG_SIDECHAINGATE_FILTER) += af_agate.o | 140 | OBJS-$(CONFIG_SIDECHAINGATE_FILTER) += af_agate.o |
| @@ -1,369 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * This file is part of FFmpeg. | ||
| 3 | * | ||
| 4 | * FFmpeg is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU Lesser General Public | ||
| 6 | * License as published by the Free Software Foundation; either | ||
| 7 | * version 2.1 of the License, or (at your option) any later version. | ||
| 8 | * | ||
| 9 | * FFmpeg is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 12 | * Lesser General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU Lesser General Public | ||
| 15 | * License along with FFmpeg; if not, write to the Free Software | ||
| 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 17 | */ | ||
| 18 | |||
| 19 | /** | ||
| 20 | * @file | ||
| 21 | * sample format and channel layout conversion audio filter | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include "libavutil/avassert.h" | ||
| 25 | #include "libavutil/avstring.h" | ||
| 26 | #include "libavutil/common.h" | ||
| 27 | #include "libavutil/dict.h" | ||
| 28 | #include "libavutil/mathematics.h" | ||
| 29 | #include "libavutil/opt.h" | ||
| 30 | |||
| 31 | #include "libavresample/avresample.h" | ||
| 32 | |||
| 33 | #include "audio.h" | ||
| 34 | #include "avfilter.h" | ||
| 35 | #include "formats.h" | ||
| 36 | #include "internal.h" | ||
| 37 | |||
| 38 | typedef struct ResampleContext { | ||
| 39 | const AVClass *class; | ||
| 40 | AVAudioResampleContext *avr; | ||
| 41 | AVDictionary *options; | ||
| 42 | |||
| 43 | int resampling; | ||
| 44 | int64_t next_pts; | ||
| 45 | int64_t next_in_pts; | ||
| 46 | |||
| 47 | /* set by filter_frame() to signal an output frame to request_frame() */ | ||
| 48 | int got_output; | ||
| 49 | } ResampleContext; | ||
| 50 | |||
| 51 | static av_cold int init(AVFilterContext *ctx, AVDictionary **opts) | ||
| 52 | { | ||
| 53 | ResampleContext *s = ctx->priv; | ||
| 54 | const AVClass *avr_class = avresample_get_class(); | ||
| 55 | AVDictionaryEntry *e = NULL; | ||
| 56 | |||
| 57 | while ((e = av_dict_get(*opts, "", e, AV_DICT_IGNORE_SUFFIX))) { | ||
| 58 | if (av_opt_find(&avr_class, e->key, NULL, 0, | ||
| 59 | AV_OPT_SEARCH_FAKE_OBJ | AV_OPT_SEARCH_CHILDREN)) | ||
| 60 | av_dict_set(&s->options, e->key, e->value, 0); | ||
| 61 | } | ||
| 62 | |||
| 63 | e = NULL; | ||
| 64 | while ((e = av_dict_get(s->options, "", e, AV_DICT_IGNORE_SUFFIX))) | ||
| 65 | av_dict_set(opts, e->key, NULL, 0); | ||
| 66 | |||
| 67 | /* do not allow the user to override basic format options */ | ||
| 68 | av_dict_set(&s->options, "in_channel_layout", NULL, 0); | ||
| 69 | av_dict_set(&s->options, "out_channel_layout", NULL, 0); | ||
| 70 | av_dict_set(&s->options, "in_sample_fmt", NULL, 0); | ||
| 71 | av_dict_set(&s->options, "out_sample_fmt", NULL, 0); | ||
| 72 | av_dict_set(&s->options, "in_sample_rate", NULL, 0); | ||
| 73 | av_dict_set(&s->options, "out_sample_rate", NULL, 0); | ||
| 74 | |||
| 75 | return 0; | ||
| 76 | } | ||
| 77 | |||
| 78 | static av_cold void uninit(AVFilterContext *ctx) | ||
| 79 | { | ||
| 80 | ResampleContext *s = ctx->priv; | ||
| 81 | |||
| 82 | if (s->avr) { | ||
| 83 | avresample_close(s->avr); | ||
| 84 | avresample_free(&s->avr); | ||
| 85 | } | ||
| 86 | av_dict_free(&s->options); | ||
| 87 | } | ||
| 88 | |||
| 89 | static int query_formats(AVFilterContext *ctx) | ||
| 90 | { | ||
| 91 | AVFilterLink *inlink = ctx->inputs[0]; | ||
| 92 | AVFilterLink *outlink = ctx->outputs[0]; | ||
| 93 | AVFilterFormats *in_formats, *out_formats, *in_samplerates, *out_samplerates; | ||
| 94 | AVFilterChannelLayouts *in_layouts, *out_layouts; | ||
| 95 | int ret; | ||
| 96 | |||
| 97 | if (!(in_formats = ff_all_formats (AVMEDIA_TYPE_AUDIO)) || | ||
| 98 | !(out_formats = ff_all_formats (AVMEDIA_TYPE_AUDIO)) || | ||
| 99 | !(in_samplerates = ff_all_samplerates ( )) || | ||
| 100 | !(out_samplerates = ff_all_samplerates ( )) || | ||
| 101 | !(in_layouts = ff_all_channel_layouts ( )) || | ||
| 102 | !(out_layouts = ff_all_channel_layouts ( ))) | ||
| 103 | return AVERROR(ENOMEM); | ||
| 104 | |||
| 105 | if ((ret = ff_formats_ref (in_formats, &inlink->outcfg.formats )) < 0 || | ||
| 106 | (ret = ff_formats_ref (out_formats, &outlink->incfg.formats )) < 0 || | ||
| 107 | (ret = ff_formats_ref (in_samplerates, &inlink->outcfg.samplerates )) < 0 || | ||
| 108 | (ret = ff_formats_ref (out_samplerates, &outlink->incfg.samplerates )) < 0 || | ||
| 109 | (ret = ff_channel_layouts_ref (in_layouts, &inlink->outcfg.channel_layouts)) < 0 || | ||
| 110 | (ret = ff_channel_layouts_ref (out_layouts, &outlink->incfg.channel_layouts)) < 0) | ||
| 111 | return ret; | ||
| 112 | |||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | static int config_output(AVFilterLink *outlink) | ||
| 117 | { | ||
| 118 | AVFilterContext *ctx = outlink->src; | ||
| 119 | AVFilterLink *inlink = ctx->inputs[0]; | ||
| 120 | ResampleContext *s = ctx->priv; | ||
| 121 | char buf1[64], buf2[64]; | ||
| 122 | int ret; | ||
| 123 | |||
| 124 | int64_t resampling_forced; | ||
| 125 | |||
| 126 | if (s->avr) { | ||
| 127 | avresample_close(s->avr); | ||
| 128 | avresample_free(&s->avr); | ||
| 129 | } | ||
| 130 | |||
| 131 | if (inlink->channel_layout == outlink->channel_layout && | ||
| 132 | inlink->sample_rate == outlink->sample_rate && | ||
| 133 | (inlink->format == outlink->format || | ||
| 134 | (av_get_channel_layout_nb_channels(inlink->channel_layout) == 1 && | ||
| 135 | av_get_channel_layout_nb_channels(outlink->channel_layout) == 1 && | ||
| 136 | av_get_planar_sample_fmt(inlink->format) == | ||
| 137 | av_get_planar_sample_fmt(outlink->format)))) | ||
| 138 | return 0; | ||
| 139 | |||
| 140 | if (!(s->avr = avresample_alloc_context())) | ||
| 141 | return AVERROR(ENOMEM); | ||
| 142 | |||
| 143 | if (s->options) { | ||
| 144 | int ret; | ||
| 145 | AVDictionaryEntry *e = NULL; | ||
| 146 | while ((e = av_dict_get(s->options, "", e, AV_DICT_IGNORE_SUFFIX))) | ||
| 147 | av_log(ctx, AV_LOG_VERBOSE, "lavr option: %s=%s\n", e->key, e->value); | ||
| 148 | |||
| 149 | ret = av_opt_set_dict(s->avr, &s->options); | ||
| 150 | if (ret < 0) | ||
| 151 | return ret; | ||
| 152 | } | ||
| 153 | |||
| 154 | av_opt_set_int(s->avr, "in_channel_layout", inlink ->channel_layout, 0); | ||
| 155 | av_opt_set_int(s->avr, "out_channel_layout", outlink->channel_layout, 0); | ||
| 156 | av_opt_set_int(s->avr, "in_sample_fmt", inlink ->format, 0); | ||
| 157 | av_opt_set_int(s->avr, "out_sample_fmt", outlink->format, 0); | ||
| 158 | av_opt_set_int(s->avr, "in_sample_rate", inlink ->sample_rate, 0); | ||
| 159 | av_opt_set_int(s->avr, "out_sample_rate", outlink->sample_rate, 0); | ||
| 160 | |||
| 161 | if ((ret = avresample_open(s->avr)) < 0) | ||
| 162 | return ret; | ||
| 163 | |||
| 164 | av_opt_get_int(s->avr, "force_resampling", 0, &resampling_forced); | ||
| 165 | s->resampling = resampling_forced || (inlink->sample_rate != outlink->sample_rate); | ||
| 166 | |||
| 167 | if (s->resampling) { | ||
| 168 | outlink->time_base = (AVRational){ 1, outlink->sample_rate }; | ||
| 169 | s->next_pts = AV_NOPTS_VALUE; | ||
| 170 | s->next_in_pts = AV_NOPTS_VALUE; | ||
| 171 | } else | ||
| 172 | outlink->time_base = inlink->time_base; | ||
| 173 | |||
| 174 | av_get_channel_layout_string(buf1, sizeof(buf1), | ||
| 175 | -1, inlink ->channel_layout); | ||
| 176 | av_get_channel_layout_string(buf2, sizeof(buf2), | ||
| 177 | -1, outlink->channel_layout); | ||
| 178 | av_log(ctx, AV_LOG_VERBOSE, | ||
| 179 | "fmt:%s srate:%d cl:%s -> fmt:%s srate:%d cl:%s\n", | ||
| 180 | av_get_sample_fmt_name(inlink ->format), inlink ->sample_rate, buf1, | ||
| 181 | av_get_sample_fmt_name(outlink->format), outlink->sample_rate, buf2); | ||
| 182 | |||
| 183 | return 0; | ||
| 184 | } | ||
| 185 | |||
| 186 | static int request_frame(AVFilterLink *outlink) | ||
| 187 | { | ||
| 188 | AVFilterContext *ctx = outlink->src; | ||
| 189 | ResampleContext *s = ctx->priv; | ||
| 190 | int ret = 0; | ||
| 191 | |||
| 192 | s->got_output = 0; | ||
| 193 | while (ret >= 0 && !s->got_output) | ||
| 194 | ret = ff_request_frame(ctx->inputs[0]); | ||
| 195 | |||
| 196 | /* flush the lavr delay buffer */ | ||
| 197 | if (ret == AVERROR_EOF && s->avr) { | ||
| 198 | AVFrame *frame; | ||
| 199 | int nb_samples = avresample_get_out_samples(s->avr, 0); | ||
| 200 | |||
| 201 | if (!nb_samples) | ||
| 202 | return ret; | ||
| 203 | |||
| 204 | frame = ff_get_audio_buffer(outlink, nb_samples); | ||
| 205 | if (!frame) | ||
| 206 | return AVERROR(ENOMEM); | ||
| 207 | |||
| 208 | ret = avresample_convert(s->avr, frame->extended_data, | ||
| 209 | frame->linesize[0], nb_samples, | ||
| 210 | NULL, 0, 0); | ||
| 211 | if (ret <= 0) { | ||
| 212 | av_frame_free(&frame); | ||
| 213 | return (ret == 0) ? AVERROR_EOF : ret; | ||
| 214 | } | ||
| 215 | |||
| 216 | frame->nb_samples = ret; | ||
| 217 | frame->pts = s->next_pts; | ||
| 218 | return ff_filter_frame(outlink, frame); | ||
| 219 | } | ||
| 220 | return ret; | ||
| 221 | } | ||
| 222 | |||
| 223 | static int filter_frame(AVFilterLink *inlink, AVFrame *in) | ||
| 224 | { | ||
| 225 | AVFilterContext *ctx = inlink->dst; | ||
| 226 | ResampleContext *s = ctx->priv; | ||
| 227 | AVFilterLink *outlink = ctx->outputs[0]; | ||
| 228 | int ret; | ||
| 229 | |||
| 230 | if (s->avr) { | ||
| 231 | AVFrame *out; | ||
| 232 | int delay, nb_samples; | ||
| 233 | |||
| 234 | /* maximum possible samples lavr can output */ | ||
| 235 | delay = avresample_get_delay(s->avr); | ||
| 236 | nb_samples = avresample_get_out_samples(s->avr, in->nb_samples); | ||
| 237 | |||
| 238 | out = ff_get_audio_buffer(outlink, nb_samples); | ||
| 239 | if (!out) { | ||
| 240 | ret = AVERROR(ENOMEM); | ||
| 241 | goto fail; | ||
| 242 | } | ||
| 243 | |||
| 244 | ret = avresample_convert(s->avr, out->extended_data, out->linesize[0], | ||
| 245 | nb_samples, in->extended_data, in->linesize[0], | ||
| 246 | in->nb_samples); | ||
| 247 | if (ret <= 0) { | ||
| 248 | av_frame_free(&out); | ||
| 249 | if (ret < 0) | ||
| 250 | goto fail; | ||
| 251 | } | ||
| 252 | |||
| 253 | av_assert0(!avresample_available(s->avr)); | ||
| 254 | |||
| 255 | if (s->resampling && s->next_pts == AV_NOPTS_VALUE) { | ||
| 256 | if (in->pts == AV_NOPTS_VALUE) { | ||
| 257 | av_log(ctx, AV_LOG_WARNING, "First timestamp is missing, " | ||
| 258 | "assuming 0.\n"); | ||
| 259 | s->next_pts = 0; | ||
| 260 | } else | ||
| 261 | s->next_pts = av_rescale_q(in->pts, inlink->time_base, | ||
| 262 | outlink->time_base); | ||
| 263 | } | ||
| 264 | |||
| 265 | if (ret > 0) { | ||
| 266 | out->nb_samples = ret; | ||
| 267 | |||
| 268 | ret = av_frame_copy_props(out, in); | ||
| 269 | if (ret < 0) { | ||
| 270 | av_frame_free(&out); | ||
| 271 | goto fail; | ||
| 272 | } | ||
| 273 | |||
| 274 | if (s->resampling) { | ||
| 275 | out->sample_rate = outlink->sample_rate; | ||
| 276 | /* Only convert in->pts if there is a discontinuous jump. | ||
| 277 | This ensures that out->pts tracks the number of samples actually | ||
| 278 | output by the resampler in the absence of such a jump. | ||
| 279 | Otherwise, the rounding in av_rescale_q() and av_rescale() | ||
| 280 | causes off-by-1 errors. */ | ||
| 281 | if (in->pts != AV_NOPTS_VALUE && in->pts != s->next_in_pts) { | ||
| 282 | out->pts = av_rescale_q(in->pts, inlink->time_base, | ||
| 283 | outlink->time_base) - | ||
| 284 | av_rescale(delay, outlink->sample_rate, | ||
| 285 | inlink->sample_rate); | ||
| 286 | } else | ||
| 287 | out->pts = s->next_pts; | ||
| 288 | |||
| 289 | s->next_pts = out->pts + out->nb_samples; | ||
| 290 | s->next_in_pts = in->pts + in->nb_samples; | ||
| 291 | } else | ||
| 292 | out->pts = in->pts; | ||
| 293 | |||
| 294 | ret = ff_filter_frame(outlink, out); | ||
| 295 | s->got_output = 1; | ||
| 296 | } | ||
| 297 | |||
| 298 | fail: | ||
| 299 | av_frame_free(&in); | ||
| 300 | } else { | ||
| 301 | in->format = outlink->format; | ||
| 302 | ret = ff_filter_frame(outlink, in); | ||
| 303 | s->got_output = 1; | ||
| 304 | } | ||
| 305 | |||
| 306 | return ret; | ||
| 307 | } | ||
| 308 | |||
| 309 | #if FF_API_CHILD_CLASS_NEXT | ||
| 310 | static const AVClass *resample_child_class_next(const AVClass *prev) | ||
| 311 | { | ||
| 312 | return prev ? NULL : avresample_get_class(); | ||
| 313 | } | ||
| 314 | #endif | ||
| 315 | |||
| 316 | static const AVClass *resample_child_class_iterate(void **iter) | ||
| 317 | { | ||
| 318 | const AVClass *c = *iter ? NULL : avresample_get_class(); | ||
| 319 | *iter = (void*)(uintptr_t)c; | ||
| 320 | return c; | ||
| 321 | } | ||
| 322 | |||
| 323 | static void *resample_child_next(void *obj, void *prev) | ||
| 324 | { | ||
| 325 | ResampleContext *s = obj; | ||
| 326 | return prev ? NULL : s->avr; | ||
| 327 | } | ||
| 328 | |||
| 329 | static const AVClass resample_class = { | ||
| 330 | .class_name = "resample", | ||
| 331 | .item_name = av_default_item_name, | ||
| 332 | .version = LIBAVUTIL_VERSION_INT, | ||
| 333 | #if FF_API_CHILD_CLASS_NEXT | ||
| 334 | .child_class_next = resample_child_class_next, | ||
| 335 | #endif | ||
| 336 | .child_class_iterate = resample_child_class_iterate, | ||
| 337 | .child_next = resample_child_next, | ||
| 338 | }; | ||
| 339 | |||
| 340 | static const AVFilterPad avfilter_af_resample_inputs[] = { | ||
| 341 | { | ||
| 342 | .name = "default", | ||
| 343 | .type = AVMEDIA_TYPE_AUDIO, | ||
| 344 | .filter_frame = filter_frame, | ||
| 345 | }, | ||
| 346 | { NULL } | ||
| 347 | }; | ||
| 348 | |||
| 349 | static const AVFilterPad avfilter_af_resample_outputs[] = { | ||
| 350 | { | ||
| 351 | .name = "default", | ||
| 352 | .type = AVMEDIA_TYPE_AUDIO, | ||
| 353 | .config_props = config_output, | ||
| 354 | .request_frame = request_frame | ||
| 355 | }, | ||
| 356 | { NULL } | ||
| 357 | }; | ||
| 358 | |||
| 359 | AVFilter ff_af_resample = { | ||
| 360 | .name = "resample", | ||
| 361 | .description = NULL_IF_CONFIG_SMALL("Audio resampling and conversion."), | ||
| 362 | .priv_size = sizeof(ResampleContext), | ||
| 363 | .priv_class = &resample_class, | ||
| 364 | .init_dict = init, | ||
| 365 | .uninit = uninit, | ||
| 366 | .query_formats = query_formats, | ||
| 367 | .inputs = avfilter_af_resample_inputs, | ||
| 368 | .outputs = avfilter_af_resample_outputs, | ||
| 369 | }; | ||
| @@ -129,7 +129,6 @@ extern AVFilter ff_af_lv2; · 128 unmodified lines | |||
| 129 | extern AVFilter ff_af_mcompand; | 129 | extern AVFilter ff_af_mcompand; |
| 130 | extern AVFilter ff_af_pan; | 130 | extern AVFilter ff_af_pan; |
| 131 | extern AVFilter ff_af_replaygain; | 131 | extern AVFilter ff_af_replaygain; |
| 132 | extern AVFilter ff_af_resample; | ||
| 133 | extern AVFilter ff_af_rubberband; | 132 | extern AVFilter ff_af_rubberband; |
| 134 | extern AVFilter ff_af_sidechaincompress; | 133 | extern AVFilter ff_af_sidechaincompress; |
| 135 | extern AVFilter ff_af_sidechaingate; | 134 | extern AVFilter ff_af_sidechaingate; |