Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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.  
  37. typedef 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.  
  46. static 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);
  69. end:
  70.     return ret;
  71. }
  72.  
  73. static av_cold void uninit(AVFilterContext *ctx)
  74. {
  75.     AResampleContext *aresample = ctx->priv;
  76.     swr_free(&aresample->swr);
  77. }
  78.  
  79. static 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.         out_samplerates = ff_make_format_list((int[]){ out_rate, -1 });
  102.     } else {
  103.         out_samplerates = ff_all_samplerates();
  104.     }
  105.     ff_formats_ref(out_samplerates, &outlink->in_samplerates);
  106.  
  107.     if(out_format != AV_SAMPLE_FMT_NONE) {
  108.         out_formats = ff_make_format_list((int[]){ out_format, -1 });
  109.     } else
  110.         out_formats = ff_all_formats(AVMEDIA_TYPE_AUDIO);
  111.     ff_formats_ref(out_formats, &outlink->in_formats);
  112.  
  113.     if(out_layout) {
  114.         out_layouts = avfilter_make_format64_list((int64_t[]){ out_layout, -1 });
  115.     } else
  116.         out_layouts = ff_all_channel_counts();
  117.     ff_channel_layouts_ref(out_layouts, &outlink->in_channel_layouts);
  118.  
  119.     return 0;
  120. }
  121.  
  122.  
  123. static int config_output(AVFilterLink *outlink)
  124. {
  125.     int ret;
  126.     AVFilterContext *ctx = outlink->src;
  127.     AVFilterLink *inlink = ctx->inputs[0];
  128.     AResampleContext *aresample = ctx->priv;
  129.     int out_rate;
  130.     uint64_t out_layout;
  131.     enum AVSampleFormat out_format;
  132.     char inchl_buf[128], outchl_buf[128];
  133.  
  134.     aresample->swr = swr_alloc_set_opts(aresample->swr,
  135.                                         outlink->channel_layout, outlink->format, outlink->sample_rate,
  136.                                         inlink->channel_layout, inlink->format, inlink->sample_rate,
  137.                                         0, ctx);
  138.     if (!aresample->swr)
  139.         return AVERROR(ENOMEM);
  140.     if (!inlink->channel_layout)
  141.         av_opt_set_int(aresample->swr, "ich", inlink->channels, 0);
  142.     if (!outlink->channel_layout)
  143.         av_opt_set_int(aresample->swr, "och", outlink->channels, 0);
  144.  
  145.     ret = swr_init(aresample->swr);
  146.     if (ret < 0)
  147.         return ret;
  148.  
  149.     out_rate   = av_get_int(aresample->swr, "osr", NULL);
  150.     out_layout = av_get_int(aresample->swr, "ocl", NULL);
  151.     out_format = av_get_int(aresample->swr, "osf", NULL);
  152.     outlink->time_base = (AVRational) {1, out_rate};
  153.  
  154.     av_assert0(outlink->sample_rate == out_rate);
  155.     av_assert0(outlink->channel_layout == out_layout || !outlink->channel_layout);
  156.     av_assert0(outlink->format == out_format);
  157.  
  158.     aresample->ratio = (double)outlink->sample_rate / inlink->sample_rate;
  159.  
  160.     av_get_channel_layout_string(inchl_buf,  sizeof(inchl_buf),  inlink ->channels, inlink ->channel_layout);
  161.     av_get_channel_layout_string(outchl_buf, sizeof(outchl_buf), outlink->channels, outlink->channel_layout);
  162.  
  163.     av_log(ctx, AV_LOG_VERBOSE, "ch:%d chl:%s fmt:%s r:%dHz -> ch:%d chl:%s fmt:%s r:%dHz\n",
  164.            inlink ->channels, inchl_buf,  av_get_sample_fmt_name(inlink->format),  inlink->sample_rate,
  165.            outlink->channels, outchl_buf, av_get_sample_fmt_name(outlink->format), outlink->sample_rate);
  166.     return 0;
  167. }
  168.  
  169. static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref)
  170. {
  171.     AResampleContext *aresample = inlink->dst->priv;
  172.     const int n_in  = insamplesref->nb_samples;
  173.     int n_out       = n_in * aresample->ratio * 2 + 256;
  174.     AVFilterLink *const outlink = inlink->dst->outputs[0];
  175.     AVFrame *outsamplesref = ff_get_audio_buffer(outlink, n_out);
  176.     int ret;
  177.  
  178.     if(!outsamplesref)
  179.         return AVERROR(ENOMEM);
  180.  
  181.     av_frame_copy_props(outsamplesref, insamplesref);
  182.     outsamplesref->format                = outlink->format;
  183.     av_frame_set_channels(outsamplesref, outlink->channels);
  184.     outsamplesref->channel_layout        = outlink->channel_layout;
  185.     outsamplesref->sample_rate           = outlink->sample_rate;
  186.  
  187.     if(insamplesref->pts != AV_NOPTS_VALUE) {
  188.         int64_t inpts = av_rescale(insamplesref->pts, inlink->time_base.num * (int64_t)outlink->sample_rate * inlink->sample_rate, inlink->time_base.den);
  189.         int64_t outpts= swr_next_pts(aresample->swr, inpts);
  190.         aresample->next_pts =
  191.         outsamplesref->pts  = ROUNDED_DIV(outpts, inlink->sample_rate);
  192.     } else {
  193.         outsamplesref->pts  = AV_NOPTS_VALUE;
  194.     }
  195.     n_out = swr_convert(aresample->swr, outsamplesref->extended_data, n_out,
  196.                                  (void *)insamplesref->extended_data, n_in);
  197.     if (n_out <= 0) {
  198.         av_frame_free(&outsamplesref);
  199.         av_frame_free(&insamplesref);
  200.         return 0;
  201.     }
  202.  
  203.     outsamplesref->nb_samples  = n_out;
  204.  
  205.     ret = ff_filter_frame(outlink, outsamplesref);
  206.     aresample->req_fullfilled= 1;
  207.     av_frame_free(&insamplesref);
  208.     return ret;
  209. }
  210.  
  211. static int request_frame(AVFilterLink *outlink)
  212. {
  213.     AVFilterContext *ctx = outlink->src;
  214.     AResampleContext *aresample = ctx->priv;
  215.     AVFilterLink *const inlink = outlink->src->inputs[0];
  216.     int ret;
  217.  
  218.     aresample->req_fullfilled = 0;
  219.     do{
  220.         ret = ff_request_frame(ctx->inputs[0]);
  221.     }while(!aresample->req_fullfilled && ret>=0);
  222.  
  223.     if (ret == AVERROR_EOF) {
  224.         AVFrame *outsamplesref;
  225.         int n_out = 4096;
  226.  
  227.         outsamplesref = ff_get_audio_buffer(outlink, n_out);
  228.         if (!outsamplesref)
  229.             return AVERROR(ENOMEM);
  230.         n_out = swr_convert(aresample->swr, outsamplesref->extended_data, n_out, 0, 0);
  231.         if (n_out <= 0) {
  232.             av_frame_free(&outsamplesref);
  233.             return (n_out == 0) ? AVERROR_EOF : n_out;
  234.         }
  235.  
  236.         outsamplesref->sample_rate = outlink->sample_rate;
  237.         outsamplesref->nb_samples  = n_out;
  238. #if 0
  239.         outsamplesref->pts = aresample->next_pts;
  240.         if(aresample->next_pts != AV_NOPTS_VALUE)
  241.             aresample->next_pts += av_rescale_q(n_out, (AVRational){1 ,outlink->sample_rate}, outlink->time_base);
  242. #else
  243.         outsamplesref->pts = swr_next_pts(aresample->swr, INT64_MIN);
  244.         outsamplesref->pts = ROUNDED_DIV(outsamplesref->pts, inlink->sample_rate);
  245. #endif
  246.  
  247.         return ff_filter_frame(outlink, outsamplesref);
  248.     }
  249.     return ret;
  250. }
  251.  
  252. static const AVClass *resample_child_class_next(const AVClass *prev)
  253. {
  254.     return prev ? NULL : swr_get_class();
  255. }
  256.  
  257. static void *resample_child_next(void *obj, void *prev)
  258. {
  259.     AResampleContext *s = obj;
  260.     return prev ? NULL : s->swr;
  261. }
  262.  
  263. #define OFFSET(x) offsetof(AResampleContext, x)
  264. #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
  265.  
  266. static const AVOption options[] = {
  267.     {"sample_rate", NULL, OFFSET(sample_rate_arg), AV_OPT_TYPE_INT, {.i64=0},  0,        INT_MAX, FLAGS },
  268.     {NULL}
  269. };
  270.  
  271. static const AVClass aresample_class = {
  272.     .class_name       = "aresample",
  273.     .item_name        = av_default_item_name,
  274.     .option           = options,
  275.     .version          = LIBAVUTIL_VERSION_INT,
  276.     .child_class_next = resample_child_class_next,
  277.     .child_next       = resample_child_next,
  278. };
  279.  
  280. static const AVFilterPad aresample_inputs[] = {
  281.     {
  282.         .name         = "default",
  283.         .type         = AVMEDIA_TYPE_AUDIO,
  284.         .filter_frame = filter_frame,
  285.     },
  286.     { NULL }
  287. };
  288.  
  289. static const AVFilterPad aresample_outputs[] = {
  290.     {
  291.         .name          = "default",
  292.         .config_props  = config_output,
  293.         .request_frame = request_frame,
  294.         .type          = AVMEDIA_TYPE_AUDIO,
  295.     },
  296.     { NULL }
  297. };
  298.  
  299. AVFilter avfilter_af_aresample = {
  300.     .name          = "aresample",
  301.     .description   = NULL_IF_CONFIG_SMALL("Resample audio data."),
  302.     .init_dict     = init_dict,
  303.     .uninit        = uninit,
  304.     .query_formats = query_formats,
  305.     .priv_size     = sizeof(AResampleContext),
  306.     .priv_class    = &aresample_class,
  307.     .inputs        = aresample_inputs,
  308.     .outputs       = aresample_outputs,
  309. };
  310.