/*
 * ATI VCR1 codec
 * Copyright (c) 2003 Michael Niedermayer
 *
 * 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
 * ATI VCR1 codec
 */

#include "avcodec.h"
#include "dsputil.h"
#include "internal.h"
#include "libavutil/avassert.h"
#include "libavutil/internal.h"

typedef struct VCR1Context {
    AVFrame picture;
    int delta[16];
    int offset[4];
} VCR1Context;

static av_cold int vcr1_common_init(AVCodecContext *avctx)
{
    VCR1Context *const a = avctx->priv_data;

    avctx->coded_frame = &a->picture;
    avcodec_get_frame_defaults(&a->picture);

    return 0;
}

static av_cold int vcr1_decode_init(AVCodecContext *avctx)
{
    vcr1_common_init(avctx);

    avctx->pix_fmt = AV_PIX_FMT_YUV410P;

    if (avctx->width % 8 || avctx->height%4) {
        av_log_ask_for_sample(avctx, "odd dimensions (%d x %d) support", avctx->width, avctx->height);
        return AVERROR_INVALIDDATA;
    }

    return 0;
}

static av_cold int vcr1_decode_end(AVCodecContext *avctx)
{
    VCR1Context *s = avctx->priv_data;

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

    return 0;
}

static int vcr1_decode_frame(AVCodecContext *avctx, void *data,
                             int *got_frame, AVPacket *avpkt)
{
    const uint8_t *buf        = avpkt->data;
    int buf_size              = avpkt->size;
    VCR1Context *const a      = avctx->priv_data;
    AVFrame *picture          = data;
    AVFrame *const p          = &a->picture;
    const uint8_t *bytestream = buf;
    int i, x, y;

    if (p->data[0])
        avctx->release_buffer(avctx, p);

    if(buf_size < 16 + avctx->height + avctx->width*avctx->height*5/8){
        av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n");
        return AVERROR(EINVAL);
    }

    p->reference = 0;
    if (ff_get_buffer(avctx, p) < 0) {
        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
        return -1;
    }
    p->pict_type = AV_PICTURE_TYPE_I;
    p->key_frame = 1;

    for (i = 0; i < 16; i++) {
        a->delta[i] = *bytestream++;
        bytestream++;
        buf_size--;
    }

    for (y = 0; y < avctx->height; y++) {
        int offset;
        uint8_t *luma = &a->picture.data[0][y * a->picture.linesize[0]];

        if ((y & 3) == 0) {
            uint8_t *cb = &a->picture.data[1][(y >> 2) * a->picture.linesize[1]];
            uint8_t *cr = &a->picture.data[2][(y >> 2) * a->picture.linesize[2]];

            av_assert0 (buf_size >= 4 + avctx->width);

            for (i = 0; i < 4; i++)
                a->offset[i] = *bytestream++;
            buf_size -= 4;

            offset = a->offset[0] - a->delta[bytestream[2] & 0xF];
            for (x = 0; x < avctx->width; x += 4) {
                luma[0]     = offset += a->delta[bytestream[2] & 0xF];
                luma[1]     = offset += a->delta[bytestream[2] >>  4];
                luma[2]     = offset += a->delta[bytestream[0] & 0xF];
                luma[3]     = offset += a->delta[bytestream[0] >>  4];
                luma       += 4;

                *cb++       = bytestream[3];
                *cr++       = bytestream[1];

                bytestream += 4;
                buf_size   -= 4;
            }
        } else {
            av_assert0 (buf_size >= avctx->width / 2);

            offset = a->offset[y & 3] - a->delta[bytestream[2] & 0xF];

            for (x = 0; x < avctx->width; x += 8) {
                luma[0]     = offset += a->delta[bytestream[2] & 0xF];
                luma[1]     = offset += a->delta[bytestream[2] >>  4];
                luma[2]     = offset += a->delta[bytestream[3] & 0xF];
                luma[3]     = offset += a->delta[bytestream[3] >>  4];
                luma[4]     = offset += a->delta[bytestream[0] & 0xF];
                luma[5]     = offset += a->delta[bytestream[0] >>  4];
                luma[6]     = offset += a->delta[bytestream[1] & 0xF];
                luma[7]     = offset += a->delta[bytestream[1] >>  4];
                luma       += 8;
                bytestream += 4;
                buf_size   -= 4;
            }
        }
    }

    *picture   = a->picture;
    *got_frame = 1;

    return bytestream - avpkt->data;
}

AVCodec ff_vcr1_decoder = {
    .name           = "vcr1",
    .type           = AVMEDIA_TYPE_VIDEO,
    .id             = AV_CODEC_ID_VCR1,
    .priv_data_size = sizeof(VCR1Context),
    .init           = vcr1_decode_init,
    .close          = vcr1_decode_end,
    .decode         = vcr1_decode_frame,
    .capabilities   = CODEC_CAP_DR1,
    .long_name      = NULL_IF_CONFIG_SMALL("ATI VCR1"),
};

/* Disable the encoder. */
#undef CONFIG_VCR1_ENCODER
#define CONFIG_VCR1_ENCODER 0

#if CONFIG_VCR1_ENCODER

#include "put_bits.h"

static int vcr1_encode_frame(AVCodecContext *avctx, unsigned char *buf,
                             int buf_size, void *data)
{
    VCR1Context *const a = avctx->priv_data;
    AVFrame *pict        = data;
    AVFrame *const p     = &a->picture;
    int size;

    *p           = *pict;
    p->pict_type = AV_PICTURE_TYPE_I;
    p->key_frame = 1;

    avpriv_align_put_bits(&a->pb);
    flush_put_bits(&a->pb);

    size = put_bits_count(&a->pb) / 32;

    return size * 4;
}

AVCodec ff_vcr1_encoder = {
    .name           = "vcr1",
    .type           = AVMEDIA_TYPE_VIDEO,
    .id             = AV_CODEC_ID_VCR1,
    .priv_data_size = sizeof(VCR1Context),
    .init           = vcr1_common_init,
    .encode         = vcr1_encode_frame,
    .long_name      = NULL_IF_CONFIG_SMALL("ATI VCR1"),
};
#endif /* CONFIG_VCR1_ENCODER */
