// Copyright 2019 Joe Drago. All rights reserved.
// SPDX-License-Identifier: BSD-2-Clause

#include "avif/internal.h"

#include "aom/aom_decoder.h"
#include "aom/aomdx.h"
#include "aom/aom_encoder.h"
#include "aom/aomcx.h"

#include <string.h>

struct avifCodecInternal
{
    avifBool decoderInitialized[AVIF_CODEC_PLANES_COUNT];
    aom_codec_ctx_t decoders[AVIF_CODEC_PLANES_COUNT];

    aom_image_t * images[AVIF_CODEC_PLANES_COUNT];
    avifRawData encodedOBUs[AVIF_CODEC_PLANES_COUNT];
    avifCodecConfigurationBox configs[AVIF_CODEC_PLANES_COUNT];
};

avifCodec * avifCodecCreate()
{
    avifCodec * codec = (avifCodec *)avifAlloc(sizeof(avifCodec));
    codec->internal = (struct avifCodecInternal *)avifAlloc(sizeof(struct avifCodecInternal));
    memset(codec->internal, 0, sizeof(struct avifCodecInternal));
    return codec;
}

void avifCodecDestroy(avifCodec * codec)
{
    for (int plane = 0; plane < AVIF_CODEC_PLANES_COUNT; ++plane) {
        if (codec->internal->decoderInitialized[plane]) {
            aom_codec_destroy(&codec->internal->decoders[plane]);
        }
        avifRawDataFree(&codec->internal->encodedOBUs[plane]);
    }
    avifFree(codec->internal);
    avifFree(codec);
}

avifBool avifCodecDecode(avifCodec * codec, avifCodecPlanes planes, avifRawData * obu)
{
    aom_codec_stream_info_t si;
    aom_codec_iface_t * decoder_interface = aom_codec_av1_dx();
    if (aom_codec_dec_init(&codec->internal->decoders[planes], decoder_interface, NULL, 0)) {
        return AVIF_FALSE;
    }
    codec->internal->decoderInitialized[planes] = AVIF_TRUE;

    if (aom_codec_control(&codec->internal->decoders[planes], AV1D_SET_OUTPUT_ALL_LAYERS, 1)) {
        return AVIF_FALSE;
    }

    si.is_annexb = 0;
    if (aom_codec_peek_stream_info(decoder_interface, obu->data, obu->size, &si)) {
        return AVIF_FALSE;
    }

    if (aom_codec_decode(&codec->internal->decoders[planes], obu->data, obu->size, NULL)) {
        return AVIF_FALSE;
    }

    aom_codec_iter_t iter = NULL;
    codec->internal->images[planes] = aom_codec_get_frame(&codec->internal->decoders[planes], &iter); // It doesn't appear that I own this / need to free this
    return (codec->internal->images[planes]) ? AVIF_TRUE : AVIF_FALSE;
}

avifCodecImageSize avifCodecGetImageSize(avifCodec * codec, avifCodecPlanes planes)
{
    avifCodecImageSize size;
    if (codec->internal->images[planes]) {
        size.width = codec->internal->images[planes]->d_w;
        size.height = codec->internal->images[planes]->d_h;
    } else {
        size.width = 0;
        size.height = 0;
    }
    return size;
}

avifBool avifCodecAlphaLimitedRange(avifCodec * codec)
{
    aom_image_t * aomAlphaImage = codec->internal->images[AVIF_CODEC_PLANES_ALPHA];
    if (aomAlphaImage && (aomAlphaImage->range == AOM_CR_STUDIO_RANGE)) {
        return AVIF_TRUE;
    }
    return AVIF_FALSE;
}

