/*
 * ISS (.iss) file demuxer
 * Copyright (c) 2008 Jaikrishnan Menon <realityman@gmx.net>
 *
 * 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
 * Funcom ISS file demuxer
 * @author Jaikrishnan Menon
 * @see http://wiki.multimedia.cx/index.php?title=FunCom_ISS
 */

#include "libavutil/channel_layout.h"
#include "avformat.h"
#include "internal.h"
#include "libavutil/avstring.h"

#define ISS_SIG "IMA_ADPCM_Sound"
#define ISS_SIG_LEN 15
#define MAX_TOKEN_SIZE 20

typedef struct {
    int packet_size;
    int sample_start_pos;
} IssDemuxContext;

static void get_token(AVIOContext *s, char *buf, int maxlen)
{
    int i = 0;
    char c;

    while ((c = avio_r8(s))) {
        if(c == ' ')
            break;
        if (i < maxlen-1)
            buf[i++] = c;
    }

    if(!c)
        avio_r8(s);

    buf[i] = 0; /* Ensure null terminated, but may be truncated */
}

static int iss_probe(AVProbeData *p)
{
    if (strncmp(p->buf, ISS_SIG, ISS_SIG_LEN))
        return 0;

    return AVPROBE_SCORE_MAX;
}

static av_cold int iss_read_header(AVFormatContext *s)
{
    IssDemuxContext *iss = s->priv_data;
    AVIOContext *pb = s->pb;
    AVStream *st;
    char token[MAX_TOKEN_SIZE];
    int stereo, rate_divisor;

    get_token(pb, token, sizeof(token)); //"IMA_ADPCM_Sound"
    get_token(pb, token, sizeof(token)); //packet size
    if (sscanf(token, "%d", &iss->packet_size) != 1) {
        av_log(s, AV_LOG_ERROR, "Failed parsing packet size\n");
        return AVERROR_INVALIDDATA;
    }
    get_token(pb, token, sizeof(token)); //File ID
    get_token(pb, token, sizeof(token)); //out size
    get_token(pb, token, sizeof(token)); //stereo
    if (sscanf(token, "%d", &stereo) != 1) {
        av_log(s, AV_LOG_ERROR, "Failed parsing stereo flag\n");
        return AVERROR_INVALIDDATA;
    }
    get_token(pb, token, sizeof(token)); //Unknown1
    get_token(pb, token, sizeof(token)); //RateDivisor
    if (sscanf(token, "%d", &rate_divisor) != 1) {
        av_log(s, AV_LOG_ERROR, "Failed parsing rate_divisor\n");
        return AVERROR_INVALIDDATA;
    }
    get_token(pb, token, sizeof(token)); //Unknown2
    get_token(pb, token, sizeof(token)); //Version ID
    get_token(pb, token, sizeof(token)); //Size

    if (iss->packet_size <= 0) {
        av_log(s, AV_LOG_ERROR, "packet_size %d is invalid\n", iss->packet_size);
        return AVERROR_INVALIDDATA;
    }

    iss->sample_start_pos = avio_tell(pb);

    st = avformat_new_stream(s, NULL);
    if (!st)
        return AVERROR(ENOMEM);
    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
    st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_ISS;
    if (stereo) {
        st->codec->channels       = 2;
        st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
    } else {
        st->codec->channels       = 1;
        st->codec->channel_layout = AV_CH_LAYOUT_MONO;
    }
    st->codec->sample_rate = 44100;
    if(rate_divisor > 0)
         st->codec->sample_rate /= rate_divisor;
    st->codec->bits_per_coded_sample = 4;
    st->codec->bit_rate = st->codec->channels * st->codec->sample_rate
                                      * st->codec->bits_per_coded_sample;
    st->codec->block_align = iss->packet_size;
    avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate);

    return 0;
}

static int iss_read_packet(AVFormatContext *s, AVPacket *pkt)
{
    IssDemuxContext *iss = s->priv_data;
    int ret = av_get_packet(s->pb, pkt, iss->packet_size);

    if(ret != iss->packet_size)
        return AVERROR(EIO);

    pkt->stream_index = 0;
    pkt->pts = avio_tell(s->pb) - iss->sample_start_pos;
    if(s->streams[0]->codec->channels > 0)
        pkt->pts /= s->streams[0]->codec->channels*2;
    return 0;
}

AVInputFormat ff_iss_demuxer = {
    .name           = "iss",
    .long_name      = NULL_IF_CONFIG_SMALL("Funcom ISS"),
    .priv_data_size = sizeof(IssDemuxContext),
    .read_probe     = iss_probe,
    .read_header    = iss_read_header,
    .read_packet    = iss_read_packet,
};
