libavfilter/af_aresample.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011 Stefano Sabatini
00003  * Copyright (c) 2011 Mina Nagy Zaki
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00027 #include "libavutil/eval.h"
00028 #include "libavcodec/avcodec.h"
00029 #include "avfilter.h"
00030 #include "internal.h"
00031 
00032 typedef struct {
00033     struct AVResampleContext *resample;
00034     int out_rate;
00035     double ratio;
00036     AVFilterBufferRef *outsamplesref;
00037     int unconsumed_nb_samples,
00038         max_cached_nb_samples;
00039     int16_t *cached_data[8],
00040             *resampled_data[8];
00041 } AResampleContext;
00042 
00043 static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
00044 {
00045     AResampleContext *aresample = ctx->priv;
00046     int ret;
00047 
00048     if (args) {
00049         if ((ret = ff_parse_sample_rate(&aresample->out_rate, args, ctx)) < 0)
00050             return ret;
00051     } else {
00052         aresample->out_rate = -1;
00053     }
00054 
00055     return 0;
00056 }
00057 
00058 static av_cold void uninit(AVFilterContext *ctx)
00059 {
00060     AResampleContext *aresample = ctx->priv;
00061     if (aresample->outsamplesref) {
00062         int nb_channels =
00063             av_get_channel_layout_nb_channels(
00064                 aresample->outsamplesref->audio->channel_layout);
00065         avfilter_unref_buffer(aresample->outsamplesref);
00066         while (nb_channels--) {
00067             av_freep(&(aresample->cached_data[nb_channels]));
00068             av_freep(&(aresample->resampled_data[nb_channels]));
00069         }
00070     }
00071 
00072     if (aresample->resample)
00073         av_resample_close(aresample->resample);
00074 }
00075 
00076 static int config_output(AVFilterLink *outlink)
00077 {
00078     AVFilterContext *ctx = outlink->src;
00079     AVFilterLink *inlink = ctx->inputs[0];
00080     AResampleContext *aresample = ctx->priv;
00081 
00082     if (aresample->out_rate == -1)
00083         aresample->out_rate = outlink->sample_rate;
00084     else
00085         outlink->sample_rate = aresample->out_rate;
00086     outlink->time_base = (AVRational) {1, aresample->out_rate};
00087 
00088     //TODO: make the resampling parameters configurable
00089     aresample->resample = av_resample_init(aresample->out_rate, inlink->sample_rate,
00090                                            16, 10, 0, 0.8);
00091 
00092     aresample->ratio = (double)outlink->sample_rate / inlink->sample_rate;
00093 
00094     av_log(ctx, AV_LOG_INFO, "r:%"PRId64"Hz -> r:%"PRId64"Hz\n",
00095            inlink->sample_rate, outlink->sample_rate);
00096     return 0;
00097 }
00098 
00099 static int query_formats(AVFilterContext *ctx)
00100 {
00101     AVFilterFormats *formats = NULL;
00102 
00103     avfilter_add_format(&formats, AV_SAMPLE_FMT_S16);
00104     if (!formats)
00105         return AVERROR(ENOMEM);
00106     avfilter_set_common_sample_formats(ctx, formats);
00107 
00108     formats = avfilter_make_all_channel_layouts();
00109     if (!formats)
00110         return AVERROR(ENOMEM);
00111     avfilter_set_common_channel_layouts(ctx, formats);
00112 
00113     formats = avfilter_make_all_packing_formats();
00114     if (!formats)
00115         return AVERROR(ENOMEM);
00116     avfilter_set_common_packing_formats(ctx, formats);
00117 
00118     return 0;
00119 }
00120 
00121 static void deinterleave(int16_t **outp, int16_t *in,
00122                          int nb_channels, int nb_samples)
00123 {
00124     int16_t *out[8];
00125     memcpy(out, outp, nb_channels * sizeof(int16_t*));
00126 
00127     switch (nb_channels) {
00128     case 2:
00129         while (nb_samples--) {
00130             *out[0]++ = *in++;
00131             *out[1]++ = *in++;
00132         }
00133         break;
00134     case 3:
00135         while (nb_samples--) {
00136             *out[0]++ = *in++;
00137             *out[1]++ = *in++;
00138             *out[2]++ = *in++;
00139         }
00140         break;
00141     case 4:
00142         while (nb_samples--) {
00143             *out[0]++ = *in++;
00144             *out[1]++ = *in++;
00145             *out[2]++ = *in++;
00146             *out[3]++ = *in++;
00147         }
00148         break;
00149     case 5:
00150         while (nb_samples--) {
00151             *out[0]++ = *in++;
00152             *out[1]++ = *in++;
00153             *out[2]++ = *in++;
00154             *out[3]++ = *in++;
00155             *out[4]++ = *in++;
00156         }
00157         break;
00158     case 6:
00159         while (nb_samples--) {
00160             *out[0]++ = *in++;
00161             *out[1]++ = *in++;
00162             *out[2]++ = *in++;
00163             *out[3]++ = *in++;
00164             *out[4]++ = *in++;
00165             *out[5]++ = *in++;
00166         }
00167         break;
00168     case 8:
00169         while (nb_samples--) {
00170             *out[0]++ = *in++;
00171             *out[1]++ = *in++;
00172             *out[2]++ = *in++;
00173             *out[3]++ = *in++;
00174             *out[4]++ = *in++;
00175             *out[5]++ = *in++;
00176             *out[6]++ = *in++;
00177             *out[7]++ = *in++;
00178         }
00179         break;
00180     }
00181 }
00182 
00183 static void interleave(int16_t *out, int16_t **inp,
00184         int nb_channels, int nb_samples)
00185 {
00186     int16_t *in[8];
00187     memcpy(in, inp, nb_channels * sizeof(int16_t*));
00188 
00189     switch (nb_channels) {
00190     case 2:
00191         while (nb_samples--) {
00192             *out++ = *in[0]++;
00193             *out++ = *in[1]++;
00194         }
00195         break;
00196     case 3:
00197         while (nb_samples--) {
00198             *out++ = *in[0]++;
00199             *out++ = *in[1]++;
00200             *out++ = *in[2]++;
00201         }
00202         break;
00203     case 4:
00204         while (nb_samples--) {
00205             *out++ = *in[0]++;
00206             *out++ = *in[1]++;
00207             *out++ = *in[2]++;
00208             *out++ = *in[3]++;
00209         }
00210         break;
00211     case 5:
00212         while (nb_samples--) {
00213             *out++ = *in[0]++;
00214             *out++ = *in[1]++;
00215             *out++ = *in[2]++;
00216             *out++ = *in[3]++;
00217             *out++ = *in[4]++;
00218         }
00219         break;
00220     case 6:
00221         while (nb_samples--) {
00222             *out++ = *in[0]++;
00223             *out++ = *in[1]++;
00224             *out++ = *in[2]++;
00225             *out++ = *in[3]++;
00226             *out++ = *in[4]++;
00227             *out++ = *in[5]++;
00228         }
00229         break;
00230     case 8:
00231         while (nb_samples--) {
00232             *out++ = *in[0]++;
00233             *out++ = *in[1]++;
00234             *out++ = *in[2]++;
00235             *out++ = *in[3]++;
00236             *out++ = *in[4]++;
00237             *out++ = *in[5]++;
00238             *out++ = *in[6]++;
00239             *out++ = *in[7]++;
00240         }
00241         break;
00242     }
00243 }
00244 
00245 static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref)
00246 {
00247     AResampleContext *aresample  = inlink->dst->priv;
00248     AVFilterLink * const outlink = inlink->dst->outputs[0];
00249     int i,
00250         in_nb_samples            = insamplesref->audio->nb_samples,
00251         cached_nb_samples        = in_nb_samples + aresample->unconsumed_nb_samples,
00252         requested_out_nb_samples = aresample->ratio * cached_nb_samples,
00253         nb_channels              =
00254             av_get_channel_layout_nb_channels(inlink->channel_layout);
00255 
00256     if (cached_nb_samples > aresample->max_cached_nb_samples) {
00257         for (i = 0; i < nb_channels; i++) {
00258             aresample->cached_data[i]    =
00259                 av_realloc(aresample->cached_data[i], cached_nb_samples * sizeof(int16_t));
00260             aresample->resampled_data[i] =
00261                 av_realloc(aresample->resampled_data[i],
00262                            FFALIGN(sizeof(int16_t) * requested_out_nb_samples, 16));
00263 
00264             if (aresample->cached_data[i] == NULL || aresample->resampled_data[i] == NULL)
00265                 return;
00266         }
00267         aresample->max_cached_nb_samples = cached_nb_samples;
00268 
00269         if (aresample->outsamplesref)
00270             avfilter_unref_buffer(aresample->outsamplesref);
00271 
00272         aresample->outsamplesref =
00273             avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, requested_out_nb_samples);
00274         outlink->out_buf = aresample->outsamplesref;
00275     }
00276 
00277     avfilter_copy_buffer_ref_props(aresample->outsamplesref, insamplesref);
00278     aresample->outsamplesref->audio->sample_rate = outlink->sample_rate;
00279     aresample->outsamplesref->pts =
00280         av_rescale(outlink->sample_rate, insamplesref->pts, inlink->sample_rate);
00281 
00282     /* av_resample() works with planar audio buffers */
00283     if (!inlink->planar && nb_channels > 1) {
00284         int16_t *out[8];
00285         for (i = 0; i < nb_channels; i++)
00286             out[i] = aresample->cached_data[i] + aresample->unconsumed_nb_samples;
00287 
00288         deinterleave(out, (int16_t *)insamplesref->data[0],
00289                      nb_channels, in_nb_samples);
00290     } else {
00291         for (i = 0; i < nb_channels; i++)
00292             memcpy(aresample->cached_data[i] + aresample->unconsumed_nb_samples,
00293                    insamplesref->data[i],
00294                    in_nb_samples * sizeof(int16_t));
00295     }
00296 
00297     for (i = 0; i < nb_channels; i++) {
00298         int consumed_nb_samples;
00299         const int is_last = i+1 == nb_channels;
00300 
00301         aresample->outsamplesref->audio->nb_samples =
00302             av_resample(aresample->resample,
00303                         aresample->resampled_data[i], aresample->cached_data[i],
00304                         &consumed_nb_samples,
00305                         cached_nb_samples,
00306                         requested_out_nb_samples, is_last);
00307 
00308         /* move unconsumed data back to the beginning of the cache */
00309         aresample->unconsumed_nb_samples = cached_nb_samples - consumed_nb_samples;
00310         memmove(aresample->cached_data[i],
00311                 aresample->cached_data[i] + consumed_nb_samples,
00312                 aresample->unconsumed_nb_samples * sizeof(int16_t));
00313     }
00314 
00315 
00316     /* copy resampled data to the output samplesref */
00317     if (!inlink->planar && nb_channels > 1) {
00318         interleave((int16_t *)aresample->outsamplesref->data[0],
00319                    aresample->resampled_data,
00320                    nb_channels, aresample->outsamplesref->audio->nb_samples);
00321     } else {
00322         for (i = 0; i < nb_channels; i++)
00323             memcpy(aresample->outsamplesref->data[i], aresample->resampled_data[i],
00324                    aresample->outsamplesref->audio->nb_samples * sizeof(int16_t));
00325     }
00326 
00327     avfilter_filter_samples(outlink, avfilter_ref_buffer(aresample->outsamplesref, ~0));
00328     avfilter_unref_buffer(insamplesref);
00329 }
00330 
00331 AVFilter avfilter_af_aresample = {
00332     .name          = "aresample",
00333     .description   = NULL_IF_CONFIG_SMALL("Resample audio data."),
00334     .init          = init,
00335     .uninit        = uninit,
00336     .query_formats = query_formats,
00337     .priv_size     = sizeof(AResampleContext),
00338 
00339     .inputs    = (const AVFilterPad[]) {{ .name      = "default",
00340                                     .type            = AVMEDIA_TYPE_AUDIO,
00341                                     .filter_samples  = filter_samples,
00342                                     .min_perms       = AV_PERM_READ, },
00343                                   { .name = NULL}},
00344     .outputs   = (const AVFilterPad[]) {{ .name      = "default",
00345                                     .config_props    = config_output,
00346                                     .type            = AVMEDIA_TYPE_AUDIO, },
00347                                   { .name = NULL}},
00348 };