/*
 * Creative Voice File demuxer.
 * Copyright (c) 2006  Aurelien Jacobs <aurel@gnuage.org>
 *
 * 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 "libavutil/intreadwrite.h"
#include "voc.h"
#include "internal.h"


static int voc_probe(AVProbeData *p)
{
    int version, check;

    if (memcmp(p->buf, ff_voc_magic, sizeof(ff_voc_magic) - 1))
        return 0;
    version = AV_RL16(p->buf + 22);
    check = AV_RL16(p->buf + 24);
    if (~version + 0x1234 != check)
        return 10;

    return AVPROBE_SCORE_MAX;
}

static int voc_read_header(AVFormatContext *s)
{
    VocDecContext *voc = s->priv_data;
    AVIOContext *pb = s->pb;
    int header_size;
    AVStream *st;

    avio_skip(pb, 20);
    header_size = avio_rl16(pb) - 22;
    if (header_size != 4) {
        av_log(s, AV_LOG_ERROR, "unknown header size: %d\n", header_size);
        return AVERROR(ENOSYS);
    }
    avio_skip(pb, header_size);
    st = avformat_new_stream(s, NULL);
    if (!st)
        return AVERROR(ENOMEM);
    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;

    voc->remaining_size = 0;
    return 0;
}

int
ff_voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size)
{
    VocDecContext *voc = s->priv_data;
    AVCodecContext *dec = st->codec;
    AVIOContext *pb = s->pb;
    VocType type;
    int size, tmp_codec=-1;
    int sample_rate = 0;
    int channels = 1;

    while (!voc->remaining_size) {
        type = avio_r8(pb);
        if (type == VOC_TYPE_EOF)
            return AVERROR(EIO);
        voc->remaining_size = avio_rl24(pb);
        if (!voc->remaining_size) {
            if (!s->pb->seekable)
                return AVERROR(EIO);
            voc->remaining_size = avio_size(pb) - avio_tell(pb);
        }
        max_size -= 4;

        switch (type) {
        case VOC_TYPE_VOICE_DATA:
            if (!dec->sample_rate) {
                dec->sample_rate = 1000000 / (256 - avio_r8(pb));
                if (sample_rate)
                    dec->sample_rate = sample_rate;
                avpriv_set_pts_info(st, 64, 1, dec->sample_rate);
            } else
                avio_skip(pb, 1);
            dec->channels = channels;
            tmp_codec = avio_r8(pb);
            dec->bits_per_coded_sample = av_get_bits_per_sample(dec->codec_id);
            voc->remaining_size -= 2;
            max_size -= 2;
            channels = 1;
            break;

        case VOC_TYPE_VOICE_DATA_CONT:
            break;

        case VOC_TYPE_EXTENDED:
            sample_rate = avio_rl16(pb);
            avio_r8(pb);
            channels = avio_r8(pb) + 1;
            sample_rate = 256000000 / (channels * (65536 - sample_rate));
            voc->remaining_size = 0;
            max_size -= 4;
            break;

        case VOC_TYPE_NEW_VOICE_DATA:
            if (!dec->sample_rate) {
                dec->sample_rate = avio_rl32(pb);
                avpriv_set_pts_info(st, 64, 1, dec->sample_rate);
            } else
                avio_skip(pb, 4);
            dec->bits_per_coded_sample = avio_r8(pb);
            dec->channels = avio_r8(pb);
            tmp_codec = avio_rl16(pb);
            avio_skip(pb, 4);
            voc->remaining_size -= 12;
            max_size -= 12;
            break;

        default:
            avio_skip(pb, voc->remaining_size);
            max_size -= voc->remaining_size;
            voc->remaining_size = 0;
            break;
        }
    }

    if (tmp_codec >= 0) {
        tmp_codec = ff_codec_get_id(ff_voc_codec_tags, tmp_codec);
        if (dec->codec_id == AV_CODEC_ID_NONE)
            dec->codec_id = tmp_codec;
        else if (dec->codec_id != tmp_codec)
            av_log(s, AV_LOG_WARNING, "Ignoring mid-stream change in audio codec\n");
        if (dec->codec_id == AV_CODEC_ID_NONE) {
            if (s->audio_codec_id == AV_CODEC_ID_NONE) {
                av_log(s, AV_LOG_ERROR, "unknown codec tag\n");
                return AVERROR(EINVAL);
            }
            av_log(s, AV_LOG_WARNING, "unknown codec tag\n");
        }
    }

    dec->bit_rate = dec->sample_rate * dec->channels * dec->bits_per_coded_sample;

    if (max_size <= 0)
        max_size = 2048;
    size = FFMIN(voc->remaining_size, max_size);
    voc->remaining_size -= size;
    return av_get_packet(pb, pkt, size);
}

static int voc_read_packet(AVFormatContext *s, AVPacket *pkt)
{
    return ff_voc_get_packet(s, pkt, s->streams[0], 0);
}

AVInputFormat ff_voc_demuxer = {
    .name           = "voc",
    .long_name      = NULL_IF_CONFIG_SMALL("Creative Voice"),
    .priv_data_size = sizeof(VocDecContext),
    .read_probe     = voc_probe,
    .read_header    = voc_read_header,
    .read_packet    = voc_read_packet,
    .codec_tag      = (const AVCodecTag* const []){ ff_voc_codec_tags, 0 },
};
