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

#ifndef SkYUVAInfo_DEFINED
#define SkYUVAInfo_DEFINED

#include "include/codec/SkEncodedOrigin.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkSize.h"
#include "include/core/SkTypes.h"

#include <array>
#include <cstddef>
#include <cstdint>
#include <tuple>

/**
 * Specifies the structure of planes for a YUV image with optional alpha. The actual planar data
 * is not part of this structure and depending on usage is in external textures or pixmaps.
 */
class SK_API SkYUVAInfo {
public:
    enum YUVAChannels { kY, kU, kV, kA, kLast = kA };
    static constexpr int kYUVAChannelCount = static_cast<int>(YUVAChannels::kLast + 1);

    struct YUVALocation;  // For internal use.
    using YUVALocations = std::array<YUVALocation, kYUVAChannelCount>;

    /**
     * Specifies how YUV (and optionally A) are divided among planes. Planes are separated by
     * underscores in the enum value names. Within each plane the pixmap/texture channels are
     * mapped to the YUVA channels in the order specified, e.g. for kY_UV Y is in channel 0 of plane
     * 0, U is in channel 0 of plane 1, and V is in channel 1 of plane 1. Channel ordering
     * within a pixmap/texture given the channels it contains:
     * A:                       0:A
     * Luminance/Gray:          0:Gray
     * Luminance/Gray + Alpha:  0:Gray, 1:A
     * RG                       0:R,    1:G
     * RGB                      0:R,    1:G, 2:B
     * RGBA                     0:R,    1:G, 2:B, 3:A
     */
    enum class PlaneConfig {
        kUnknown,

        kY_U_V,    ///< Plane 0: Y, Plane 1: U,  Plane 2: V
        kY_V_U,    ///< Plane 0: Y, Plane 1: V,  Plane 2: U
        kY_UV,     ///< Plane 0: Y, Plane 1: UV
        kY_VU,     ///< Plane 0: Y, Plane 1: VU
        kYUV,      ///< Plane 0: YUV
        kUYV,      ///< Plane 0: UYV

        kY_U_V_A,  ///< Plane 0: Y, Plane 1: U,  Plane 2: V, Plane 3: A
        kY_V_U_A,  ///< Plane 0: Y, Plane 1: V,  Plane 2: U, Plane 3: A
        kY_UV_A,   ///< Plane 0: Y, Plane 1: UV, Plane 2: A
        kY_VU_A,   ///< Plane 0: Y, Plane 1: VU, Plane 2: A
        kYUVA,     ///< Plane 0: YUVA
        kUYVA,     ///< Plane 0: UYVA

#if defined(SK_ENABLE_YUVA_PACKED_422)
        /**
         * Plane 0: YUYV. Packed 4:2:2 where the plane has one 2-channel texel per
         * pixel: channel 0 holds the pixel's own luma and channel 1 holds the
         * chroma sample shared by the pixel's horizontal pair (U in even texels,
         * V in odd texels): (Y0, U0) (Y1, V0) (Y2, U1) (Y3, V1). Only valid with
         * Subsampling::k422. The plane has the same texel dimensions as the
         * image; the texture must be viewed as a 2-channel 16-bit format. The
         * image width must be even.
         */
        kYUYV,

        kLast = kYUYV
#else
        kLast = kUYVA
#endif
    };

    /**
     * UV subsampling is also specified in the enum value names using J:a:b notation (e.g. 4:2:0 is
     * 1/2 horizontal and 1/2 vertical resolution for U and V). If alpha is present it is not sub-
     * sampled. Note that Subsampling values other than k444 are only valid with PlaneConfig values
     * that have U and V in different planes than Y (and A, if present), with the exception of
     * PlaneConfig::kYUYV which represents packed 4:2:2 and is only valid with Subsampling::k422.
     */
    enum class Subsampling {
        kUnknown,

        k444,    ///< No subsampling. UV values for each Y.
        k422,    ///< 1 set of UV values for each 2x1 block of Y values.
        k420,    ///< 1 set of UV values for each 2x2 block of Y values.
        k440,    ///< 1 set of UV values for each 1x2 block of Y values.
        k411,    ///< 1 set of UV values for each 4x1 block of Y values.
        k410,    ///< 1 set of UV values for each 4x2 block of Y values.

        kLast = k410
    };

    /**
     * Describes how subsampled chroma values are sited relative to luma values.
     *
     * Currently only centered siting is supported but will expand to support additional sitings.
     */
    enum class Siting {
        /**
         * Subsampled chroma value is sited at the center of the block of corresponding luma values.
         */
        kCentered,
    };

    static constexpr int kMaxPlanes = 4;

    /** ratio of Y/A values to U/V values in x and y. */
    static std::tuple<int, int> SubsamplingFactors(Subsampling);

