Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 2011 Stefano Sabatini
  3.  *
  4.  * This file is part of FFmpeg.
  5.  *
  6.  * FFmpeg is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Lesser General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2.1 of the License, or (at your option) any later version.
  10.  *
  11.  * FFmpeg is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Lesser General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Lesser General Public
  17.  * License along with FFmpeg; if not, write to the Free Software
  18.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19.  */
  20.  
  21. /**
  22.  * @file
  23.  * eval audio source
  24.  */
  25.  
  26. #include "libavutil/avassert.h"
  27. #include "libavutil/avstring.h"
  28. #include "libavutil/channel_layout.h"
  29. #include "libavutil/eval.h"
  30. #include "libavutil/opt.h"
  31. #include "libavutil/parseutils.h"
  32. #include "avfilter.h"
  33. #include "audio.h"
  34. #include "internal.h"
  35.  
  36. static const char * const var_names[] = {
  37.     "ch",           ///< the value of the current channel
  38.     "n",            ///< number of frame
  39.     "nb_in_channels",
  40.     "nb_out_channels",
  41.     "t",            ///< timestamp expressed in seconds
  42.     "s",            ///< sample rate
  43.     NULL
  44. };
  45.  
  46. enum var_name {
  47.     VAR_CH,
  48.     VAR_N,
  49.     VAR_NB_IN_CHANNELS,
  50.     VAR_NB_OUT_CHANNELS,
  51.     VAR_T,
  52.     VAR_S,
  53.     VAR_VARS_NB
  54. };
  55.  
  56. typedef struct {
  57.     const AVClass *class;
  58.     char *sample_rate_str;
  59.     int sample_rate;
  60.     int64_t chlayout;
  61.     char *chlayout_str;
  62.     int nb_channels;            ///< number of output channels
  63.     int nb_in_channels;         ///< number of input channels
  64.     int same_chlayout;          ///< set output as input channel layout
  65.     int64_t pts;
  66.     AVExpr **expr;
  67.     char *exprs;
  68.     int nb_samples;             ///< number of samples per requested frame
  69.     int64_t duration;
  70.     uint64_t n;
  71.     double var_values[VAR_VARS_NB];
  72.     double *channel_values;
  73.     int64_t out_channel_layout;
  74. } EvalContext;
  75.  
  76. static double val(void *priv, double ch)
  77. {
  78.     EvalContext *eval = priv;
  79.     return eval->channel_values[FFMIN((int)ch, eval->nb_in_channels-1)];
  80. }
  81.  
  82. static double (* const aeval_func1[])(void *, double) = { val, NULL };
  83. static const char * const aeval_func1_names[] = { "val", NULL };
  84.  
  85. #define OFFSET(x) offsetof(EvalContext, x)
  86. #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
  87.  
  88. static const AVOption aevalsrc_options[]= {
  89.     { "exprs",       "set the '|'-separated list of channels expressions", OFFSET(exprs), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = FLAGS },
  90.     { "nb_samples",  "set the number of samples per requested frame", OFFSET(nb_samples),      AV_OPT_TYPE_INT,    {.i64 = 1024},    0,        INT_MAX, FLAGS },
  91.     { "n",           "set the number of samples per requested frame", OFFSET(nb_samples),      AV_OPT_TYPE_INT,    {.i64 = 1024},    0,        INT_MAX, FLAGS },
  92.     { "sample_rate", "set the sample rate",                           OFFSET(sample_rate_str), AV_OPT_TYPE_STRING, {.str = "44100"}, CHAR_MIN, CHAR_MAX, FLAGS },
  93.     { "s",           "set the sample rate",                           OFFSET(sample_rate_str), AV_OPT_TYPE_STRING, {.str = "44100"}, CHAR_MIN, CHAR_MAX, FLAGS },
  94.     { "duration",    "set audio duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS },
  95.     { "d",           "set audio duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS },
  96.     { "channel_layout", "set channel layout", OFFSET(chlayout_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
  97.     { "c",              "set channel layout", OFFSET(chlayout_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
  98.     { NULL }
  99. };
  100.  
  101. AVFILTER_DEFINE_CLASS(aevalsrc);
  102.  
  103. static int parse_channel_expressions(AVFilterContext *ctx,
  104.                                      int expected_nb_channels)
  105. {
  106.     EvalContext *eval = ctx->priv;
  107.     char *args1 = av_strdup(eval->exprs);
  108.     char *expr, *last_expr = NULL, *buf;
  109.     double (* const *func1)(void *, double) = NULL;
  110.     const char * const *func1_names = NULL;
  111.     int i, ret = 0;
  112.  
  113.     if (!args1)
  114.         return AVERROR(ENOMEM);
  115.  
  116.     if (!eval->exprs) {
  117.         av_log(ctx, AV_LOG_ERROR, "Channels expressions list is empty\n");
  118.         return AVERROR(EINVAL);
  119.     }
  120.  
  121.     if (!strcmp(ctx->filter->name, "aeval")) {
  122.         func1 = aeval_func1;
  123.         func1_names = aeval_func1_names;
  124.     }
  125.  
  126. #define ADD_EXPRESSION(expr_) do {                                      \
  127.         if (!av_dynarray2_add((void **)&eval->expr, &eval->nb_channels, \
  128.                               sizeof(*eval->expr), NULL)) {             \
  129.             ret = AVERROR(ENOMEM);                                      \
  130.             goto end;                                                   \
  131.         }                                                               \
  132.         eval->expr[eval->nb_channels-1] = NULL;                         \
  133.         ret = av_expr_parse(&eval->expr[eval->nb_channels - 1], expr_,  \
  134.                             var_names, func1_names, func1,              \
  135.                             NULL, NULL, 0, ctx);                        \
  136.         if (ret < 0)                                                    \
  137.             goto end;                                                   \
  138.     } while (0)
  139.  
  140.     /* reset expressions */
  141.     for (i = 0; i < eval->nb_channels; i++) {
  142.         av_expr_free(eval->expr[i]);
  143.         eval->expr[i] = NULL;
  144.     }
  145.     av_freep(&eval->expr);
  146.     eval->nb_channels = 0;
  147.  
  148.     buf = args1;
  149.     while (expr = av_strtok(buf, "|", &buf)) {
  150.         ADD_EXPRESSION(expr);
  151.         last_expr = expr;
  152.     }
  153.  
  154.     if (expected_nb_channels > eval->nb_channels)
  155.         for (i = eval->nb_channels; i < expected_nb_channels; i++)
  156.             ADD_EXPRESSION(last_expr);
  157.  
  158.     if (expected_nb_channels > 0 && eval->nb_channels != expected_nb_channels) {
  159.         av_log(ctx, AV_LOG_ERROR,
  160.                "Mismatch between the specified number of channel expressions '%d' "
  161.                "and the number of expected output channels '%d' for the specified channel layout\n",
  162.                eval->nb_channels, expected_nb_channels);
  163.         ret = AVERROR(EINVAL);
  164.         goto end;
  165.     }
  166.  
  167. end:
  168.     av_free(args1);
  169.     return ret;
  170. }
  171.  
  172. static av_cold int init(AVFilterContext *ctx)
  173. {
  174.     EvalContext *eval = ctx->priv;
  175.     int ret = 0;
  176.  
  177.     if (eval->chlayout_str) {
  178.         if (!strcmp(eval->chlayout_str, "same") && !strcmp(ctx->filter->name, "aeval")) {
  179.             eval->same_chlayout = 1;
  180.         } else {
  181.             ret = ff_parse_channel_layout(&eval->chlayout, NULL, eval->chlayout_str, ctx);
  182.             if (ret < 0)
  183.                 return ret;
  184.  
  185.             ret = parse_channel_expressions(ctx, av_get_channel_layout_nb_channels(eval->chlayout));
  186.             if (ret < 0)
  187.                 return ret;
  188.         }
  189.     } else {
  190.         /* guess channel layout from nb expressions/channels */
  191.         if ((ret = parse_channel_expressions(ctx, -1)) < 0)
  192.             return ret;
  193.  
  194.         eval->chlayout = av_get_default_channel_layout(eval->nb_channels);
  195.         if (!eval->chlayout && eval->nb_channels <= 0) {
  196.             av_log(ctx, AV_LOG_ERROR, "Invalid number of channels '%d' provided\n",
  197.                    eval->nb_channels);
  198.             return AVERROR(EINVAL);
  199.         }
  200.     }
  201.  
  202.     if (eval->sample_rate_str)
  203.         if ((ret = ff_parse_sample_rate(&eval->sample_rate, eval->sample_rate_str, ctx)))
  204.             return ret;
  205.     eval->n = 0;
  206.  
  207.     return ret;
  208. }
  209.  
  210. static av_cold void uninit(AVFilterContext *ctx)
  211. {
  212.     EvalContext *eval = ctx->priv;
  213.     int i;
  214.  
  215.     for (i = 0; i < eval->nb_channels; i++) {
  216.         av_expr_free(eval->expr[i]);
  217.         eval->expr[i] = NULL;
  218.     }
  219.     av_freep(&eval->expr);
  220.     av_freep(&eval->channel_values);
  221. }
  222.  
  223. static int config_props(AVFilterLink *outlink)
  224. {
  225.     EvalContext *eval = outlink->src->priv;
  226.     char buf[128];
  227.  
  228.     outlink->time_base = (AVRational){1, eval->sample_rate};
  229.     outlink->sample_rate = eval->sample_rate;
  230.  
  231.     eval->var_values[VAR_S] = eval->sample_rate;
  232.     eval->var_values[VAR_NB_IN_CHANNELS] = NAN;
  233.     eval->var_values[VAR_NB_OUT_CHANNELS] = outlink->channels;
  234.  
  235.     av_get_channel_layout_string(buf, sizeof(buf), 0, eval->chlayout);
  236.  
  237.     av_log(outlink->src, AV_LOG_VERBOSE,
  238.            "sample_rate:%d chlayout:%s duration:%"PRId64"\n",
  239.            eval->sample_rate, buf, eval->duration);
  240.  
  241.     return 0;
  242. }
  243.  
  244. static int query_formats(AVFilterContext *ctx)
  245. {
  246.     EvalContext *eval = ctx->priv;
  247.     static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE };
  248.     int64_t chlayouts[] = { eval->chlayout ? eval->chlayout : FF_COUNT2LAYOUT(eval->nb_channels) , -1 };
  249.     int sample_rates[] = { eval->sample_rate, -1 };
  250.     AVFilterFormats *formats;
  251.     AVFilterChannelLayouts *layouts;
  252.     int ret;
  253.  
  254.     formats = ff_make_format_list(sample_fmts);
  255.     if (!formats)
  256.         return AVERROR(ENOMEM);
  257.     ret = ff_set_common_formats (ctx, formats);
  258.     if (ret < 0)
  259.         return ret;
  260.  
  261.     layouts = avfilter_make_format64_list(chlayouts);
  262.     if (!layouts)
  263.         return AVERROR(ENOMEM);
  264.     ret = ff_set_common_channel_layouts(ctx, layouts);
  265.     if (ret < 0)
  266.         return ret;
  267.  
  268.     formats = ff_make_format_list(sample_rates);
  269.     if (!formats)
  270.         return AVERROR(ENOMEM);
  271.     return ff_set_common_samplerates(ctx, formats);
  272. }
  273.  
  274. static int request_frame(AVFilterLink *outlink)
  275. {
  276.     EvalContext *eval = outlink->src->priv;
  277.     AVFrame *samplesref;
  278.     int i, j;
  279.     int64_t t = av_rescale(eval->n, AV_TIME_BASE, eval->sample_rate);
  280.  
  281.     if (eval->duration >= 0 && t >= eval->duration)
  282.         return AVERROR_EOF;
  283.  
  284.     samplesref = ff_get_audio_buffer(outlink, eval->nb_samples);
  285.     if (!samplesref)
  286.         return AVERROR(ENOMEM);
  287.  
  288.     /* evaluate expression for each single sample and for each channel */
  289.     for (i = 0; i < eval->nb_samples; i++, eval->n++) {
  290.         eval->var_values[VAR_N] = eval->n;
  291.         eval->var_values[VAR_T] = eval->var_values[VAR_N] * (double)1/eval->sample_rate;
  292.  
  293.         for (j = 0; j < eval->nb_channels; j++) {
  294.             *((double *) samplesref->extended_data[j] + i) =
  295.                 av_expr_eval(eval->expr[j], eval->var_values, NULL);
  296.         }
  297.     }
  298.  
  299.     samplesref->pts = eval->pts;
  300.     samplesref->sample_rate = eval->sample_rate;
  301.     eval->pts += eval->nb_samples;
  302.  
  303.     return ff_filter_frame(outlink, samplesref);
  304. }
  305.  
  306. #if CONFIG_AEVALSRC_FILTER
  307. static const AVFilterPad aevalsrc_outputs[] = {
  308.     {
  309.         .name          = "default",
  310.         .type          = AVMEDIA_TYPE_AUDIO,
  311.         .config_props  = config_props,
  312.         .request_frame = request_frame,
  313.     },
  314.     { NULL }
  315. };
  316.  
  317. AVFilter ff_asrc_aevalsrc = {
  318.     .name          = "aevalsrc",
  319.     .description   = NULL_IF_CONFIG_SMALL("Generate an audio signal generated by an expression."),
  320.     .query_formats = query_formats,
  321.     .init          = init,
  322.     .uninit        = uninit,
  323.     .priv_size     = sizeof(EvalContext),
  324.     .inputs        = NULL,
  325.     .outputs       = aevalsrc_outputs,
  326.     .priv_class    = &aevalsrc_class,
  327. };
  328.  
  329. #endif /* CONFIG_AEVALSRC_FILTER */
  330.  
  331. #define OFFSET(x) offsetof(EvalContext, x)
  332. #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
  333.  
  334. static const AVOption aeval_options[]= {
  335.     { "exprs", "set the '|'-separated list of channels expressions", OFFSET(exprs), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = FLAGS },
  336.     { "channel_layout", "set channel layout", OFFSET(chlayout_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
  337.     { "c",              "set channel layout", OFFSET(chlayout_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
  338.     { NULL }
  339. };
  340.  
  341. AVFILTER_DEFINE_CLASS(aeval);
  342.  
  343. static int aeval_query_formats(AVFilterContext *ctx)
  344. {
  345.     AVFilterFormats *formats = NULL;
  346.     AVFilterChannelLayouts *layouts;
  347.     AVFilterLink *inlink  = ctx->inputs[0];
  348.     AVFilterLink *outlink  = ctx->outputs[0];
  349.     EvalContext *eval = ctx->priv;
  350.     static const enum AVSampleFormat sample_fmts[] = {
  351.         AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE
  352.     };
  353.  
  354.     // inlink supports any channel layout
  355.     layouts = ff_all_channel_counts();
  356.     ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts);
  357.  
  358.     if (eval->same_chlayout) {
  359.         layouts = ff_all_channel_counts();
  360.         if (!layouts)
  361.             return AVERROR(ENOMEM);
  362.             ff_set_common_channel_layouts(ctx, layouts);
  363.     } else {
  364.         // outlink supports only requested output channel layout
  365.         layouts = NULL;
  366.         ff_add_channel_layout(&layouts,
  367.                               eval->out_channel_layout ? eval->out_channel_layout :
  368.                               FF_COUNT2LAYOUT(eval->nb_channels));
  369.         ff_channel_layouts_ref(layouts, &outlink->in_channel_layouts);
  370.     }
  371.  
  372.     formats = ff_make_format_list(sample_fmts);
  373.     if (!formats)
  374.         return AVERROR(ENOMEM);
  375.     ff_set_common_formats(ctx, formats);
  376.  
  377.     formats = ff_all_samplerates();
  378.     if (!formats)
  379.         return AVERROR(ENOMEM);
  380.     ff_set_common_samplerates(ctx, formats);
  381.  
  382.     return 0;
  383. }
  384.  
  385. static int aeval_config_output(AVFilterLink *outlink)
  386. {
  387.     AVFilterContext *ctx = outlink->src;
  388.     EvalContext *eval = ctx->priv;
  389.     AVFilterLink *inlink = ctx->inputs[0];
  390.     int ret;
  391.  
  392.     if (eval->same_chlayout) {
  393.         eval->chlayout = inlink->channel_layout;
  394.  
  395.         if ((ret = parse_channel_expressions(ctx, inlink->channels)) < 0)
  396.             return ret;
  397.     }
  398.  
  399.     eval->n = 0;
  400.     eval->nb_in_channels = eval->var_values[VAR_NB_IN_CHANNELS] = inlink->channels;
  401.     eval->var_values[VAR_NB_OUT_CHANNELS] = outlink->channels;
  402.     eval->var_values[VAR_S] = inlink->sample_rate;
  403.     eval->var_values[VAR_T] = NAN;
  404.  
  405.     eval->channel_values = av_realloc_f(eval->channel_values,
  406.                                         inlink->channels, sizeof(*eval->channel_values));
  407.     if (!eval->channel_values)
  408.         return AVERROR(ENOMEM);
  409.  
  410.     return 0;
  411. }
  412.  
  413. #define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)*av_q2d(tb))
  414.  
  415. static int filter_frame(AVFilterLink *inlink, AVFrame *in)
  416. {
  417.     EvalContext *eval     = inlink->dst->priv;
  418.     AVFilterLink *outlink = inlink->dst->outputs[0];
  419.     int nb_samples        = in->nb_samples;
  420.     AVFrame *out;
  421.     double t0;
  422.     int i, j;
  423.  
  424.     /* do volume scaling in-place if input buffer is writable */
  425.     out = ff_get_audio_buffer(outlink, nb_samples);
  426.     if (!out)
  427.         return AVERROR(ENOMEM);
  428.     av_frame_copy_props(out, in);
  429.  
  430.     t0 = TS2T(in->pts, inlink->time_base);
  431.  
  432.     /* evaluate expression for each single sample and for each channel */
  433.     for (i = 0; i < nb_samples; i++, eval->n++) {
  434.         eval->var_values[VAR_N] = eval->n;
  435.         eval->var_values[VAR_T] = t0 + i * (double)1/inlink->sample_rate;
  436.  
  437.         for (j = 0; j < inlink->channels; j++)
  438.             eval->channel_values[j] = *((double *) in->extended_data[j] + i);
  439.  
  440.         for (j = 0; j < outlink->channels; j++) {
  441.             eval->var_values[VAR_CH] = j;
  442.             *((double *) out->extended_data[j] + i) =
  443.                 av_expr_eval(eval->expr[j], eval->var_values, eval);
  444.         }
  445.     }
  446.  
  447.     av_frame_free(&in);
  448.     return ff_filter_frame(outlink, out);
  449. }
  450.  
  451. #if CONFIG_AEVAL_FILTER
  452.  
  453. static const AVFilterPad aeval_inputs[] = {
  454.     {
  455.         .name           = "default",
  456.         .type           = AVMEDIA_TYPE_AUDIO,
  457.         .filter_frame   = filter_frame,
  458.     },
  459.     { NULL }
  460. };
  461.  
  462. static const AVFilterPad aeval_outputs[] = {
  463.     {
  464.         .name          = "default",
  465.         .type          = AVMEDIA_TYPE_AUDIO,
  466.         .config_props  = aeval_config_output,
  467.     },
  468.     { NULL }
  469. };
  470.  
  471. AVFilter ff_af_aeval = {
  472.     .name          = "aeval",
  473.     .description   = NULL_IF_CONFIG_SMALL("Filter audio signal according to a specified expression."),
  474.     .query_formats = aeval_query_formats,
  475.     .init          = init,
  476.     .uninit        = uninit,
  477.     .priv_size     = sizeof(EvalContext),
  478.     .inputs        = aeval_inputs,
  479.     .outputs       = aeval_outputs,
  480.     .priv_class    = &aeval_class,
  481. };
  482.  
  483. #endif /* CONFIG_AEVAL_FILTER */
  484.