/*
 * WMA compatible encoder
 * Copyright (c) 2007 Michael Niedermayer
 *
 * 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
 */

#include "avcodec.h"
#include "wma.h"

#undef NDEBUG
#include <assert.h>


static int encode_init(AVCodecContext * avctx){
    WMACodecContext *s = avctx->priv_data;
    int i, flags1, flags2;
    uint8_t *extradata;

    s->avctx = avctx;

    if(avctx->channels > MAX_CHANNELS) {
        av_log(avctx, AV_LOG_ERROR, "too many channels: got %i, need %i or fewer",
               avctx->channels, MAX_CHANNELS);
        return AVERROR(EINVAL);
    }

    if(avctx->bit_rate < 24*1000) {
        av_log(avctx, AV_LOG_ERROR, "bitrate too low: got %i, need 24000 or higher\n",
               avctx->bit_rate);
        return AVERROR(EINVAL);
    }

    /* extract flag infos */
    flags1 = 0;
    flags2 = 1;
    if (avctx->codec->id == CODEC_ID_WMAV1) {
        extradata= av_malloc(4);
        avctx->extradata_size= 4;
        AV_WL16(extradata, flags1);
        AV_WL16(extradata+2, flags2);
    } else if (avctx->codec->id == CODEC_ID_WMAV2) {
        extradata= av_mallocz(10);
        avctx->extradata_size= 10;
        AV_WL32(extradata, flags1);
        AV_WL16(extradata+4, flags2);
    }else
        assert(0);
    avctx->extradata= extradata;
    s->use_exp_vlc = flags2 & 0x0001;
    s->use_bit_reservoir = flags2 & 0x0002;
    s->use_variable_block_len = flags2 & 0x0004;

    ff_wma_init(avctx, flags2);

    /* init MDCT */
    for(i = 0; i < s->nb_block_sizes; i++)
        ff_mdct_init(&s->mdct_ctx[i], s->frame_len_bits - i + 1, 0, 1.0);

    avctx->block_align=
    s->block_align= avctx->bit_rate*(int64_t)s->frame_len / (avctx->sample_rate*8);
//av_log(NULL, AV_LOG_ERROR, "%d %d %d %d\n", s->block_align, avctx->bit_rate, s->frame_len, avctx->sample_rate);
    avctx->frame_size= s->frame_len;

    return 0;
}


static void apply_window_and_mdct(AVCodecContext * avctx, const signed short * audio, int len) {
    WMACodecContext *s = avctx->priv_data;
    int window_index= s->frame_len_bits - s->block_len_bits;
    FFTContext *mdct = &s->mdct_ctx[window_index];
    int i, j, channel;
    const float * win = s->windows[window_index];
    int window_len = 1 << s->block_len_bits;
    float n = window_len/2;

    for (channel = 0; channel < avctx->channels; channel++) {
        memcpy(s->output, s->frame_out[channel], sizeof(float)*window_len);
        j = channel;
        for (i = 0; i < len; i++, j += avctx->channels){
            s->output[i+window_len]  = audio[j] / n * win[window_len - i - 1];
            s->frame_out[channel][i] = audio[j] / n * win[i];
        }
        mdct->mdct_calc(mdct, s->coefs[channel], s->output);
    }
}

//FIXME use for decoding too
static void init_exp(WMACodecContext *s, int ch, const int *exp_param){
    int n;
    const uint16_t *ptr;
    float v, *q, max_scale, *q_end;

    ptr = s->exponent_bands[s->frame_len_bits - s->block_len_bits];
    q = s->exponents[ch];
    q_end = q + s->block_len;
    max_scale = 0;
    while (q < q_end) {
        /* XXX: use a table */
        v = pow(10, *exp_param++ * (1.0 / 16.0));
        max_scale= FFMAX(max_scale, v);
        n = *ptr++;
        do {
            *q++ = v;
        } while (--n);
    }
    s->max_exponent[ch] = max_scale;
}

static void encode_exp_vlc(WMACodecContext *s, int ch, const int *exp_param){
    int last_exp;
    const uint16_t *ptr;
    float *q, *q_end;

    ptr = s->exponent_bands[s->frame_len_bits - s->block_len_bits];
    q = s->exponents[ch];
    q_end = q + s->block_len;
    if (s->version == 1) {
        last_exp= *exp_param++;
        assert(last_exp-10 >= 0 && last_exp-10 < 32);
        put_bits(&s->pb, 5, last_exp - 10);
        q+= *ptr++;
    }else
        last_exp = 36;
    while (q < q_end) {
        int exp = *exp_param++;
        int code = exp - last_exp + 60;
        assert(code >= 0 && code < 120);
        put_bits(&s->pb, ff_aac_scalefactor_bits[code], ff_aac_scalefactor_code[code]);
        /* XXX: use a table */
        q+= *ptr++;
        last_exp= exp;
    }
}