    /**
     * SubsamplingFactors(Subsampling) if planedIdx refers to a U/V plane and otherwise {1, 1} if
     * inputs are valid. Invalid inputs consist of incompatible PlaneConfig/Subsampling/planeIdx
     * combinations. {0, 0} is returned for invalid inputs.
     */
    static std::tuple<int, int> PlaneSubsamplingFactors(PlaneConfig, Subsampling, int planeIdx);

    /**
     * Given image dimensions, a planer configuration, subsampling, and origin, determine the
     * expected size of each plane. Returns the number of expected planes. planeDimensions[0]
     * through planeDimensions[<ret>] are written. The input image dimensions are as displayed
     * (after the planes have been transformed to the intended display orientation). The plane
     * dimensions are output as the planes are stored in memory (may be rotated from image
     * dimensions).
     */
    static int PlaneDimensions(SkISize imageDimensions,
                               PlaneConfig,
                               Subsampling,
                               SkEncodedOrigin,
                               SkISize planeDimensions[kMaxPlanes]);

    /** Number of planes for a given PlaneConfig. */
    static constexpr int NumPlanes(PlaneConfig);

    /**
     * Number of Y, U, V, A channels in the ith plane for a given PlaneConfig (or 0 if i is
     * invalid).
     */
    static constexpr int NumChannelsInPlane(PlaneConfig, int i);

    /**
     * Given a PlaneConfig and a set of channel flags for each plane, convert to YUVALocations
     * representation. Fails if channel flags aren't valid for the PlaneConfig (i.e. don't have
     * enough channels in a plane) by returning an invalid set of locations (plane indices are -1).
     */
    static YUVALocations GetYUVALocations(PlaneConfig, const uint32_t* planeChannelFlags);

    /** Does the PlaneConfig have alpha values? */
    static bool HasAlpha(PlaneConfig);

    SkYUVAInfo() = default;
    SkYUVAInfo(const SkYUVAInfo&) = default;

    /**
     * 'dimensions' should specify the size of the full resolution image (after planes have been
     * oriented to how the image is displayed as indicated by 'origin').
     */
    SkYUVAInfo(SkISize dimensions,
               PlaneConfig,
               Subsampling,
               SkYUVColorSpace,
               SkEncodedOrigin origin = kTopLeft_SkEncodedOrigin,
               Siting sitingX = Siting::kCentered,
               Siting sitingY = Siting::kCentered);

    SkYUVAInfo& operator=(const SkYUVAInfo& that) = default;

    PlaneConfig planeConfig() const { return fPlaneConfig; }
    Subsampling subsampling() const { return fSubsampling; }

    std::tuple<int, int> planeSubsamplingFactors(int planeIdx) const {
        return PlaneSubsamplingFactors(fPlaneConfig, fSubsampling, planeIdx);
    }

    /**
     * Dimensions of the full resolution image (after planes have been oriented to how the image
     * is displayed as indicated by fOrigin).
     */
    SkISize dimensions() const { return fDimensions; }
    int width() const { return fDimensions.width(); }
    int height() const { return fDimensions.height(); }

    SkYUVColorSpace yuvColorSpace() const { return fYUVColorSpace; }
    Siting sitingX() const { return fSitingX; }
    Siting sitingY() const { return fSitingY; }

    SkEncodedOrigin origin() const { return fOrigin; }

    SkMatrix originMatrix() const {
        return SkEncodedOriginToMatrix(fOrigin, this->width(), this->height());
    }
    SkMatrix inverseOriginMatrix() const {
        return SkEncodedOriginToMatrixInverse(fOrigin, this->width(), this->height());
    }

    bool hasAlpha() const { return HasAlpha(fPlaneConfig); }

    /**
     * Returns the number of planes and initializes planeDimensions[0]..planeDimensions[<ret>] to
     * the expected dimensions for each plane. Dimensions are as stored in memory, before
     * transformation to image display space as indicated by origin().
     */
    int planeDimensions(SkISize planeDimensions[kMaxPlanes]) const {
        return PlaneDimensions(fDimensions, fPlaneConfig, fSubsampling, fOrigin, planeDimensions);
    }

    /**
     * Given a per-plane row bytes, determine size to allocate for all planes. Optionally retrieves
     * the per-plane byte sizes in planeSizes if not null. If total size overflows will return
     * SIZE_MAX and set all planeSizes to SIZE_MAX.
     */
    size_t computeTotalBytes(const size_t rowBytes[kMaxPlanes],
                             size_t planeSizes[kMaxPlanes] = nullptr) const;

    int numPlanes() const { return NumPlanes(fPlaneConfig); }

    int numChannelsInPlane(int i) const { return NumChannelsInPlane(fPlaneConfig, i); }

