/*
 * Xiph CELT decoder using libcelt
 * Copyright (c) 2011 Nicolas George
 *
 * 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 <celt/celt.h>
#include <celt/celt_header.h>
#include "avcodec.h"
#include "codec_internal.h"
#include "decode.h"
#include "libavutil/intreadwrite.h"

struct libcelt_context {
    CELTMode *mode;
    CELTDecoder *dec;
    int discard;
};

static int ff_celt_error_to_averror(int err)
{
    switch (err) {
        case CELT_BAD_ARG:          return AVERROR(EINVAL);
#ifdef CELT_BUFFER_TOO_SMALL
        case CELT_BUFFER_TOO_SMALL: return AVERROR(ENOBUFS);
#endif
        case CELT_INTERNAL_ERROR:   return AVERROR(EFAULT);
        case CELT_CORRUPTED_DATA:   return AVERROR_INVALIDDATA;
        case CELT_UNIMPLEMENTED:    return AVERROR(ENOSYS);
#ifdef ENOTRECOVERABLE
        case CELT_INVALID_STATE:    return AVERROR(ENOTRECOVERABLE);
#endif
        case CELT_ALLOC_FAIL:       return AVERROR(ENOMEM);
        default:                    return AVERROR(EINVAL);
    }
}

static int ff_celt_bitstream_version_hack(CELTMode *mode)
{
    CELTHeader header = { .version_id = 0 };
    celt_header_init(&header, mode, 960, 2);
    return header.version_id;
}

static av_cold int libcelt_dec_init(AVCodecContext *c)
{
    struct libcelt_context *celt = c->priv_data;
    int err;

    if (!c->ch_layout.nb_channels || !c->frame_size ||
        c->frame_size > INT_MAX / sizeof(int16_t) / c->ch_layout.nb_channels)
        return AVERROR(EINVAL);
    celt->mode = celt_mode_create(c->sample_rate, c->frame_size, &err);
    if (!celt->mode)
        return ff_celt_error_to_averror(err);
    celt->dec = celt_decoder_create_custom(celt->mode, c->ch_layout.nb_channels, &err);
    if (!celt->dec) {
        celt_mode_destroy(celt->mode);
        return ff_celt_error_to_averror(err);
    }
    if (c->extradata_size >= 4) {
        celt->discard = AV_RL32(c->extradata);
        if (celt->discard < 0 || celt->discard >= c->frame_size) {
            av_log(c, AV_LOG_WARNING,
                   "Invalid overlap (%d), ignored.\n", celt->discard);
            celt->discard = 0;
        }
    }
    if (c->extradata_size >= 8) {
        unsigned version = AV_RL32(c->extradata + 4);
        unsigned lib_version = ff_celt_bitstream_version_hack(celt->mode);
        if (version != lib_version)
            av_log(c, AV_LOG_WARNING,
                   "CELT bitstream version 0x%x may be "
                   "improperly decoded by libcelt for version 0x%x.\n",
                   version, lib_version);
    }
    c->sample_fmt = AV_SAMPLE_FMT_S16;
    return 0;
}

static av_cold int libcelt_dec_close(AVCodecContext *c)
{
    struct libcelt_context *celt = c->priv_data;

    celt_decoder_destroy(celt->dec);
    celt_mode_destroy(celt->mode);
    return 0;
}

static int libcelt_dec_decode(AVCodecContext *c, AVFrame *frame,
                              int *got_frame_ptr, AVPacket *pkt)
{
    struct libcelt_context *celt = c->priv_data;
    int err;
    int16_t *pcm;

    frame->nb_samples = c->frame_size;
    if ((err = ff_get_buffer(c, frame, 0)) < 0)
        return err;
    pcm = (int16_t *)frame->data[0];
    err = celt_decode(celt->dec, pkt->data, pkt->size, pcm, c->frame_size);
    if (err < 0)
        return ff_celt_error_to_averror(err);
    if (celt->discard) {
        frame->nb_samples -= celt->discard;
        memmove(pcm, pcm + celt->discard * c->ch_layout.nb_channels,
                frame->nb_samples * c->ch_layout.nb_channels * sizeof(int16_t));
        celt->discard = 0;
    }
    *got_frame_ptr = 1;
    return pkt->size;
}

const FFCodec ff_libcelt_decoder = {
    .p.name         = "libcelt",
    CODEC_LONG_NAME("Xiph CELT decoder using libcelt"),
    .p.type         = AVMEDIA_TYPE_AUDIO,
    .p.id           = AV_CODEC_ID_CELT,
    .p.capabilities = AV_CODEC_CAP_DR1,
    .p.wrapper_name = "libcelt",
    .caps_internal  = FF_CODEC_CAP_NOT_INIT_THREADSAFE,
    .priv_data_size = sizeof(struct libcelt_context),
    .init           = libcelt_dec_init,
    .close          = libcelt_dec_close,
    FF_CODEC_DECODE_CB(libcelt_dec_decode),
};