static int encode_block(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], int total_gain){
    int v, bsize, ch, coef_nb_bits, parse_exponents;
    float mdct_norm;
    int nb_coefs[MAX_CHANNELS];
    static const int fixed_exp[25]={20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20};

    //FIXME remove duplication relative to decoder
    if (s->use_variable_block_len) {
        assert(0); //FIXME not implemented
    }else{
        /* fixed block len */
        s->next_block_len_bits = s->frame_len_bits;
        s->prev_block_len_bits = s->frame_len_bits;
        s->block_len_bits = s->frame_len_bits;
    }

    s->block_len = 1 << s->block_len_bits;
//     assert((s->block_pos + s->block_len) <= s->frame_len);
    bsize = s->frame_len_bits - s->block_len_bits;

    //FIXME factor
    v = s->coefs_end[bsize] - s->coefs_start;
    for(ch = 0; ch < s->nb_channels; ch++)
        nb_coefs[ch] = v;
    {
        int n4 = s->block_len / 2;
        mdct_norm = 1.0 / (float)n4;
        if (s->version == 1) {
            mdct_norm *= sqrt(n4);
        }
    }

    if (s->nb_channels == 2) {
        put_bits(&s->pb, 1, s->ms_stereo= 1);
    }

    for(ch = 0; ch < s->nb_channels; ch++) {
        s->channel_coded[ch] = 1; //FIXME only set channel_coded when needed, instead of always
        if (s->channel_coded[ch]) {
            init_exp(s, ch, fixed_exp);
        }
    }

    for(ch = 0; ch < s->nb_channels; ch++) {
        if (s->channel_coded[ch]) {
            WMACoef *coefs1;
            float *coefs, *exponents, mult;
            int i, n;

            coefs1 = s->coefs1[ch];
            exponents = s->exponents[ch];
            mult = pow(10, total_gain * 0.05) / s->max_exponent[ch];
            mult *= mdct_norm;
            coefs = src_coefs[ch];
            if (s->use_noise_coding && 0) {
                assert(0); //FIXME not implemented
            } else {
                coefs += s->coefs_start;
                n = nb_coefs[ch];
                for(i = 0;i < n; i++){
                    double t= *coefs++ / (exponents[i] * mult);
                    if(t<-32768 || t>32767)
                        return -1;

                    coefs1[i] = lrint(t);
                }
            }
        }
    }

    v = 0;
    for(ch = 0; ch < s->nb_channels; ch++) {
        int a = s->channel_coded[ch];
        put_bits(&s->pb, 1, a);
        v |= a;
    }

    if (!v)
        return 1;

    for(v= total_gain-1; v>=127; v-= 127)
        put_bits(&s->pb, 7, 127);
    put_bits(&s->pb, 7, v);

    coef_nb_bits= ff_wma_total_gain_to_bits(total_gain);

    if (s->use_noise_coding) {
        for(ch = 0; ch < s->nb_channels; ch++) {
            if (s->channel_coded[ch]) {
                int i, n;
                n = s->exponent_high_sizes[bsize];
                for(i=0;i<n;i++) {
                    put_bits(&s->pb, 1, s->high_band_coded[ch][i]= 0);
                    if (0)
                        nb_coefs[ch] -= s->exponent_high_bands[bsize][i];
                }
            }
        }
    }

    parse_exponents = 1;
    if (s->block_len_bits != s->frame_len_bits) {
        put_bits(&s->pb, 1, parse_exponents);
    }

    if (parse_exponents) {
        for(ch = 0; ch < s->nb_channels; ch++) {
            if (s->channel_coded[ch]) {
                if (s->use_exp_vlc) {
                    encode_exp_vlc(s, ch, fixed_exp);
                } else {
                    assert(0); //FIXME not implemented
//                    encode_exp_lsp(s, ch);
                }
            }
        }
    } else {
        assert(0); //FIXME not implemented
    }

    for(ch = 0; ch < s->nb_channels; ch++) {
        if (s->channel_coded[ch]) {
            int run, tindex;
            WMACoef *ptr, *eptr;
            tindex = (ch == 1 && s->ms_stereo);
            ptr = &s->coefs1[ch][0];
            eptr = ptr + nb_coefs[ch];

            run=0;
            for(;ptr < eptr; ptr++){
                if(*ptr){
                    int level= *ptr;
                    int abs_level= FFABS(level);
                    int code= 0;
                    if(abs_level <= s->coef_vlcs[tindex]->max_level){
                        if(run < s->coef_vlcs[tindex]->levels[abs_level-1])
                            code= run + s->int_table[tindex][abs_level-1];
                    }

                    assert(code < s->coef_vlcs[tindex]->n);
                    put_bits(&s->pb, s->coef_vlcs[tindex]->huffbits[code], s->coef_vlcs[tindex]->huffcodes[code]);

                    if(code == 0){
                        if(1<<coef_nb_bits <= abs_level)
                            return -1;


                        //Workaround minor rounding differences for the regression tests, FIXME we should find and replace the problematic float by fixpoint for reg tests
                        if(abs_level == 0x71B && (s->avctx->flags & CODEC_FLAG_BITEXACT)) abs_level=0x71A;

                        put_bits(&s->pb, coef_nb_bits, abs_level);
                        put_bits(&s->pb, s->frame_len_bits, run);
                    }
                    put_bits(&s->pb, 1, level < 0); //FIXME the sign is fliped somewhere
                    run=0;
                }else{
                    run++;
                }
            }
            if(run)
                put_bits(&s->pb, s->coef_vlcs[tindex]->huffbits[1], s->coef_vlcs[tindex]->huffcodes[1]);
        }
        if (s->version == 1 && s->nb_channels >= 2) {
            align_put_bits(&s->pb);
        }
    }
    return 0;
}