    /**
     * Given a set of channel flags for each plane, converts this->planeConfig() to YUVALocations
     * representation. Fails if the channel flags aren't valid for the PlaneConfig (i.e. don't have
     * enough channels in a plane) by returning default initialized locations (all plane indices are
     * -1).
     */
    YUVALocations toYUVALocations(const uint32_t* channelFlags) const;

    /**
     * Makes a SkYUVAInfo that is identical to this one but with the passed Subsampling. If the
     * passed Subsampling is not k444 and this info's PlaneConfig is not compatible with chroma
     * subsampling (because Y is in the same plane as UV) then the result will be an invalid
     * SkYUVAInfo.
     */
    SkYUVAInfo makeSubsampling(SkYUVAInfo::Subsampling) const;

    /**
     * Makes a SkYUVAInfo that is identical to this one but with the passed dimensions. If the
     * passed dimensions is empty then the result will be an invalid SkYUVAInfo.
     */
    SkYUVAInfo makeDimensions(SkISize) const;

    bool operator==(const SkYUVAInfo& that) const;
    bool operator!=(const SkYUVAInfo& that) const { return !(*this == that); }

    bool isValid() const { return fPlaneConfig != PlaneConfig::kUnknown; }

private:
    SkISize fDimensions = {0, 0};

    PlaneConfig fPlaneConfig = PlaneConfig::kUnknown;
    Subsampling fSubsampling = Subsampling::kUnknown;

    SkYUVColorSpace fYUVColorSpace = SkYUVColorSpace::kIdentity_SkYUVColorSpace;

    /**
     * YUVA data often comes from formats like JPEG that support EXIF orientation.
     * Code that operates on the raw YUV data often needs to know that orientation.
     */
    SkEncodedOrigin fOrigin = kTopLeft_SkEncodedOrigin;

    Siting fSitingX = Siting::kCentered;
    Siting fSitingY = Siting::kCentered;
};

constexpr int SkYUVAInfo::NumPlanes(PlaneConfig planeConfig) {
    switch (planeConfig) {
        case PlaneConfig::kUnknown: return 0;
        case PlaneConfig::kY_U_V:   return 3;
        case PlaneConfig::kY_V_U:   return 3;
        case PlaneConfig::kY_UV:    return 2;
        case PlaneConfig::kY_VU:    return 2;
        case PlaneConfig::kYUV:     return 1;
        case PlaneConfig::kUYV:     return 1;
        case PlaneConfig::kY_U_V_A: return 4;
        case PlaneConfig::kY_V_U_A: return 4;
        case PlaneConfig::kY_UV_A:  return 3;
        case PlaneConfig::kY_VU_A:  return 3;
        case PlaneConfig::kYUVA:    return 1;
        case PlaneConfig::kUYVA:    return 1;
#if defined(SK_ENABLE_YUVA_PACKED_422)
        case PlaneConfig::kYUYV:    return 1;
#endif
    }
    SkUNREACHABLE;
}

constexpr int SkYUVAInfo::NumChannelsInPlane(PlaneConfig config, int i) {
    switch (config) {
        case PlaneConfig::kUnknown:
            return 0;

        case SkYUVAInfo::PlaneConfig::kY_U_V:
        case SkYUVAInfo::PlaneConfig::kY_V_U:
            return i >= 0 && i < 3 ? 1 : 0;
        case SkYUVAInfo::PlaneConfig::kY_UV:
        case SkYUVAInfo::PlaneConfig::kY_VU:
            switch (i) {
                case 0:  return 1;
                case 1:  return 2;
                default: return 0;
            }
        case SkYUVAInfo::PlaneConfig::kYUV:
        case SkYUVAInfo::PlaneConfig::kUYV:
            return i == 0 ? 3 : 0;
        case SkYUVAInfo::PlaneConfig::kY_U_V_A:
        case SkYUVAInfo::PlaneConfig::kY_V_U_A:
            return i >= 0 && i < 4 ? 1 : 0;
        case SkYUVAInfo::PlaneConfig::kY_UV_A:
        case SkYUVAInfo::PlaneConfig::kY_VU_A:
            switch (i) {
                case 0:  return 1;
                case 1:  return 2;
                case 2:  return 1;
                default: return 0;
            }
        case SkYUVAInfo::PlaneConfig::kYUVA:
        case SkYUVAInfo::PlaneConfig::kUYVA:
            return i == 0 ? 4 : 0;
#if defined(SK_ENABLE_YUVA_PACKED_422)
        case SkYUVAInfo::PlaneConfig::kYUYV:
            // Two YUVA channels (Y and the shared U/V chroma) are read from
            // each 2-channel texel (see kYUYV docs).
            return i == 0 ? 2 : 0;
#endif
    }
    return 0;
}

#endif
