/*
 * American Laser Games MM Video Decoder
 * Copyright (c) 2006,2008 Peter Ross
 *
 * 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 libavcodec/mmvideo.c
 * American Laser Games MM Video Decoder
 * by Peter Ross (suxen_drol at hotmail dot com)
 *
 * The MM format was used by IBM-PC ports of ALG's "arcade shooter" games,
 * including Mad Dog McCree and Crime Patrol.
 *
 * Technical details here:
 *  http://wiki.multimedia.cx/index.php?title=American_Laser_Games_MM
 */

#include "libavutil/intreadwrite.h"
#include "avcodec.h"

#define MM_PREAMBLE_SIZE    6

#define MM_TYPE_INTER       0x5
#define MM_TYPE_INTRA       0x8
#define MM_TYPE_INTRA_HH    0xc
#define MM_TYPE_INTER_HH    0xd
#define MM_TYPE_INTRA_HHV   0xe
#define MM_TYPE_INTER_HHV   0xf
#define MM_TYPE_PALETTE     0x31

typedef struct MmContext {
    AVCodecContext *avctx;
    AVFrame frame;
    int palette[AVPALETTE_COUNT];
} MmContext;

static av_cold int mm_decode_init(AVCodecContext *avctx)
{
    MmContext *s = avctx->priv_data;

    s->avctx = avctx;

    avctx->pix_fmt = PIX_FMT_PAL8;

    if (avcodec_check_dimensions(avctx, avctx->width, avctx->height))
        return -1;

    s->frame.reference = 1;
    if (avctx->get_buffer(avctx, &s->frame)) {
        av_log(s->avctx, AV_LOG_ERROR, "mmvideo: get_buffer() failed\n");
        return -1;
    }

    return 0;
}

static void mm_decode_pal(MmContext *s, const uint8_t *buf, const uint8_t *buf_end)
{
    int i;
    buf += 4;
    for (i=0; i<128 && buf+2<buf_end; i++) {
        s->palette[i] = AV_RB24(buf);
        s->palette[i+128] = s->palette[i]<<2;
        buf += 3;
    }
}

static void mm_decode_intra(MmContext * s, int half_horiz, int half_vert, const uint8_t *buf, int buf_size)
{
    int i, x, y;
    i=0; x=0; y=0;

    while(i<buf_size) {
        int run_length, color;

        if (buf[i] & 0x80) {
            run_length = 1;
            color = buf[i];
            i++;
        }else{
            run_length = (buf[i] & 0x7f) + 2;
            color = buf[i+1];
            i+=2;
        }

        if (half_horiz)
            run_length *=2;

        if (color) {
            memset(s->frame.data[0] + y*s->frame.linesize[0] + x, color, run_length);
            if (half_vert)
                memset(s->frame.data[0] + (y+1)*s->frame.linesize[0] + x, color, run_length);
        }
        x+= run_length;

        if (x >= s->avctx->width) {
            x=0;
            y += half_vert ? 2 : 1;
        }
    }
}

static void mm_decode_inter(MmContext * s, int half_horiz, int half_vert, const uint8_t *buf, int buf_size)
{
    const int data_ptr = 2 + AV_RL16(&buf[0]);
    int d, r, y;
    d = data_ptr; r = 2; y = 0;

    while(r < data_ptr) {
        int i, j;
        int length = buf[r] & 0x7f;
        int x = buf[r+1] + ((buf[r] & 0x80) << 1);
        r += 2;

        if (length==0) {
            y += x;
            continue;
        }

        for(i=0; i<length; i++) {
            for(j=0; j<8; j++) {
                int replace = (buf[r+i] >> (7-j)) & 1;
                if (replace) {
                    int color = buf[d];
                    s->frame.data[0][y*s->frame.linesize[0] + x] = color;
                    if (half_horiz)
                        s->frame.data[0][y*s->frame.linesize[0] + x + 1] = color;
                    if (half_vert) {
                        s->frame.data[0][(y+1)*s->frame.linesize[0] + x] = color;
                        if (half_horiz)
                            s->frame.data[0][(y+1)*s->frame.linesize[0] + x + 1] = color;
                    }
                    d++;
                }
                x += half_horiz ? 2 : 1;
            }
        }

        r += length;
        y += half_vert ? 2 : 1;
    }
}

static int mm_decode_frame(AVCodecContext *avctx,
                            void *data, int *data_size,
                            const uint8_t *buf, int buf_size)
{
    MmContext *s = avctx->priv_data;
    const uint8_t *buf_end = buf+buf_size;
    int type;

    type = AV_RL16(&buf[0]);
    buf += MM_PREAMBLE_SIZE;
    buf_size -= MM_PREAMBLE_SIZE;

    switch(type) {
    case MM_TYPE_PALETTE   : mm_decode_pal(s, buf, buf_end); return buf_size;
    case MM_TYPE_INTRA     : mm_decode_intra(s, 0, 0, buf, buf_size); break;
    case MM_TYPE_INTRA_HH  : mm_decode_intra(s, 1, 0, buf, buf_size); break;
    case MM_TYPE_INTRA_HHV : mm_decode_intra(s, 1, 1, buf, buf_size); break;
    case MM_TYPE_INTER     : mm_decode_inter(s, 0, 0, buf, buf_size); break;
    case MM_TYPE_INTER_HH  : mm_decode_inter(s, 1, 0, buf, buf_size); break;
    case MM_TYPE_INTER_HHV : mm_decode_inter(s, 1, 1, buf, buf_size); break;
    default :
        return -1;
    }

    memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);

    *data_size = sizeof(AVFrame);
    *(AVFrame*)data = s->frame;

    return buf_size;
}

static av_cold int mm_decode_end(AVCodecContext *avctx)
{
    MmContext *s = avctx->priv_data;

    if(s->frame.data[0])
        avctx->release_buffer(avctx, &s->frame);

    return 0;
}

AVCodec mmvideo_decoder = {
    "mmvideo",
    CODEC_TYPE_VIDEO,
    CODEC_ID_MMVIDEO,
    sizeof(MmContext),
    mm_decode_init,
    NULL,
    mm_decode_end,
    mm_decode_frame,
    CODEC_CAP_DR1,
    .long_name = NULL_IF_CONFIG_SMALL("American Laser Games MM Video"),
};
