/*
 * Animated GIF muxer
 * Copyright (c) 2000 Fabrice Bellard
 *
 * first version by Francois Revol <revol@free.fr>
 *
 * 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
 */

#include "avformat.h"
#include "internal.h"
#include "libavutil/avassert.h"
#include "libavutil/imgutils.h"
#include "libavutil/log.h"
#include "libavutil/opt.h"

/* XXX: random value that shouldn't be taken into effect if there is no
 * transparent color in the palette (the transparency bit will be set to 0) */
#define DEFAULT_TRANSPARENCY_INDEX 0x1f

static int get_palette_transparency_index(const uint32_t *palette)
{
    int transparent_color_index = -1;
    unsigned i, smallest_alpha = 0xff;

    if (!palette)
        return -1;

    for (i = 0; i < AVPALETTE_COUNT; i++) {
        const uint32_t v = palette[i];
        if (v >> 24 < smallest_alpha) {
            smallest_alpha = v >> 24;
            transparent_color_index = i;
        }
    }
    return smallest_alpha < 128 ? transparent_color_index : -1;
}

static int gif_image_write_header(AVIOContext *pb, AVStream *st,
                                  int loop_count, uint32_t *palette)
{
    int i;
    int64_t aspect = 0;
    const AVRational sar = st->sample_aspect_ratio;

    if (sar.num > 0 && sar.den > 0) {
        aspect = sar.num * 64LL / sar.den - 15;
        if (aspect < 0 || aspect > 255)
            aspect = 0;
    }

    avio_write(pb, "GIF", 3);
    avio_write(pb, "89a", 3);
    avio_wl16(pb, st->codecpar->width);
    avio_wl16(pb, st->codecpar->height);

    if (palette) {
        const int bcid = get_palette_transparency_index(palette);

        avio_w8(pb, 0xf7); /* flags: global clut, 256 entries */
        avio_w8(pb, bcid < 0 ? DEFAULT_TRANSPARENCY_INDEX : bcid); /* background color index */
        avio_w8(pb, aspect);
        for (i = 0; i < 256; i++) {
            const uint32_t v = palette[i] & 0xffffff;
            avio_wb24(pb, v);
        }
    } else {
        avio_w8(pb, 0); /* flags */
        avio_w8(pb, 0); /* background color index */
        avio_w8(pb, aspect);
    }


    if (loop_count >= 0 ) {
        /* "NETSCAPE EXTENSION" for looped animation GIF */
        avio_w8(pb, 0x21); /* GIF Extension code */
        avio_w8(pb, 0xff); /* Application Extension Label */
        avio_w8(pb, 0x0b); /* Length of Application Block */
        avio_write(pb, "NETSCAPE2.0", sizeof("NETSCAPE2.0") - 1);
        avio_w8(pb, 0x03); /* Length of Data Sub-Block */
        avio_w8(pb, 0x01);
        avio_wl16(pb, (uint16_t)loop_count);
        avio_w8(pb, 0x00); /* Data Sub-block Terminator */
    }

    avio_flush(pb);
    return 0;
}

typedef struct GIFContext {
    AVClass *class;
    int loop;
    int last_delay;
    AVPacket *prev_pkt;
    int duration;
} GIFContext;

static int gif_write_header(AVFormatContext *s)
{
    GIFContext *gif = s->priv_data;
    AVCodecParameters *video_par;
    uint32_t palette[AVPALETTE_COUNT];

    if (s->nb_streams != 1 ||
        s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
        s->streams[0]->codecpar->codec_id   != AV_CODEC_ID_GIF) {
        av_log(s, AV_LOG_ERROR,
               "GIF muxer supports only a single video GIF stream.\n");
        return AVERROR(EINVAL);
    }

    video_par = s->streams[0]->codecpar;

    avpriv_set_pts_info(s->streams[0], 64, 1, 100);
    if (avpriv_set_systematic_pal2(palette, video_par->format) < 0) {
        av_assert0(video_par->format == AV_PIX_FMT_PAL8);
        /* delay header writing: we wait for the first palette to put it
         * globally */
    } else {
        gif_image_write_header(s->pb, s->streams[0], gif->loop, palette);
    }

    return 0;
}

