/*
 * Copyright (c) 2011 Stefano Sabatini
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/**
 * @file
 * eval audio source
 */

#include "libavutil/audioconvert.h"
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/eval.h"
#include "libavutil/opt.h"
#include "libavutil/parseutils.h"
#include "avfilter.h"
#include "internal.h"

static const char * const var_names[] = {
    "n",            ///< number of frame
    "t",            ///< timestamp expressed in seconds
    "s",            ///< sample rate
    NULL
};

enum var_name {
    VAR_N,
    VAR_T,
    VAR_S,
    VAR_VARS_NB
};

typedef struct {
    const AVClass *class;
    char *sample_rate_str;
    int sample_rate;
    int64_t chlayout;
    int nb_channels;
    int64_t pts;
    AVExpr *expr[8];
    char *expr_str[8];
    int nb_samples;             ///< number of samples per requested frame
    char *duration_str;         ///< total duration of the generated audio
    double duration;
    uint64_t n;
    double var_values[VAR_VARS_NB];
} EvalContext;

#define OFFSET(x) offsetof(EvalContext, x)

static const AVOption eval_options[]= {
    { "nb_samples",  "set the number of samples per requested frame", OFFSET(nb_samples),      AV_OPT_TYPE_INT,    {.dbl = 1024},    0,        INT_MAX },
    { "n",           "set the number of samples per requested frame", OFFSET(nb_samples),      AV_OPT_TYPE_INT,    {.dbl = 1024},    0,        INT_MAX },
    { "sample_rate", "set the sample rate",                           OFFSET(sample_rate_str), AV_OPT_TYPE_STRING, {.str = "44100"}, CHAR_MIN, CHAR_MAX },
    { "s",           "set the sample rate",                           OFFSET(sample_rate_str), AV_OPT_TYPE_STRING, {.str = "44100"}, CHAR_MIN, CHAR_MAX },
    { "duration",    "set audio duration", OFFSET(duration_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0 },
    { "d",           "set audio duration", OFFSET(duration_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0 },
{NULL},
};

static const char *eval_get_name(void *ctx)
{
    return "aevalsrc";
}

static const AVClass eval_class = {
    "AEvalSrcContext",
    eval_get_name,
    eval_options
};

static int init(AVFilterContext *ctx, const char *args, void *opaque)
{
    EvalContext *eval = ctx->priv;
    char *args1 = av_strdup(args);
    char *expr, *buf, *bufptr;
    int ret, i;

    eval->class = &eval_class;
    av_opt_set_defaults(eval);

    if (!args1) {
        av_log(ctx, AV_LOG_ERROR, "Argument is empty\n");
        ret = args ? AVERROR(ENOMEM) : AVERROR(EINVAL);
        goto end;
    }

    /* parse expressions */
    buf = args1;
    i = 0;
    while (expr = av_strtok(buf, ":", &bufptr)) {
        if (i >= 8) {
            av_log(ctx, AV_LOG_ERROR,
                   "More than 8 expressions provided, unsupported.\n");
            ret = AVERROR(EINVAL);
            return ret;
        }
        ret = av_expr_parse(&eval->expr[i], expr, var_names,
                            NULL, NULL, NULL, NULL, 0, ctx);
        if (ret < 0)
            goto end;
        i++;
        if (bufptr && *bufptr == ':') { /* found last expression */
            bufptr++;
            break;
        }
        buf = NULL;
    }

    /* guess channel layout from nb expressions/channels */
    eval->nb_channels = i;
    eval->chlayout = av_get_default_channel_layout(eval->nb_channels);
    if (!eval->chlayout) {
        av_log(ctx, AV_LOG_ERROR, "Invalid number of channels '%d' provided\n",
               eval->nb_channels);
        ret = AVERROR(EINVAL);
        goto end;
    }

    if (bufptr && (ret = av_set_options_string(eval, bufptr, "=", ":")) < 0)
        goto end;

    if ((ret = ff_parse_sample_rate(&eval->sample_rate, eval->sample_rate_str, ctx)))
        goto end;

    eval->duration = -1;
    if (eval->duration_str) {
        int64_t us = -1;
        if ((ret = av_parse_time(&us, eval->duration_str, 1)) < 0) {
            av_log(ctx, AV_LOG_ERROR, "Invalid duration: '%s'\n", eval->duration_str);
            goto end;
        }
        eval->duration = (double)us / 1000000;
    }
    eval->n = 0;

end:
    av_free(args1);
    return ret;
}

static void uninit(AVFilterContext *ctx)
{
    EvalContext *eval = ctx->priv;
    int i;

    for (i = 0; i < 8; i++) {
        av_expr_free(eval->expr[i]);
        eval->expr[i] = NULL;
    }
    av_freep(&eval->duration_str);
    av_freep(&eval->sample_rate_str);
}

static int config_props(AVFilterLink *outlink)
{
    EvalContext *eval = outlink->src->priv;
    char buf[128];

    outlink->time_base = (AVRational){1, eval->sample_rate};
    outlink->sample_rate = eval->sample_rate;

    eval->var_values[VAR_S] = eval->sample_rate;

    av_get_channel_layout_string(buf, sizeof(buf), 0, eval->chlayout);

    av_log(outlink->src, AV_LOG_INFO,
           "sample_rate:%d chlayout:%s duration:%f\n",
           eval->sample_rate, buf, eval->duration);

    return 0;
}

static int query_formats(AVFilterContext *ctx)
{
    EvalContext *eval = ctx->priv;
    enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_NONE };
    int64_t chlayouts[] = { eval->chlayout, -1 };
    int packing_fmts[] = { AVFILTER_PLANAR, -1 };

    avfilter_set_common_sample_formats (ctx, avfilter_make_format_list(sample_fmts));
    avfilter_set_common_channel_layouts(ctx, avfilter_make_format64_list(chlayouts));
    avfilter_set_common_packing_formats(ctx, avfilter_make_format_list(packing_fmts));

    return 0;
}

static int request_frame(AVFilterLink *outlink)
{
    EvalContext *eval = outlink->src->priv;
    AVFilterBufferRef *samplesref;
    int i, j;
    double t = eval->var_values[VAR_N] * (double)1/eval->sample_rate;

    if (eval->duration >= 0 && t > eval->duration)
        return AVERROR_EOF;

    samplesref = avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, eval->nb_samples);

    /* evaluate expression for each single sample and for each channel */
    for (i = 0; i < eval->nb_samples; i++, eval->n++) {
        eval->var_values[VAR_N] = eval->n;
        eval->var_values[VAR_T] = eval->var_values[VAR_N] * (double)1/eval->sample_rate;

        for (j = 0; j < eval->nb_channels; j++) {
            *((double *) samplesref->data[j] + i) =
                av_expr_eval(eval->expr[j], eval->var_values, NULL);
        }
    }

    samplesref->pts = eval->pts;
    samplesref->pos = -1;
    samplesref->audio->sample_rate = eval->sample_rate;
    eval->pts += eval->nb_samples;

    avfilter_filter_samples(outlink, samplesref);

    return 0;
}

AVFilter avfilter_asrc_aevalsrc = {
    .name        = "aevalsrc",
    .description = NULL_IF_CONFIG_SMALL("Generate an audio signal generated by an expression."),

    .query_formats = query_formats,
    .init        = init,
    .uninit      = uninit,
    .priv_size   = sizeof(EvalContext),

    .inputs      = (const AVFilterPad[]) {{ .name = NULL}},

    .outputs     = (const AVFilterPad[]) {{ .name = "default",
                                      .type = AVMEDIA_TYPE_AUDIO,
                                      .config_props = config_props,
                                      .request_frame = request_frame, },
                                    { .name = NULL}},
};
