/*
 * WebP encoding support via libwebp
 * Copyright (c) 2015 Urvang Joshi
 *
 * 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
 * WebP encoder using libwebp (WebPAnimEncoder API)
 */

#include "libavutil/buffer.h"

#include "config.h"
#include "codec_internal.h"
#include "encode.h"
#include "libwebpenc_common.h"

#include <webp/mux.h>

typedef struct LibWebPAnimContext {
    LibWebPContextCommon cc;
    WebPAnimEncoder *enc;     // the main AnimEncoder object
    int64_t first_frame_pts;  // pts of the first encoded frame.
    int64_t end_pts;          // pts + duration of the last frame

    void           *first_frame_opaque;
    AVBufferRef    *first_frame_opaque_ref;

    int done;                 // If true, we have assembled the bitstream already
} LibWebPAnimContext;

static av_cold int libwebp_anim_encode_init(AVCodecContext *avctx)
{
    int ret = ff_libwebp_encode_init_common(avctx);
    if (!ret) {
        LibWebPAnimContext *s = avctx->priv_data;
        WebPAnimEncoderOptions enc_options = { { 0 } };
        WebPAnimEncoderOptionsInit(&enc_options);
        enc_options.verbose = av_log_get_level() >= AV_LOG_VERBOSE;
        // TODO(urvang): Expose some options on command-line perhaps.
        s->enc = WebPAnimEncoderNew(avctx->width, avctx->height, &enc_options);
        if (!s->enc)
            return AVERROR(EINVAL);
        s->first_frame_pts = AV_NOPTS_VALUE;
        s->done = 0;
    }
    return ret;
}

static int libwebp_anim_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
                                     const AVFrame *frame, int *got_packet) {
    LibWebPAnimContext *s = avctx->priv_data;
    int ret;

    if (!frame) {
        if (s->done) {  // Second flush: return empty package to denote finish.
            *got_packet = 0;
            return 0;
        } else {  // First flush: assemble bitstream and return it.
            WebPData assembled_data = { 0 };
            ret = WebPAnimEncoderAssemble(s->enc, &assembled_data);
            if (ret) {
                ret = ff_get_encode_buffer(avctx, pkt, assembled_data.size, 0);
                if (ret < 0) {
                    WebPDataClear(&assembled_data);
                    return ret;
                }
                memcpy(pkt->data, assembled_data.bytes, assembled_data.size);
                WebPDataClear(&assembled_data);
                s->done = 1;
                pkt->pts = s->first_frame_pts;

                if (pkt->pts != AV_NOPTS_VALUE && s->end_pts > pkt->pts)
                    pkt->duration = s->end_pts - pkt->pts;

                if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
                    pkt->opaque               = s->first_frame_opaque;
                    pkt->opaque_ref           = s->first_frame_opaque_ref;
                    s->first_frame_opaque_ref = NULL;
                }

                *got_packet = 1;
                return 0;
            } else {
                WebPDataClear(&assembled_data);
                av_log(s, AV_LOG_ERROR,
                       "WebPAnimEncoderAssemble() failed with error: %d\n",
                       VP8_ENC_ERROR_OUT_OF_MEMORY);
                return AVERROR(ENOMEM);
            }
        }
    } else {
        int timestamp_ms;
        WebPPicture *pic = NULL;
        AVFrame *alt_frame = NULL;
        ret = ff_libwebp_get_frame(avctx, &s->cc, frame, &alt_frame, &pic);
        if (ret < 0)
            goto end;

        timestamp_ms =
            avctx->time_base.num * frame->pts * 1000 / avctx->time_base.den;
        ret = WebPAnimEncoderAdd(s->enc, pic, timestamp_ms, &s->cc.config);
        if (!ret) {
                av_log(avctx, AV_LOG_ERROR,
                       "Encoding WebP frame failed with error: %d\n",
                   pic->error_code);
            ret = ff_libwebp_error_to_averror(pic->error_code);
            goto end;
        }

        if (!avctx->frame_num) {
            s->first_frame_pts = frame->pts;

            if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
                s->first_frame_opaque = frame->opaque;
                ret = av_buffer_replace(&s->first_frame_opaque_ref, frame->opaque_ref);
                if (ret < 0)
                    goto end;
            }
        }

        if (frame->pts != AV_NOPTS_VALUE)
            s->end_pts = frame->pts + frame->duration;

        ret = 0;
        *got_packet = 0;

end:
        WebPPictureFree(pic);
        av_freep(&pic);
        av_frame_free(&alt_frame);
        return ret;
    }
}

static int libwebp_anim_encode_close(AVCodecContext *avctx)
{
    LibWebPAnimContext *s = avctx->priv_data;
    av_frame_free(&s->cc.ref);
    WebPAnimEncoderDelete(s->enc);

    av_buffer_unref(&s->first_frame_opaque_ref);

    return 0;
}

const FFCodec ff_libwebp_anim_encoder = {
    .p.name         = "libwebp_anim",
    CODEC_LONG_NAME("libwebp WebP image"),
    .p.type         = AVMEDIA_TYPE_VIDEO,
    .p.id           = AV_CODEC_ID_WEBP,
    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
    .p.pix_fmts     = ff_libwebpenc_pix_fmts,
    .p.priv_class   = &ff_libwebpenc_class,
    .p.wrapper_name = "libwebp",
    .caps_internal  = FF_CODEC_CAP_NOT_INIT_THREADSAFE,
    .priv_data_size = sizeof(LibWebPAnimContext),
    .defaults       = ff_libwebp_defaults,
    .init           = libwebp_anim_encode_init,
    FF_CODEC_ENCODE_CB(libwebp_anim_encode_frame),
    .close          = libwebp_anim_encode_close,
};