avifResult avifCodecGetDecodedImage(avifCodec * codec, avifImage * image)
{
    aom_image_t * aomColorImage = codec->internal->images[AVIF_CODEC_PLANES_COLOR];
    aom_image_t * aomAlphaImage = codec->internal->images[AVIF_CODEC_PLANES_ALPHA];
    avifBool hasAlpha = aomAlphaImage ? AVIF_TRUE : AVIF_FALSE;

    avifPixelFormat yuvFormat = AVIF_PIXEL_FORMAT_NONE;
    switch (aomColorImage->fmt) {
        case AOM_IMG_FMT_I420:
        case AOM_IMG_FMT_AOMI420:
        case AOM_IMG_FMT_I42016:
            yuvFormat = AVIF_PIXEL_FORMAT_YUV420;
            break;
        case AOM_IMG_FMT_I422:
        case AOM_IMG_FMT_I42216:
            yuvFormat = AVIF_PIXEL_FORMAT_YUV422;
            break;
        case AOM_IMG_FMT_I444:
        case AOM_IMG_FMT_I44416:
            yuvFormat = AVIF_PIXEL_FORMAT_YUV444;
            break;
        case AOM_IMG_FMT_YV12:
        case AOM_IMG_FMT_AOMYV12:
        case AOM_IMG_FMT_YV1216:
            yuvFormat = AVIF_PIXEL_FORMAT_YV12;
            break;
        case AOM_IMG_FMT_NONE:
        default:
            break;
    }

    image->width = aomColorImage->d_w;
    image->height = aomColorImage->d_h;
    image->depth = aomColorImage->bit_depth;
    image->yuvFormat = yuvFormat;
    image->yuvRange = (aomColorImage->range == AOM_CR_STUDIO_RANGE) ? AVIF_RANGE_LIMITED : AVIF_RANGE_FULL;

    avifPixelFormatInfo formatInfo;
    avifGetPixelFormatInfo(yuvFormat, &formatInfo);

    int uvHeight = image->height >> formatInfo.chromaShiftY;
    avifImageAllocatePlanes(image, AVIF_PLANES_YUV);
    for (int yuvPlane = 0; yuvPlane < 3; ++yuvPlane) {
        int aomPlaneIndex = yuvPlane;
        int planeHeight = image->height;
        if (yuvPlane == AVIF_CHAN_U) {
            aomPlaneIndex = formatInfo.aomIndexU;
            planeHeight = uvHeight;
        } else if (yuvPlane == AVIF_CHAN_V) {
            aomPlaneIndex = formatInfo.aomIndexV;
            planeHeight = uvHeight;
        }

        for (int j = 0; j < planeHeight; ++j) {
            uint8_t * srcRow = &aomColorImage->planes[aomPlaneIndex][j * aomColorImage->stride[aomPlaneIndex]];
            uint8_t * dstRow = &image->yuvPlanes[yuvPlane][j * image->yuvRowBytes[yuvPlane]];
            memcpy(dstRow, srcRow, image->yuvRowBytes[yuvPlane]);
        }
    }

    if (hasAlpha) {
        avifImageAllocatePlanes(image, AVIF_PLANES_A);
        for (int j = 0; j < image->height; ++j) {
            uint8_t * srcAlphaRow = &aomAlphaImage->planes[0][j * aomAlphaImage->stride[0]];
            uint8_t * dstAlphaRow = &image->alphaPlane[j * image->alphaRowBytes];
            memcpy(dstAlphaRow, srcAlphaRow, image->alphaRowBytes);
        }
    }
    return AVIF_RESULT_OK;
}

static aom_img_fmt_t avifImageCalcAOMFmt(avifImage * image, avifBool alphaOnly, int * yShift)
{
    *yShift = 0;

    aom_img_fmt_t fmt;
    if (alphaOnly) {
        // We're going monochrome, who cares about chroma quality
        fmt = AOM_IMG_FMT_I420;
        *yShift = 1;
    } else {
        switch (image->yuvFormat) {
            case AVIF_PIXEL_FORMAT_YUV444:
                fmt = AOM_IMG_FMT_I444;
                break;
            case AVIF_PIXEL_FORMAT_YUV422:
                fmt = AOM_IMG_FMT_I422;
                break;
            case AVIF_PIXEL_FORMAT_YUV420:
                fmt = AOM_IMG_FMT_I420;
                *yShift = 1;
                break;
            case AVIF_PIXEL_FORMAT_YV12:
                fmt = AOM_IMG_FMT_YV12;
                *yShift = 1;
                break;
            default:
                return AOM_IMG_FMT_NONE;
        }
    }

    if (image->depth > 8) {
        fmt |= AOM_IMG_FMT_HIGHBITDEPTH;
    }

    return fmt;
}

