/*
 * Bethsoft VID format Demuxer
 * Copyright (c) 2007 Nicholas Tung
 *
 * 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
 * @brief Bethesda Softworks VID (.vid) file demuxer
 * @author Nicholas Tung [ntung (at. ntung com] (2007-03)
 * @sa http://wiki.multimedia.cx/index.php?title=Bethsoft_VID
 * @sa http://www.svatopluk.com/andux/docs/dfvid.html
 */

#include "libavutil/intreadwrite.h"
#include "avformat.h"
#include "libavcodec/bethsoftvideo.h"

typedef struct BVID_DemuxContext
{
    int nframes;
    /** delay value between frames, added to individual frame delay.
     * custom units, which will be added to other custom units (~=16ms according
     * to free, unofficial documentation) */
    int bethsoft_global_delay;

    /** video presentation time stamp.
     * delay = 16 milliseconds * (global_delay + per_frame_delay) */
    int video_pts;

    int is_finished;

} BVID_DemuxContext;

static int vid_probe(AVProbeData *p)
{
    // little endian VID tag, file starts with "VID\0"
    if (AV_RL32(p->buf) != MKTAG('V', 'I', 'D', 0))
        return 0;

    return AVPROBE_SCORE_MAX;
}

static int vid_read_header(AVFormatContext *s,
                            AVFormatParameters *ap)
{
    BVID_DemuxContext *vid = s->priv_data;
    AVIOContext *pb = s->pb;
    AVStream *stream;

    /* load main header. Contents:
    *    bytes: 'V' 'I' 'D'
    *    int16s: always_512, nframes, width, height, delay, always_14
    */
    avio_skip(pb, 5);
    vid->nframes = avio_rl16(pb);

    stream = av_new_stream(s, 0);
    if (!stream)
        return AVERROR(ENOMEM);
    av_set_pts_info(stream, 32, 1, 60);     // 16 ms increments, i.e. 60 fps
    stream->codec->codec_type = AVMEDIA_TYPE_VIDEO;
    stream->codec->codec_id = CODEC_ID_BETHSOFTVID;
    stream->codec->width = avio_rl16(pb);
    stream->codec->height = avio_rl16(pb);
    stream->codec->pix_fmt = PIX_FMT_PAL8;
    vid->bethsoft_global_delay = avio_rl16(pb);
    avio_rl16(pb);

    // done with video codec, set up audio codec
    stream = av_new_stream(s, 0);
    if (!stream)
        return AVERROR(ENOMEM);
    stream->codec->codec_type = AVMEDIA_TYPE_AUDIO;
    stream->codec->codec_id = CODEC_ID_PCM_U8;
    stream->codec->channels = 1;
    stream->codec->sample_rate = 11025;
    stream->codec->bits_per_coded_sample = 8;
    stream->codec->bit_rate = stream->codec->channels * stream->codec->sample_rate * stream->codec->bits_per_coded_sample;

    return 0;
}