static int encode_frame(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], uint8_t *buf, int buf_size, int total_gain){
    init_put_bits(&s->pb, buf, buf_size);

    if (s->use_bit_reservoir) {
        assert(0);//FIXME not implemented
    }else{
        if(encode_block(s, src_coefs, total_gain) < 0)
            return INT_MAX;
    }

    align_put_bits(&s->pb);

    return put_bits_count(&s->pb)/8 - s->block_align;
}

static int encode_superframe(AVCodecContext *avctx,
                            unsigned char *buf, int buf_size, void *data){
    WMACodecContext *s = avctx->priv_data;
    const short *samples = data;
    int i, total_gain;

    s->block_len_bits= s->frame_len_bits; //required by non variable block len
    s->block_len = 1 << s->block_len_bits;

    apply_window_and_mdct(avctx, samples, avctx->frame_size);

    if (s->ms_stereo) {
        float a, b;
        int i;

        for(i = 0; i < s->block_len; i++) {
            a = s->coefs[0][i]*0.5;
            b = s->coefs[1][i]*0.5;
            s->coefs[0][i] = a + b;
            s->coefs[1][i] = a - b;
        }
    }

#if 1
    total_gain= 128;
    for(i=64; i; i>>=1){
        int error= encode_frame(s, s->coefs, buf, buf_size, total_gain-i);
        if(error<0)
            total_gain-= i;
    }
#else
    total_gain= 90;
    best= encode_frame(s, s->coefs, buf, buf_size, total_gain);
    for(i=32; i; i>>=1){
        int scoreL= encode_frame(s, s->coefs, buf, buf_size, total_gain-i);
        int scoreR= encode_frame(s, s->coefs, buf, buf_size, total_gain+i);
        av_log(NULL, AV_LOG_ERROR, "%d %d %d (%d)\n", scoreL, best, scoreR, total_gain);
        if(scoreL < FFMIN(best, scoreR)){
            best = scoreL;
            total_gain -= i;
        }else if(scoreR < best){
            best = scoreR;
            total_gain += i;
        }
    }
#endif

    encode_frame(s, s->coefs, buf, buf_size, total_gain);
    assert((put_bits_count(&s->pb) & 7) == 0);
    i= s->block_align - (put_bits_count(&s->pb)+7)/8;
    assert(i>=0);
    while(i--)
        put_bits(&s->pb, 8, 'N');

    flush_put_bits(&s->pb);
    return put_bits_ptr(&s->pb) - s->pb.buf;
}

AVCodec ff_wmav1_encoder =
{
    "wmav1",
    AVMEDIA_TYPE_AUDIO,
    CODEC_ID_WMAV1,
    sizeof(WMACodecContext),
    encode_init,
    encode_superframe,
    ff_wma_end,
    .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
    .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 1"),
};

AVCodec ff_wmav2_encoder =
{
    "wmav2",
    AVMEDIA_TYPE_AUDIO,
    CODEC_ID_WMAV2,
    sizeof(WMACodecContext),
    encode_init,
    encode_superframe,
    ff_wma_end,
    .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
    .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 2"),
};
