/*
 * Copyright 2022 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/codec/SkAvifCodec.h"

#include "include/codec/SkAvifDecoder.h"
#include "include/codec/SkCodec.h"
#include "include/codec/SkCodecAnimation.h"
#include "include/core/SkColorType.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkSize.h"
#include "include/core/SkStream.h"
#include "include/core/SkTypes.h"
#include "modules/skcms/skcms.h"
#include "src/codec/SkCodecPriv.h"
#include "src/core/SkRectMemcpy.h"
#include "src/core/SkStreamPriv.h"

#include <cstdint>
#include <cstring>
#include <utility>

#include "avif/avif.h"

void AvifDecoderDeleter::operator()(avifDecoder* decoder) const {
    if (decoder != nullptr) {
        avifDecoderDestroy(decoder);
    }
}

bool SkAvifCodec::IsAvif(const void* buffer, size_t bytesRead) {
    avifROData avifData = {static_cast<const uint8_t*>(buffer), bytesRead};
    bool isAvif = avifPeekCompatibleFileType(&avifData) == AVIF_TRUE;
    if (isAvif) return true;
    // Peeking sometimes fails if the ftyp box is too large. Check the signature
    // just to be sure.
    const char* bytes = static_cast<const char*>(buffer);
    isAvif = bytesRead >= 12 && !memcmp(&bytes[4], "ftyp", 4) &&
             (!memcmp(&bytes[8], "avif", 4) || !memcmp(&bytes[8], "avis", 4));
    return isAvif;
}

std::unique_ptr<SkCodec> SkAvifCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
                                                     Result* result) {
    SkASSERT(result);
    if (!stream) {
        *result = SkCodec::kInvalidInput;
        return nullptr;
    }
    AvifDecoder avifDecoder(avifDecoderCreate());
    if (avifDecoder == nullptr) {
        *result = SkCodec::kInternalError;
        return nullptr;
    }
    avifDecoder->ignoreXMP = AVIF_TRUE;
    avifDecoder->ignoreExif = AVIF_TRUE;
    avifDecoder->allowProgressive = AVIF_FALSE;
    avifDecoder->allowIncremental = AVIF_FALSE;
    avifDecoder->strictFlags = AVIF_STRICT_DISABLED;
    // TODO(vigneshv): Enable threading based on number of CPU cores available.
    avifDecoder->maxThreads = 1;

    // libavif needs a contiguous data buffer.
    sk_sp<SkData> data = nullptr;
    if (stream->getMemoryBase()) {
        // It is safe to make without copy because we'll hold onto the stream.
        data = SkData::MakeWithoutCopy(stream->getMemoryBase(), stream->getLength());
    } else {
        data = SkStreamPriv::CopyStreamToData(stream.get());
        // If we are forced to copy the stream to a data, we can go ahead and
        // delete the stream.
        stream.reset(nullptr);
    }

    avifResult res = avifDecoderSetIOMemory(avifDecoder.get(), data->bytes(), data->size());
    if (res != AVIF_RESULT_OK) {
        *result = SkCodec::kInternalError;
        return nullptr;
    }

    res = avifDecoderParse(avifDecoder.get());
    if (res != AVIF_RESULT_OK) {
        *result = SkCodec::kInvalidInput;
        return nullptr;
    }

    std::unique_ptr<SkCodecs::ColorProfile> profile;
    // TODO(vigneshv): Get ICC Profile from the avif decoder.

    const int bitsPerComponent = avifDecoder->image->depth > 8 ? 16 : 8;
    SkEncodedInfo::Color color;
    SkEncodedInfo::Alpha alpha;
    if (avifDecoder->alphaPresent) {
        color = SkEncodedInfo::kRGBA_Color;
        alpha = SkEncodedInfo::kUnpremul_Alpha;
    } else if (avifDecoder->image->yuvFormat == AVIF_PIXEL_FORMAT_YUV400) {
        color = SkEncodedInfo::kGray_Color;
        alpha = SkEncodedInfo::kOpaque_Alpha;
    } else {
        color = SkEncodedInfo::kRGB_Color;
        alpha = SkEncodedInfo::kOpaque_Alpha;
    }
    SkEncodedInfo info = SkEncodedInfo::Make(avifDecoder->image->width,
                                             avifDecoder->image->height,
                                             color,
                                             alpha,
                                             bitsPerComponent,
                                             std::move(profile),
                                             avifDecoder->image->depth);
    bool animation = avifDecoder->imageCount > 1;
    *result = kSuccess;
    return std::unique_ptr<SkCodec>(new SkAvifCodec(std::move(info),
                                                    std::move(stream),
                                                    std::move(data),
                                                    std::move(avifDecoder),
                                                    kDefault_SkEncodedOrigin,
                                                    animation));
}

SkAvifCodec::SkAvifCodec(SkEncodedInfo&& info,
                         std::unique_ptr<SkStream> stream,
                         sk_sp<const SkData> data,
                         AvifDecoder avifDecoder,
                         SkEncodedOrigin origin,
                         bool useAnimation)
        : INHERITED(std::move(info), skcms_PixelFormat_RGBA_8888, std::move(stream), origin)
        , fData(std::move(data))
        , fAvifDecoder(std::move(avifDecoder))
        , fUseAnimation(useAnimation) {}

int SkAvifCodec::onGetFrameCount() {
    if (!fUseAnimation) {
        return 1;
    }

    if (fFrameHolder.size() == 0) {
        if (fAvifDecoder->imageCount <= 1) {
            fUseAnimation = false;
            return 1;
        }
        fFrameHolder.reserve(fAvifDecoder->imageCount);
        for (int i = 0; i < fAvifDecoder->imageCount; i++) {
            Frame* frame = fFrameHolder.appendNewFrame(fAvifDecoder->alphaPresent == AVIF_TRUE);
            frame->setXYWH(0, 0, fAvifDecoder->image->width, fAvifDecoder->image->height);
            frame->setDisposalMethod(SkCodecAnimation::DisposalMethod::kKeep);
            avifImageTiming timing;
            avifDecoderNthImageTiming(fAvifDecoder.get(), i, &timing);
            frame->setDuration(timing.duration * 1000);
            frame->setRequiredFrame(SkCodec::kNoFrame);
            frame->setHasAlpha(fAvifDecoder->alphaPresent == AVIF_TRUE);
        }
    }

    return fFrameHolder.size();
}

const SkFrame* SkAvifCodec::FrameHolder::onGetFrame(int i) const {
    return static_cast<const SkFrame*>(this->frame(i));
}

SkAvifCodec::Frame* SkAvifCodec::FrameHolder::appendNewFrame(bool hasAlpha) {
    const int i = this->size();
    fFrames.emplace_back(i,
                         hasAlpha ? SkEncodedInfo::kUnpremul_Alpha : SkEncodedInfo::kOpaque_Alpha);
    return &fFrames[i];
}

const SkAvifCodec::Frame* SkAvifCodec::FrameHolder::frame(int i) const {
    SkASSERT(i >= 0 && i < this->size());
    return &fFrames[i];
}

bool SkAvifCodec::onGetFrameInfo(int i, FrameInfo* frameInfo) const {
    if (i >= fFrameHolder.size()) {
        return false;
    }

    const Frame* frame = fFrameHolder.frame(i);
    if (!frame) {
        return false;
    }

    if (frameInfo) {
        frame->fillIn(frameInfo, true);
    }

    return true;
}

int SkAvifCodec::onGetRepetitionCount() { return kRepetitionCountInfinite; }

SkCodec::IsAnimated SkAvifCodec::onIsAnimated() {
    if (!fUseAnimation || fAvifDecoder->imageCount <= 1) {
        return IsAnimated::kNo;
    }
    return IsAnimated::kYes;
}

SkCodec::Result SkAvifCodec::onGetPixels(const SkImageInfo& dstInfo,
                                         void* dst,
                                         size_t dstRowBytes,
                                         const Options& options,
                                         int* rowsDecoded) {
    if (options.fSubset) {
        return kUnimplemented;
    }

    const SkColorType dstColorType = dstInfo.colorType();
    if (dstColorType == kGray_8_SkColorType &&
        this->getEncodedInfo().color() != SkEncodedInfo::kGray_Color) {
        return kInvalidConversion;
    }

    if (dstColorType != kRGBA_8888_SkColorType
        && dstColorType != kBGRA_8888_SkColorType
        && dstColorType != kRGBA_F16_SkColorType
        && dstColorType != kGray_8_SkColorType) {
        // TODO(vigneshv): Check if more color types need to be supported.
        // Currently android supports at least RGB565 which is not
        // supported here.
        return kUnimplemented;
    }

    avifResult result = avifDecoderNthImage(fAvifDecoder.get(), options.fFrameIndex);
    if (result != AVIF_RESULT_OK) {
        return kInvalidInput;
    }

    if (this->dimensions() != dstInfo.dimensions()) {
        result = avifImageScale(
                fAvifDecoder->image, dstInfo.width(), dstInfo.height(), &fAvifDecoder->diag);
        if (result != AVIF_RESULT_OK) {
            return kInvalidInput;
        }
    }

    if (dstColorType == kGray_8_SkColorType) {
        if (fAvifDecoder->image->depth != 8) {
            return kInvalidConversion;
        }
        const uint8_t* srcRow = fAvifDecoder->image->yuvPlanes[AVIF_CHAN_Y];
        size_t srcRowBytes = fAvifDecoder->image->yuvRowBytes[AVIF_CHAN_Y];

        SkRectMemcpy(dst, dstRowBytes, srcRow, srcRowBytes, dstInfo.width(), dstInfo.height());
        if (rowsDecoded) {
            *rowsDecoded = dstInfo.height();
        }
        return kSuccess;
    }

    avifRGBImage rgbImage;
    avifRGBImageSetDefaults(&rgbImage, fAvifDecoder->image);

    if (dstColorType == kRGBA_8888_SkColorType) {
        rgbImage.depth = 8;
    } else if (dstColorType == kBGRA_8888_SkColorType){
        rgbImage.depth = 8;
        rgbImage.format = AVIF_RGB_FORMAT_BGRA;
    } else if (dstColorType == kRGBA_F16_SkColorType) {
        rgbImage.depth = 16;
        rgbImage.isFloat = AVIF_TRUE;
    }

    rgbImage.pixels = static_cast<uint8_t*>(dst);
    rgbImage.rowBytes = dstRowBytes;
    rgbImage.chromaUpsampling = AVIF_CHROMA_UPSAMPLING_FASTEST;

    result = avifImageYUVToRGB(fAvifDecoder->image, &rgbImage);
    if (result != AVIF_RESULT_OK) {
        return kInvalidInput;
    }

    *rowsDecoded = fAvifDecoder->image->height;
    return kSuccess;
}

namespace SkAvifDecoder {
namespace LibAvif {

bool IsAvif(const void* data, size_t len) {
    return SkAvifCodec::IsAvif(data, len);
}

std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream> stream,
                                SkCodec::Result* outResult,
                                SkCodecs::DecodeContext) {
    SkCodec::Result resultStorage;
    if (!outResult) {
        outResult = &resultStorage;
    }
    return SkAvifCodec::MakeFromStream(std::move(stream), outResult);
}

std::unique_ptr<SkCodec> Decode(sk_sp<const SkData> data,
                                SkCodec::Result* outResult,
                                SkCodecs::DecodeContext) {
    if (!data) {
        if (outResult) {
            *outResult = SkCodec::kInvalidInput;
        }
        return nullptr;
    }
    return Decode(SkMemoryStream::Make(std::move(data)), outResult, nullptr);
}

}  // namespace LibAvif
}  // namespace SkAvifDecoder