static avifBool encodeOBU(avifImage * image, avifBool alphaOnly, int numThreads, int quality, avifRawData * outputOBU, avifCodecConfigurationBox * outputConfig)
{
    avifBool success = AVIF_FALSE;
    aom_codec_iface_t * encoder_interface = aom_codec_av1_cx();
    aom_codec_ctx_t encoder;

    memset(outputConfig, 0, sizeof(avifCodecConfigurationBox));

    int yShift = 0;
    aom_img_fmt_t aomFormat = avifImageCalcAOMFmt(image, alphaOnly, &yShift);
    if (aomFormat == AOM_IMG_FMT_NONE) {
        return AVIF_FALSE;
    }

    avifPixelFormatInfo formatInfo;
    avifGetPixelFormatInfo(image->yuvFormat, &formatInfo);

    struct aom_codec_enc_cfg cfg;
    aom_codec_enc_config_default(encoder_interface, &cfg, 0);

    // Profile 0.  8-bit and 10-bit 4:2:0 and 4:0:0 only.
    // Profile 1.  8-bit and 10-bit 4:4:4
    // Profile 2.  8-bit and 10-bit 4:2:2
    //            12-bit  4:0:0, 4:2:2 and 4:4:4
    if (image->depth == 12) {
        // Only profile 2 can handle 12 bit
        cfg.g_profile = 2;
    } else {
        // 8-bit or 10-bit

        if (alphaOnly) {
            // Assuming aomImage->monochrome makes it 4:0:0
            cfg.g_profile = 0;
        } else {
            switch (image->yuvFormat) {
                case AVIF_PIXEL_FORMAT_YUV444: cfg.g_profile = 1; break;
                case AVIF_PIXEL_FORMAT_YUV422: cfg.g_profile = 2; break;
                case AVIF_PIXEL_FORMAT_YUV420: cfg.g_profile = 0; break;
                case AVIF_PIXEL_FORMAT_YV12:   cfg.g_profile = 0; break;
                case AVIF_PIXEL_FORMAT_NONE:
                default:
                    break;
            }
        }
    }

    cfg.g_bit_depth = image->depth;
    cfg.g_input_bit_depth = image->depth;
    cfg.g_w = image->width;
    cfg.g_h = image->height;
    if (numThreads > 1) {
        cfg.g_threads = numThreads;
    }

    // TODO: Choose correct value from Annex A.3 table: https://aomediacodec.github.io/av1-spec/av1-spec.pdf
    uint8_t seqLevelIdx0 = 31;
    if ((image->width <= 8192) && (image->height <= 4352) && ((image->width * image->height) <= 8912896)) {
        // Image is 5.1 compatible
        seqLevelIdx0 = 13; // 5.1
    }

    outputConfig->seqProfile = cfg.g_profile;
    outputConfig->seqLevelIdx0 = seqLevelIdx0;
    outputConfig->seqTier0 = 0;
    outputConfig->highBitdepth = (image->depth > 8) ? 1 : 0;
    outputConfig->twelveBit = (image->depth == 12) ? 1 : 0;
    outputConfig->monochrome = alphaOnly ? 1 : 0;
    outputConfig->chromaSubsamplingX = formatInfo.chromaShiftX;
    outputConfig->chromaSubsamplingY = formatInfo.chromaShiftY;

    // TODO: choose the correct one from below:
    //   * 0 - CSP_UNKNOWN   Unknown (in this case the source video transfer function must be signaled outside the AV1 bitstream)
    //   * 1 - CSP_VERTICAL  Horizontally co-located with (0, 0) luma sample, vertical position in the middle between two luma samples
    //   * 2 - CSP_COLOCATED co-located with (0, 0) luma sample
    //   * 3 - CSP_RESERVED
    outputConfig->chromaSamplePosition = 0;

    avifBool lossless = (quality == AVIF_BEST_QUALITY) ? AVIF_TRUE : AVIF_FALSE;
    cfg.rc_min_quantizer = 0;
    if (lossless) {
        cfg.rc_max_quantizer = 0;
    } else {
        cfg.rc_max_quantizer = quality;
    }

    uint32_t encoderFlags = 0;
    if (image->depth > 8) {
        encoderFlags |= AOM_CODEC_USE_HIGHBITDEPTH;
    }
    aom_codec_enc_init(&encoder, encoder_interface, &cfg, encoderFlags);

    if (lossless) {
        aom_codec_control(&encoder, AV1E_SET_LOSSLESS, 1);
    }
    if (numThreads > 1) {
        aom_codec_control(&encoder, AV1E_SET_ROW_MT, 1);
    }

    int uvHeight = image->height >> yShift;
    aom_image_t * aomImage = aom_img_alloc(NULL, aomFormat, image->width, image->height, 16);

    if (alphaOnly) {
        aomImage->range = AOM_CR_FULL_RANGE; // Alpha is always full range
        aom_codec_control(&encoder, AV1E_SET_COLOR_RANGE, aomImage->range);
        aomImage->monochrome = 1;
        for (int j = 0; j < image->height; ++j) {
            uint8_t * srcAlphaRow = &image->alphaPlane[j * image->alphaRowBytes];
            uint8_t * dstAlphaRow = &aomImage->planes[0][j * aomImage->stride[0]];
            memcpy(dstAlphaRow, srcAlphaRow, image->alphaRowBytes);
        }

        for (int j = 0; j < uvHeight; ++j) {
            // Zero out U and V
            memset(&aomImage->planes[1][j * aomImage->stride[1]], 0, aomImage->stride[1]);
            memset(&aomImage->planes[2][j * aomImage->stride[2]], 0, aomImage->stride[2]);
        }
    } else {
        aomImage->range = (image->yuvRange == AVIF_RANGE_FULL) ? AOM_CR_FULL_RANGE : AOM_CR_STUDIO_RANGE;
        aom_codec_control(&encoder, AV1E_SET_COLOR_RANGE, aomImage->range);
        for (int yuvPlane = 0; yuvPlane < 3; ++yuvPlane) {
            int aomPlaneIndex = yuvPlane;
            int planeHeight = image->height;
            if (yuvPlane == AVIF_CHAN_U) {
                aomPlaneIndex = formatInfo.aomIndexU;
                planeHeight = uvHeight;
            } else if (yuvPlane == AVIF_CHAN_V) {
                aomPlaneIndex = formatInfo.aomIndexV;
                planeHeight = uvHeight;
            }

            for (int j = 0; j < planeHeight; ++j) {
                uint8_t * srcRow = &image->yuvPlanes[yuvPlane][j * image->yuvRowBytes[yuvPlane]];
                uint8_t * dstRow = &aomImage->planes[aomPlaneIndex][j * aomImage->stride[aomPlaneIndex]];
                memcpy(dstRow, srcRow, image->yuvRowBytes[yuvPlane]);
            }
        }
    }

    aom_codec_encode(&encoder, aomImage, 0, 1, 0);
    aom_codec_encode(&encoder, NULL, 0, 1, 0); // flush

    aom_codec_iter_t iter = NULL;
    for (;;) {
        const aom_codec_cx_pkt_t * pkt = aom_codec_get_cx_data(&encoder, &iter);
        if (pkt == NULL)
            break;
        if (pkt->kind == AOM_CODEC_CX_FRAME_PKT) {
            avifRawDataSet(outputOBU, pkt->data.frame.buf, pkt->data.frame.sz);
            success = AVIF_TRUE;
            break;
        }
    }

    aom_img_free(aomImage);
    aom_codec_destroy(&encoder);
    return success;
}

avifResult avifCodecEncodeImage(avifCodec * codec, avifImage * image, int numThreads, int colorQuality, avifRawData * colorOBU, avifRawData * alphaOBU)
{
    if (colorOBU) {
        if (!encodeOBU(image, AVIF_FALSE, numThreads, colorQuality, colorOBU, &codec->internal->configs[AVIF_CODEC_PLANES_COLOR])) {
            return AVIF_RESULT_ENCODE_COLOR_FAILED;
        }
    }
    if (alphaOBU) {
        if (!encodeOBU(image, AVIF_TRUE, numThreads, AVIF_BEST_QUALITY, alphaOBU, &codec->internal->configs[AVIF_CODEC_PLANES_ALPHA])) {
            return AVIF_RESULT_ENCODE_COLOR_FAILED;
        }
    }
    return AVIF_RESULT_OK;
}

void avifCodecGetConfigurationBox(avifCodec * codec, avifCodecPlanes planes, avifCodecConfigurationBox * outConfig)
{
    memcpy(outConfig, &codec->internal->configs[planes], sizeof(avifCodecConfigurationBox));
}
