/*
 * Copyright (C) 2020 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "VP9Utilities.h"

#include <wtf/NeverDestroyed.h>
#include <wtf/text/StringToIntegerConversion.h>

namespace WebCore {

static bool isValidVPLevel(uint8_t level)
{
    constexpr uint8_t validLevels[] = {
        VPConfigurationLevel::Level_1,
        VPConfigurationLevel::Level_1_1,
        VPConfigurationLevel::Level_2,
        VPConfigurationLevel::Level_2_1,
        VPConfigurationLevel::Level_3,
        VPConfigurationLevel::Level_3_1,
        VPConfigurationLevel::Level_4,
        VPConfigurationLevel::Level_4_1,
        VPConfigurationLevel::Level_5,
        VPConfigurationLevel::Level_5_1,
        VPConfigurationLevel::Level_5_2,
        VPConfigurationLevel::Level_6,
        VPConfigurationLevel::Level_6_1,
        VPConfigurationLevel::Level_6_2,
    };

    ASSERT(std::is_sorted(std::begin(validLevels), std::end(validLevels)));
    return std::binary_search(std::begin(validLevels), std::end(validLevels), level);
}

static bool isValidVPColorPrimaries(uint8_t colorPrimaries)
{
    constexpr uint8_t validColorPrimaries[] = {
        VPConfigurationColorPrimaries::BT_709_6,
        VPConfigurationColorPrimaries::Unspecified,
        VPConfigurationColorPrimaries::BT_470_6_M,
        VPConfigurationColorPrimaries::BT_470_7_BG,
        VPConfigurationColorPrimaries::BT_601_7,
        VPConfigurationColorPrimaries::SMPTE_ST_240,
        VPConfigurationColorPrimaries::Film,
        VPConfigurationColorPrimaries::BT_2020_Nonconstant_Luminance,
        VPConfigurationColorPrimaries::SMPTE_ST_428_1,
        VPConfigurationColorPrimaries::SMPTE_RP_431_2,
        VPConfigurationColorPrimaries::SMPTE_EG_432_1,
        VPConfigurationColorPrimaries::EBU_Tech_3213_E,
    };

    ASSERT(std::is_sorted(std::begin(validColorPrimaries), std::end(validColorPrimaries)));
    return std::binary_search(std::begin(validColorPrimaries), std::end(validColorPrimaries), colorPrimaries);
}

static bool isValidVPTransferCharacteristics(uint8_t transferCharacteristics)
{
    constexpr uint8_t validTransferCharacteristics[] = {
        VPConfigurationTransferCharacteristics::BT_709_6,
        VPConfigurationTransferCharacteristics::Unspecified,
        VPConfigurationTransferCharacteristics::BT_470_6_M,
        VPConfigurationTransferCharacteristics::BT_470_7_BG,
        VPConfigurationTransferCharacteristics::BT_601_7,
        VPConfigurationTransferCharacteristics::SMPTE_ST_240,
        VPConfigurationTransferCharacteristics::Linear,
        VPConfigurationTransferCharacteristics::Logrithmic,
        VPConfigurationTransferCharacteristics::Logrithmic_Sqrt,
        VPConfigurationTransferCharacteristics::IEC_61966_2_4,
        VPConfigurationTransferCharacteristics::BT_1361_0,
        VPConfigurationTransferCharacteristics::IEC_61966_2_1,
        VPConfigurationTransferCharacteristics::BT_2020_10bit,
        VPConfigurationTransferCharacteristics::BT_2020_12bit,
        VPConfigurationTransferCharacteristics::SMPTE_ST_2084,
        VPConfigurationTransferCharacteristics::SMPTE_ST_428_1,
        VPConfigurationTransferCharacteristics::BT_2100_HLG,
    };
    ASSERT(std::is_sorted(std::begin(validTransferCharacteristics), std::end(validTransferCharacteristics)));
    return std::binary_search(std::begin(validTransferCharacteristics), std::end(validTransferCharacteristics), transferCharacteristics);
}

static bool isValidVPMatrixCoefficients(uint8_t matrixCoefficients)
{
    constexpr uint8_t validMatrixCoefficients[] = {
        VPConfigurationMatrixCoefficients::Identity,
        VPConfigurationMatrixCoefficients::BT_709_6,
        VPConfigurationMatrixCoefficients::Unspecified,
        VPConfigurationMatrixCoefficients::FCC,
        VPConfigurationMatrixCoefficients::BT_470_7_BG,
        VPConfigurationMatrixCoefficients::BT_601_7,
        VPConfigurationMatrixCoefficients::SMPTE_ST_240,
        VPConfigurationMatrixCoefficients::YCgCo,
        VPConfigurationMatrixCoefficients::BT_2020_Nonconstant_Luminance,
        VPConfigurationMatrixCoefficients::BT_2020_Constant_Luminance,
        VPConfigurationMatrixCoefficients::SMPTE_ST_2085,
        VPConfigurationMatrixCoefficients::Chromacity_Constant_Luminance,
        VPConfigurationMatrixCoefficients::Chromacity_Nonconstant_Luminance,
        VPConfigurationMatrixCoefficients::BT_2100_ICC,
    };
    ASSERT(std::is_sorted(std::begin(validMatrixCoefficients), std::end(validMatrixCoefficients)));
    return std::binary_search(std::begin(validMatrixCoefficients), std::end(validMatrixCoefficients), matrixCoefficients);
}

std::optional<VPCodecConfigurationRecord> parseVPCodecParameters(StringView codecView)
{
    auto codecSplit = codecView.split('.');
    auto nextElement = codecSplit.begin();
    if (nextElement == codecSplit.end())
        return std::nullopt;

    VPCodecConfigurationRecord configuration;

    configuration.codecName = (*nextElement).toString();
    ++nextElement;

    // Support the legacy identifiers (with no parameters) for VP8 and VP9.
    if ((configuration.codecName == "vp8" || configuration.codecName == "vp9") && nextElement == codecSplit.end())
        return configuration;

    // The format of the 'vp09' codec string is specified in the webm GitHub repo:
    // <https://github.com/webmproject/vp9-dash/blob/master/VPCodecISOMediaFileFormatBinding.md#codecs-parameter-string>

    // "sample entry 4CC, profile, level, and bitDepth are all mandatory fields. If any of these fields are empty, or not
    // within their allowed range, the processing device SHALL treat it as an error."

    // Codec identifier: legal values are 'vp08' or 'vp09'.
    if (configuration.codecName != "vp08" && configuration.codecName != "vp09")
        return std::nullopt;

    if (nextElement == codecSplit.end())
        return std::nullopt;

    // First element: profile. Legal values are 0-3.
    auto profile = parseInteger<uint8_t>(*nextElement);
    if (!profile || *profile > 3)
        return std::nullopt;
    configuration.profile = *profile;

    if (++nextElement == codecSplit.end())
        return std::nullopt;

    // Second element: level. Legal values are enumerated in validVPLevels above.
    auto level = parseInteger<uint8_t>(*nextElement);
    if (!level || !isValidVPLevel(*level))
        return std::nullopt;
    configuration.level = *level;

    if (++nextElement == codecSplit.end())
        return std::nullopt;

    // Third element: bitDepth. Legal values are 8, 10, and 12.
    auto bitDepth = parseInteger<uint8_t>(*nextElement);
    if (!bitDepth || (*bitDepth != 8 && *bitDepth != 10 && *bitDepth != 12))
        return std::nullopt;
    configuration.bitDepth = *bitDepth;

    // "colorPrimaries, transferCharacteristics, matrixCoefficients, videoFullRangeFlag, and chromaSubsampling are OPTIONAL,
    // mutually inclusive (all or none) fields. If not specified then the processing device MUST use the values listed in the
    // table below as defaults when deciding if the device is able to decode and potentially render the video."

    if (++nextElement == codecSplit.end())
        return configuration;

    // Fourth element: chromaSubsampling. Legal values are 0-3.
    auto chromaSubsampling = parseInteger<uint8_t>(*nextElement);
    if (!chromaSubsampling || *chromaSubsampling > VPConfigurationChromaSubsampling::Subsampling_444)
        return std::nullopt;
    configuration.chromaSubsampling = *chromaSubsampling;

    if (++nextElement == codecSplit.end())
        return std::nullopt;

    // Fifth element: colorPrimaries. Legal values are defined by ISO/IEC 23001-8:2016, superseded
    // by ISO/IEC 23091-2:2019.
    auto colorPrimaries = parseInteger<uint8_t>(*nextElement);
    if (!colorPrimaries || !isValidVPColorPrimaries(*colorPrimaries))
        return std::nullopt;
    configuration.colorPrimaries = *colorPrimaries;

    if (++nextElement == codecSplit.end())
        return std::nullopt;

    // Sixth element: transferCharacteristics. Legal values are defined by ISO/IEC 23001-8:2016, superseded
    // by ISO/IEC 23091-2:2019.
    auto transferCharacteristics = parseInteger<uint8_t>(*nextElement);
    if (!transferCharacteristics || !isValidVPTransferCharacteristics(*transferCharacteristics))
        return std::nullopt;
    configuration.transferCharacteristics = *transferCharacteristics;

    if (++nextElement == codecSplit.end())
        return std::nullopt;

    // Seventh element: matrixCoefficients. Legal values are defined by ISO/IEC 23001-8:2016, superseded
    // by ISO/IEC 23091-2:2019.
    auto matrixCoefficients = parseInteger<uint8_t>(*nextElement);
    if (!matrixCoefficients || !isValidVPMatrixCoefficients(*matrixCoefficients))
        return std::nullopt;
    configuration.matrixCoefficients = *matrixCoefficients;

    // "If matrixCoefficients is 0 (RGB), then chroma subsampling MUST be 3 (4:4:4)."
    if (!configuration.matrixCoefficients && configuration.chromaSubsampling != 3)
        return std::nullopt;

    if (++nextElement == codecSplit.end())
        return std::nullopt;

    // Eighth element: videoFullRangeFlag. Legal values are 0 and 1.
    auto videoFullRangeFlag = parseInteger<uint8_t>(*nextElement);
    if (!videoFullRangeFlag || *videoFullRangeFlag > 1)
        return std::nullopt;
    configuration.videoFullRangeFlag = *videoFullRangeFlag;

    if (++nextElement != codecSplit.end())
        return std::nullopt;

    return configuration;
}

}
