/*
 * Interface to libshine for mp3 encoding
 * Copyright (c) 2012 Paul B Mahol
 *
 * 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 <shine/layer3.h>

#include "libavutil/intreadwrite.h"
#include "audio_frame_queue.h"
#include "avcodec.h"
#include "internal.h"
#include "mpegaudio.h"
#include "mpegaudiodecheader.h"

#define BUFFER_SIZE (4096 * 20)

typedef struct SHINEContext {
    shine_config_t  config;
    shine_t         shine;
    uint8_t         buffer[BUFFER_SIZE];
    int             buffer_index;
    AudioFrameQueue afq;
} SHINEContext;

static av_cold int libshine_encode_init(AVCodecContext *avctx)
{
    SHINEContext *s = avctx->priv_data;

    if (avctx->channels <= 0 || avctx->channels > 2){
        av_log(avctx, AV_LOG_ERROR, "only mono or stereo is supported\n");
        return AVERROR(EINVAL);
    }

    shine_set_config_mpeg_defaults(&s->config.mpeg);
    if (avctx->bit_rate)
        s->config.mpeg.bitr = avctx->bit_rate / 1000;
    s->config.mpeg.mode = avctx->channels == 2 ? STEREO : MONO;
    s->config.wave.samplerate = avctx->sample_rate;
    s->config.wave.channels   = avctx->channels == 2 ? PCM_STEREO : PCM_MONO;
    if (shine_check_config(s->config.wave.samplerate, s->config.mpeg.bitr) < 0) {
        av_log(avctx, AV_LOG_ERROR, "invalid configuration\n");
        return AVERROR(EINVAL);
    }
    s->shine = shine_initialise(&s->config);
    if (!s->shine)
        return AVERROR(ENOMEM);
    avctx->frame_size = shine_samples_per_pass(s->shine);
    ff_af_queue_init(avctx, &s->afq);
    return 0;
}

static int libshine_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
                                 const AVFrame *frame, int *got_packet_ptr)
{
    SHINEContext *s = avctx->priv_data;
    MPADecodeHeader hdr;
    unsigned char *data;
    int written;
    int ret, len;

    if (frame)
        data = shine_encode_buffer(s->shine, (int16_t **)frame->data, &written);
    else
        data = shine_flush(s->shine, &written);
    if (written < 0)
        return -1;
    if (written > 0) {
        if (s->buffer_index + written > BUFFER_SIZE) {
            av_log(avctx, AV_LOG_ERROR, "internal buffer too small\n");
            return AVERROR_BUG;
        }
        memcpy(s->buffer + s->buffer_index, data, written);
        s->buffer_index += written;
    }
    if (frame) {
        if ((ret = ff_af_queue_add(&s->afq, frame)) < 0)
            return ret;
    }

    if (s->buffer_index < 4 || !s->afq.frame_count)
        return 0;
    if (avpriv_mpegaudio_decode_header(&hdr, AV_RB32(s->buffer))) {
        av_log(avctx, AV_LOG_ERROR, "free format output not supported\n");
        return -1;
    }

    len = hdr.frame_size;
    if (len <= s->buffer_index) {
        if ((ret = ff_alloc_packet2(avctx, avpkt, len, 0)))
            return ret;
        memcpy(avpkt->data, s->buffer, len);
        s->buffer_index -= len;
        memmove(s->buffer, s->buffer + len, s->buffer_index);

        ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
                           &avpkt->duration);

        avpkt->size = len;
        *got_packet_ptr = 1;
    }
    return 0;
}

static av_cold int libshine_encode_close(AVCodecContext *avctx)
{
    SHINEContext *s = avctx->priv_data;

    ff_af_queue_close(&s->afq);
    shine_close(s->shine);
    return 0;
}

static const int libshine_sample_rates[] = {
    44100, 48000, 32000, 0
};

AVCodec ff_libshine_encoder = {
    .name                  = "libshine",
    .long_name             = NULL_IF_CONFIG_SMALL("libshine MP3 (MPEG audio layer 3)"),
    .type                  = AVMEDIA_TYPE_AUDIO,
    .id                    = AV_CODEC_ID_MP3,
    .priv_data_size        = sizeof(SHINEContext),
    .init                  = libshine_encode_init,
    .encode2               = libshine_encode_frame,
    .close                 = libshine_encode_close,
    .capabilities          = AV_CODEC_CAP_DELAY,
    .sample_fmts           = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16P,
                                                            AV_SAMPLE_FMT_NONE },
    .supported_samplerates = libshine_sample_rates,
    .channel_layouts       = (const uint64_t[]) { AV_CH_LAYOUT_MONO,
                                                  AV_CH_LAYOUT_STEREO,
                                                  0 },
};