#define BUFFER_PADDING_SIZE 1000
static int read_frame(BVID_DemuxContext *vid, AVIOContext *pb, AVPacket *pkt,
                      uint8_t block_type, AVFormatContext *s, int npixels)
{
    uint8_t * vidbuf_start = NULL;
    int vidbuf_nbytes = 0;
    int code;
    int bytes_copied = 0;
    int position;
    unsigned int vidbuf_capacity;

    vidbuf_start = av_malloc(vidbuf_capacity = BUFFER_PADDING_SIZE);
    if(!vidbuf_start)
        return AVERROR(ENOMEM);

    // save the file position for the packet, include block type
    position = avio_tell(pb) - 1;

    vidbuf_start[vidbuf_nbytes++] = block_type;

    // get the video delay (next int16), and set the presentation time
    vid->video_pts += vid->bethsoft_global_delay + avio_rl16(pb);

    // set the y offset if it exists (decoder header data should be in data section)
    if(block_type == VIDEO_YOFF_P_FRAME){
        if(avio_read(pb, &vidbuf_start[vidbuf_nbytes], 2) != 2)
            goto fail;
        vidbuf_nbytes += 2;
    }

    do{
        vidbuf_start = av_fast_realloc(vidbuf_start, &vidbuf_capacity, vidbuf_nbytes + BUFFER_PADDING_SIZE);
        if(!vidbuf_start)
            return AVERROR(ENOMEM);

        code = avio_r8(pb);
        vidbuf_start[vidbuf_nbytes++] = code;

        if(code >= 0x80){ // rle sequence
            if(block_type == VIDEO_I_FRAME)
                vidbuf_start[vidbuf_nbytes++] = avio_r8(pb);
        } else if(code){ // plain sequence
            if(avio_read(pb, &vidbuf_start[vidbuf_nbytes], code) != code)
                goto fail;
            vidbuf_nbytes += code;
        }
        bytes_copied += code & 0x7F;
        if(bytes_copied == npixels){ // sometimes no stop character is given, need to keep track of bytes copied
            // may contain a 0 byte even if read all pixels
            if(avio_r8(pb))
                avio_seek(pb, -1, SEEK_CUR);
            break;
        }
        if(bytes_copied > npixels)
            goto fail;
    } while(code);

    // copy data into packet
    if(av_new_packet(pkt, vidbuf_nbytes) < 0)
        goto fail;
    memcpy(pkt->data, vidbuf_start, vidbuf_nbytes);
    av_free(vidbuf_start);

    pkt->pos = position;
    pkt->stream_index = 0;  // use the video decoder, which was initialized as the first stream
    pkt->pts = vid->video_pts;

    vid->nframes--;  // used to check if all the frames were read
    return vidbuf_nbytes;
fail:
    av_free(vidbuf_start);
    return -1;
}

static int vid_read_packet(AVFormatContext *s,
                           AVPacket *pkt)
{
    BVID_DemuxContext *vid = s->priv_data;
    AVIOContext *pb = s->pb;
    unsigned char block_type;
    int audio_length;
    int ret_value;

    if(vid->is_finished || url_feof(pb))
        return AVERROR(EIO);

    block_type = avio_r8(pb);
    switch(block_type){
        case PALETTE_BLOCK:
            avio_seek(pb, -1, SEEK_CUR);     // include block type
            ret_value = av_get_packet(pb, pkt, 3 * 256 + 1);
            if(ret_value != 3 * 256 + 1){
                av_free_packet(pkt);
                return AVERROR(EIO);
            }
            pkt->stream_index = 0;
            return ret_value;

        case FIRST_AUDIO_BLOCK:
            avio_rl16(pb);
            // soundblaster DAC used for sample rate, as on specification page (link above)
            s->streams[1]->codec->sample_rate = 1000000 / (256 - avio_r8(pb));
            s->streams[1]->codec->bit_rate = s->streams[1]->codec->channels * s->streams[1]->codec->sample_rate * s->streams[1]->codec->bits_per_coded_sample;
        case AUDIO_BLOCK:
            audio_length = avio_rl16(pb);
            ret_value = av_get_packet(pb, pkt, audio_length);
            pkt->stream_index = 1;
            return ret_value != audio_length ? AVERROR(EIO) : ret_value;

        case VIDEO_P_FRAME:
        case VIDEO_YOFF_P_FRAME:
        case VIDEO_I_FRAME:
            return read_frame(vid, pb, pkt, block_type, s,
                              s->streams[0]->codec->width * s->streams[0]->codec->height);

        case EOF_BLOCK:
            if(vid->nframes != 0)
                av_log(s, AV_LOG_VERBOSE, "reached terminating character but not all frames read.\n");
            vid->is_finished = 1;
            return AVERROR(EIO);
        default:
            av_log(s, AV_LOG_ERROR, "unknown block (character = %c, decimal = %d, hex = %x)!!!\n",
                   block_type, block_type, block_type); return -1;
    }

    return 0;
}

AVInputFormat ff_bethsoftvid_demuxer = {
    "bethsoftvid",
    NULL_IF_CONFIG_SMALL("Bethesda Softworks VID format"),
    sizeof(BVID_DemuxContext),
    vid_probe,
    vid_read_header,
    vid_read_packet,
};
