/*
 * Quicktime Planar RGB (8BPS) Video Decoder
 * Copyright (C) 2003 Roberto Togni
 *
 * 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
 * QT 8BPS Video Decoder by Roberto Togni
 * For more information about the 8BPS format, visit:
 *   http://www.pcisys.net/~melanson/codecs/
 *
 * Supports: PAL8 (RGB 8bpp, paletted)
 *         : BGR24 (RGB 24bpp) (can also output it as RGB32)
 *         : RGB32 (RGB 32bpp, 4th plane is alpha)
 *
 */

#include <stdio.h>
#include <stdlib.h>

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


static const enum PixelFormat pixfmt_rgb24[] = {PIX_FMT_BGR24, PIX_FMT_RGB32, PIX_FMT_NONE};

/*
 * Decoder context
 */
typedef struct EightBpsContext {

        AVCodecContext *avctx;
        AVFrame pic;

        unsigned char planes;
        unsigned char planemap[4];

        uint32_t pal[256];
} EightBpsContext;


/*
 *
 * Decode a frame
 *
 */
static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt)
{
        const uint8_t *buf = avpkt->data;
        int buf_size = avpkt->size;
        EightBpsContext * const c = avctx->priv_data;
        const unsigned char *encoded = buf;
        unsigned char *pixptr, *pixptr_end;
        unsigned int height = avctx->height; // Real image height
        unsigned int dlen, p, row;
        const unsigned char *lp, *dp;
        unsigned char count;
        unsigned int planes = c->planes;
        unsigned char *planemap = c->planemap;

        if(c->pic.data[0])
                avctx->release_buffer(avctx, &c->pic);

        c->pic.reference = 0;
        c->pic.buffer_hints = FF_BUFFER_HINTS_VALID;
        if(avctx->get_buffer(avctx, &c->pic) < 0){
                av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
                return -1;
        }

        /* Set data pointer after line lengths */
        dp = encoded + planes * (height << 1);

        for (p = 0; p < planes; p++) {
                /* Lines length pointer for this plane */
                lp = encoded + p * (height << 1);

                /* Decode a plane */
                for(row = 0; row < height; row++) {
                        pixptr = c->pic.data[0] + row * c->pic.linesize[0] + planemap[p];
                        pixptr_end = pixptr + c->pic.linesize[0];
                        dlen = av_be2ne16(*(const unsigned short *)(lp+row*2));
                        /* Decode a row of this plane */
                        while(dlen > 0) {
                                if(dp + 1 >= buf+buf_size) return -1;
                                if ((count = *dp++) <= 127) {
                                        count++;
                                        dlen -= count + 1;
                                        if (pixptr + count * planes > pixptr_end)
                                            break;
                                        if(dp + count > buf+buf_size) return -1;
                                        while(count--) {
                                                *pixptr = *dp++;
                                                pixptr += planes;
                                        }
                                } else {
                                        count = 257 - count;
                                        if (pixptr + count * planes > pixptr_end)
                                            break;
                                        while(count--) {
                                                *pixptr = *dp;
                                                pixptr += planes;
                                        }
                                        dp++;
                                        dlen -= 2;
                                }
                        }
                }
        }

        if (avctx->bits_per_coded_sample <= 8) {
                const uint8_t *pal = av_packet_get_side_data(avpkt,
                                                             AV_PKT_DATA_PALETTE,
                                                             NULL);
                if (pal) {
                        c->pic.palette_has_changed = 1;
                        memcpy(c->pal, pal, AVPALETTE_SIZE);
                }

                memcpy (c->pic.data[1], c->pal, AVPALETTE_SIZE);
        }

        *data_size = sizeof(AVFrame);
        *(AVFrame*)data = c->pic;

        /* always report that the buffer was completely consumed */
        return buf_size;
}


/*
 *
 * Init 8BPS decoder
 *
 */
static av_cold int decode_init(AVCodecContext *avctx)
{
        EightBpsContext * const c = avctx->priv_data;

        c->avctx = avctx;

        avcodec_get_frame_defaults(&c->pic);
        c->pic.data[0] = NULL;

        switch (avctx->bits_per_coded_sample) {
                case 8:
                        avctx->pix_fmt = PIX_FMT_PAL8;
                        c->planes = 1;
                        c->planemap[0] = 0; // 1st plane is palette indexes
                        break;
                case 24:
                        avctx->pix_fmt = avctx->get_format(avctx, pixfmt_rgb24);
                        c->planes = 3;
                        c->planemap[0] = 2; // 1st plane is red
                        c->planemap[1] = 1; // 2nd plane is green
                        c->planemap[2] = 0; // 3rd plane is blue
                        break;
                case 32:
                        avctx->pix_fmt = PIX_FMT_RGB32;
                        c->planes = 4;
#if HAVE_BIGENDIAN
                        c->planemap[0] = 1; // 1st plane is red
                        c->planemap[1] = 2; // 2nd plane is green
                        c->planemap[2] = 3; // 3rd plane is blue
                        c->planemap[3] = 0; // 4th plane is alpha
#else
                        c->planemap[0] = 2; // 1st plane is red
                        c->planemap[1] = 1; // 2nd plane is green
                        c->planemap[2] = 0; // 3rd plane is blue
                        c->planemap[3] = 3; // 4th plane is alpha
#endif
                        break;
                default:
                        av_log(avctx, AV_LOG_ERROR, "Error: Unsupported color depth: %u.\n", avctx->bits_per_coded_sample);
                        return -1;
        }

  return 0;
}




/*
 *
 * Uninit 8BPS decoder
 *
 */
static av_cold int decode_end(AVCodecContext *avctx)
{
        EightBpsContext * const c = avctx->priv_data;

        if (c->pic.data[0])
                avctx->release_buffer(avctx, &c->pic);

        return 0;
}



AVCodec ff_eightbps_decoder = {
    .name           = "8bps",
    .type           = AVMEDIA_TYPE_VIDEO,
    .id             = CODEC_ID_8BPS,
    .priv_data_size = sizeof(EightBpsContext),
    .init           = decode_init,
    .close          = decode_end,
    .decode         = decode_frame,
    .capabilities   = CODEC_CAP_DR1,
    .long_name      = NULL_IF_CONFIG_SMALL("QuickTime 8BPS video"),
};