static int flush_packet(AVFormatContext *s, AVPacket *new)
{
    GIFContext *gif = s->priv_data;
    int size, bcid;
    AVIOContext *pb = s->pb;
    const uint32_t *palette;
    AVPacket *pkt = gif->prev_pkt;

    if (!pkt)
        return 0;

    /* Mark one colour as transparent if the input palette contains at least
     * one colour that is more than 50% transparent. */
    palette = (uint32_t*)av_packet_get_side_data(pkt, AV_PKT_DATA_PALETTE, &size);
    if (palette && size != AVPALETTE_SIZE) {
        av_log(s, AV_LOG_ERROR, "Invalid palette extradata\n");
        return AVERROR_INVALIDDATA;
    }
    bcid = get_palette_transparency_index(palette);

    if (new && new->pts != AV_NOPTS_VALUE)
        gif->duration = av_clip_uint16(new->pts - gif->prev_pkt->pts);
    else if (!new && gif->last_delay >= 0)
        gif->duration = gif->last_delay;

    /* graphic control extension block */
    avio_w8(pb, 0x21);
    avio_w8(pb, 0xf9);
    avio_w8(pb, 0x04); /* block size */
    avio_w8(pb, 1<<2 | (bcid >= 0));
    avio_wl16(pb, gif->duration);
    avio_w8(pb, bcid < 0 ? DEFAULT_TRANSPARENCY_INDEX : bcid);
    avio_w8(pb, 0x00);

    avio_write(pb, pkt->data, pkt->size);

    av_packet_unref(gif->prev_pkt);
    if (new)
        av_packet_ref(gif->prev_pkt, new);

    return 0;
}

static int gif_write_packet(AVFormatContext *s, AVPacket *pkt)
{
    GIFContext *gif = s->priv_data;
    AVStream *video_st = s->streams[0];

    if (!gif->prev_pkt) {
        gif->prev_pkt = av_packet_alloc();
        if (!gif->prev_pkt)
            return AVERROR(ENOMEM);

        /* Write the first palette as global palette */
        if (video_st->codecpar->format == AV_PIX_FMT_PAL8) {
            int size;
            void *palette = av_packet_get_side_data(pkt, AV_PKT_DATA_PALETTE, &size);

            if (!palette) {
                av_log(s, AV_LOG_ERROR, "PAL8 packet is missing palette in extradata\n");
                return AVERROR_INVALIDDATA;
            }
            if (size != AVPALETTE_SIZE) {
                av_log(s, AV_LOG_ERROR, "Invalid palette extradata\n");
                return AVERROR_INVALIDDATA;
            }
            gif_image_write_header(s->pb, video_st, gif->loop, palette);
        }

        return av_packet_ref(gif->prev_pkt, pkt);
    }
    return flush_packet(s, pkt);
}

static int gif_write_trailer(AVFormatContext *s)
{
    GIFContext *gif = s->priv_data;
    AVIOContext *pb = s->pb;

    flush_packet(s, NULL);
    av_freep(&gif->prev_pkt);
    avio_w8(pb, 0x3b);

    return 0;
}

#define OFFSET(x) offsetof(GIFContext, x)
#define ENC AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
    { "loop", "Number of times to loop the output: -1 - no loop, 0 - infinite loop", OFFSET(loop),
      AV_OPT_TYPE_INT, { .i64 = 0 }, -1, 65535, ENC },
    { "final_delay", "Force delay (in centiseconds) after the last frame", OFFSET(last_delay),
      AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 65535, ENC },
    { NULL },
};

static const AVClass gif_muxer_class = {
    .class_name = "GIF muxer",
    .item_name  = av_default_item_name,
    .version    = LIBAVUTIL_VERSION_INT,
    .option     = options,
};

AVOutputFormat ff_gif_muxer = {
    .name           = "gif",
    .long_name      = NULL_IF_CONFIG_SMALL("GIF Animation"),
    .mime_type      = "image/gif",
    .extensions     = "gif",
    .priv_data_size = sizeof(GIFContext),
    .audio_codec    = AV_CODEC_ID_NONE,
    .video_codec    = AV_CODEC_ID_GIF,
    .write_header   = gif_write_header,
    .write_packet   = gif_write_packet,
    .write_trailer  = gif_write_trailer,
    .priv_class     = &gif_muxer_class,
    .flags          = AVFMT_VARIABLE_FPS,
};
