1/* 2 * Copyright (c) 2011 Stefano Sabatini 3 * Copyright (c) 2011 Mina Nagy Zaki 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * @file 24 * resampling audio filter 25 */ 26 27#include "libavutil/avstring.h" 28#include "libavutil/channel_layout.h" 29#include "libavutil/opt.h" 30#include "libavutil/samplefmt.h" 31#include "libavutil/avassert.h" 32#include "libswresample/swresample.h" 33#include "avfilter.h" 34#include "audio.h" 35#include "internal.h" 36 37typedef struct { 38 const AVClass *class; 39 int sample_rate_arg; 40 double ratio; 41 struct SwrContext *swr; 42 int64_t next_pts; 43 int req_fullfilled; 44} AResampleContext; 45 46static av_cold int init_dict(AVFilterContext *ctx, AVDictionary **opts) 47{ 48 AResampleContext *aresample = ctx->priv; 49 int ret = 0; 50 51 aresample->next_pts = AV_NOPTS_VALUE; 52 aresample->swr = swr_alloc(); 53 if (!aresample->swr) { 54 ret = AVERROR(ENOMEM); 55 goto end; 56 } 57 58 if (opts) { 59 AVDictionaryEntry *e = NULL; 60 61 while ((e = av_dict_get(*opts, "", e, AV_DICT_IGNORE_SUFFIX))) { 62 if ((ret = av_opt_set(aresample->swr, e->key, e->value, 0)) < 0) 63 goto end; 64 } 65 av_dict_free(opts); 66 } 67 if (aresample->sample_rate_arg > 0) 68 av_opt_set_int(aresample->swr, "osr", aresample->sample_rate_arg, 0); 69end: 70 return ret; 71} 72 73static av_cold void uninit(AVFilterContext *ctx) 74{ 75 AResampleContext *aresample = ctx->priv; 76 swr_free(&aresample->swr); 77} 78 79static int query_formats(AVFilterContext *ctx) 80{ 81 AResampleContext *aresample = ctx->priv; 82 int out_rate = av_get_int(aresample->swr, "osr", NULL); 83 uint64_t out_layout = av_get_int(aresample->swr, "ocl", NULL); 84 enum AVSampleFormat out_format = av_get_int(aresample->swr, "osf", NULL); 85 86 AVFilterLink *inlink = ctx->inputs[0]; 87 AVFilterLink *outlink = ctx->outputs[0]; 88 89 AVFilterFormats *in_formats = ff_all_formats(AVMEDIA_TYPE_AUDIO); 90 AVFilterFormats *out_formats; 91 AVFilterFormats *in_samplerates = ff_all_samplerates(); 92 AVFilterFormats *out_samplerates; 93 AVFilterChannelLayouts *in_layouts = ff_all_channel_counts(); 94 AVFilterChannelLayouts *out_layouts; 95 96 ff_formats_ref (in_formats, &inlink->out_formats); 97 ff_formats_ref (in_samplerates, &inlink->out_samplerates); 98 ff_channel_layouts_ref(in_layouts, &inlink->out_channel_layouts); 99 100 if(out_rate > 0) { 101 int ratelist[] = { out_rate, -1 }; 102 out_samplerates = ff_make_format_list(ratelist); 103 } else { 104 out_samplerates = ff_all_samplerates(); 105 } 106 ff_formats_ref(out_samplerates, &outlink->in_samplerates); 107 108 if(out_format != AV_SAMPLE_FMT_NONE) { 109 int formatlist[] = { out_format, -1 }; 110 out_formats = ff_make_format_list(formatlist); 111 } else 112 out_formats = ff_all_formats(AVMEDIA_TYPE_AUDIO); 113 ff_formats_ref(out_formats, &outlink->in_formats); 114 115 if(out_layout) { 116 int64_t layout_list[] = { out_layout, -1 }; 117 out_layouts = avfilter_make_format64_list(layout_list); 118 } else 119 out_layouts = ff_all_channel_counts(); 120 ff_channel_layouts_ref(out_layouts, &outlink->in_channel_layouts); 121 122 return 0; 123} 124 125 126static int config_output(AVFilterLink *outlink) 127{ 128 int ret; 129 AVFilterContext *ctx = outlink->src; 130 AVFilterLink *inlink = ctx->inputs[0]; 131 AResampleContext *aresample = ctx->priv; 132 int out_rate; 133 uint64_t out_layout; 134 enum AVSampleFormat out_format; 135 char inchl_buf[128], outchl_buf[128]; 136 137 aresample->swr = swr_alloc_set_opts(aresample->swr, 138 outlink->channel_layout, outlink->format, outlink->sample_rate, 139 inlink->channel_layout, inlink->format, inlink->sample_rate, 140 0, ctx); 141 if (!aresample->swr) 142 return AVERROR(ENOMEM); 143 if (!inlink->channel_layout) 144 av_opt_set_int(aresample->swr, "ich", inlink->channels, 0); 145 if (!outlink->channel_layout) 146 av_opt_set_int(aresample->swr, "och", outlink->channels, 0); 147 148 ret = swr_init(aresample->swr); 149 if (ret < 0) 150 return ret; 151 152 out_rate = av_get_int(aresample->swr, "osr", NULL); 153 out_layout = av_get_int(aresample->swr, "ocl", NULL); 154 out_format = av_get_int(aresample->swr, "osf", NULL); 155 outlink->time_base = (AVRational) {1, out_rate}; 156 157 av_assert0(outlink->sample_rate == out_rate); 158 av_assert0(outlink->channel_layout == out_layout || !outlink->channel_layout); 159 av_assert0(outlink->format == out_format); 160 161 aresample->ratio = (double)outlink->sample_rate / inlink->sample_rate; 162 163 av_get_channel_layout_string(inchl_buf, sizeof(inchl_buf), inlink ->channels, inlink ->channel_layout); 164 av_get_channel_layout_string(outchl_buf, sizeof(outchl_buf), outlink->channels, outlink->channel_layout); 165 166 av_log(ctx, AV_LOG_VERBOSE, "ch:%d chl:%s fmt:%s r:%dHz -> ch:%d chl:%s fmt:%s r:%dHz\n", 167 inlink ->channels, inchl_buf, av_get_sample_fmt_name(inlink->format), inlink->sample_rate, 168 outlink->channels, outchl_buf, av_get_sample_fmt_name(outlink->format), outlink->sample_rate); 169 return 0; 170} 171 172static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref) 173{ 174 AResampleContext *aresample = inlink->dst->priv; 175 const int n_in = insamplesref->nb_samples; 176 int64_t delay; 177 int n_out = n_in * aresample->ratio + 32; 178 AVFilterLink *const outlink = inlink->dst->outputs[0]; 179 AVFrame *outsamplesref; 180 int ret; 181 182 delay = swr_get_delay(aresample->swr, outlink->sample_rate); 183 if (delay > 0) 184 n_out += delay; 185 186 outsamplesref = ff_get_audio_buffer(outlink, n_out); 187 188 if(!outsamplesref) 189 return AVERROR(ENOMEM); 190 191 av_frame_copy_props(outsamplesref, insamplesref); 192 outsamplesref->format = outlink->format; 193 av_frame_set_channels(outsamplesref, outlink->channels); 194 outsamplesref->channel_layout = outlink->channel_layout; 195 outsamplesref->sample_rate = outlink->sample_rate; 196 197 if(insamplesref->pts != AV_NOPTS_VALUE) { 198 int64_t inpts = av_rescale(insamplesref->pts, inlink->time_base.num * (int64_t)outlink->sample_rate * inlink->sample_rate, inlink->time_base.den); 199 int64_t outpts= swr_next_pts(aresample->swr, inpts); 200 aresample->next_pts = 201 outsamplesref->pts = ROUNDED_DIV(outpts, inlink->sample_rate); 202 } else { 203 outsamplesref->pts = AV_NOPTS_VALUE; 204 } 205 n_out = swr_convert(aresample->swr, outsamplesref->extended_data, n_out, 206 (void *)insamplesref->extended_data, n_in); 207 if (n_out <= 0) { 208 av_frame_free(&outsamplesref); 209 av_frame_free(&insamplesref); 210 return 0; 211 } 212 213 outsamplesref->nb_samples = n_out; 214 215 ret = ff_filter_frame(outlink, outsamplesref); 216 aresample->req_fullfilled= 1; 217 av_frame_free(&insamplesref); 218 return ret; 219} 220 221static int request_frame(AVFilterLink *outlink) 222{ 223 AVFilterContext *ctx = outlink->src; 224 AResampleContext *aresample = ctx->priv; 225 AVFilterLink *const inlink = outlink->src->inputs[0]; 226 int ret; 227 228 aresample->req_fullfilled = 0; 229 do{ 230 ret = ff_request_frame(ctx->inputs[0]); 231 }while(!aresample->req_fullfilled && ret>=0); 232 233 if (ret == AVERROR_EOF) { 234 AVFrame *outsamplesref; 235 int n_out = 4096; 236 int64_t pts; 237 238 outsamplesref = ff_get_audio_buffer(outlink, n_out); 239 if (!outsamplesref) 240 return AVERROR(ENOMEM); 241 242 pts = swr_next_pts(aresample->swr, INT64_MIN); 243 pts = ROUNDED_DIV(pts, inlink->sample_rate); 244 245 n_out = swr_convert(aresample->swr, outsamplesref->extended_data, n_out, 0, 0); 246 if (n_out <= 0) { 247 av_frame_free(&outsamplesref); 248 return (n_out == 0) ? AVERROR_EOF : n_out; 249 } 250 251 outsamplesref->sample_rate = outlink->sample_rate; 252 outsamplesref->nb_samples = n_out; 253 254 outsamplesref->pts = pts; 255 256 return ff_filter_frame(outlink, outsamplesref); 257 } 258 return ret; 259} 260 261static const AVClass *resample_child_class_next(const AVClass *prev) 262{ 263 return prev ? NULL : swr_get_class(); 264} 265 266static void *resample_child_next(void *obj, void *prev) 267{ 268 AResampleContext *s = obj; 269 return prev ? NULL : s->swr; 270} 271 272#define OFFSET(x) offsetof(AResampleContext, x) 273#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM 274 275static const AVOption options[] = { 276 {"sample_rate", NULL, OFFSET(sample_rate_arg), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS }, 277 {NULL} 278}; 279 280static const AVClass aresample_class = { 281 .class_name = "aresample", 282 .item_name = av_default_item_name, 283 .option = options, 284 .version = LIBAVUTIL_VERSION_INT, 285 .child_class_next = resample_child_class_next, 286 .child_next = resample_child_next, 287}; 288 289static const AVFilterPad aresample_inputs[] = { 290 { 291 .name = "default", 292 .type = AVMEDIA_TYPE_AUDIO, 293 .filter_frame = filter_frame, 294 }, 295 { NULL } 296}; 297 298static const AVFilterPad aresample_outputs[] = { 299 { 300 .name = "default", 301 .config_props = config_output, 302 .request_frame = request_frame, 303 .type = AVMEDIA_TYPE_AUDIO, 304 }, 305 { NULL } 306}; 307 308AVFilter ff_af_aresample = { 309 .name = "aresample", 310 .description = NULL_IF_CONFIG_SMALL("Resample audio data."), 311 .init_dict = init_dict, 312 .uninit = uninit, 313 .query_formats = query_formats, 314 .priv_size = sizeof(AResampleContext), 315 .priv_class = &aresample_class, 316 .inputs = aresample_inputs, 317 .outputs = aresample_outputs, 318}; 319