x265-1.8版本-encoder/level.cpp注释

注:问号以及未注释部分 会在x265-1.9版本内更新

/*****************************************************************************
 * Copyright (C) 2013 x265 project
 *
 * Authors: Steve Borho 
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
 *
 * This program is also available under a commercial proprietary license.
 * For more information, contact us at license @ x265.com.
 *****************************************************************************/

#include "common.h"
#include "slice.h"
#include "level.h"

namespace X265_NS {
typedef struct
{
    uint32_t maxLumaSamples;//每帧最大亮度像素个数
    uint32_t maxLumaSamplesPerSecond;//每秒传输最多的亮度像素个数
    uint32_t maxBitrateMain;//Main tier 的最大比特率 (kbps)
    uint32_t maxBitrateHigh;//High tier 的最大比特率 (kbps)
    uint32_t maxCpbSizeMain;//MAIN层次CPB占用的最大bits数目kbps coded picture buffer (CPB)
    uint32_t maxCpbSizeHigh;//HIGH层次CPB占用的最大bits数目kbps coded picture buffer (CPB)
    uint32_t minCompressionRatio;//最小压缩比
    Level::Name levelEnum;//级别名称
    const char* name;//级别名字 字符串
    int levelIdc;//级别标号 (十位为级别主号,个位为级别副号)
} LevelSpec;

//更层次级别对应的数据
LevelSpec levels[] =
{
//分别为:每帧最大亮度像素个数、每秒传输最多的亮度像素个数、Main tier 的最大比特率 (kbps)、High tier 的最大比特率 (kbps)、MAIN层次CPB占用的最大bits数目kbps、HIGH层次CPB占用的最大bits数目kbps、最小压缩比、级别名称、级别名称字符串、级别标号(十位为级别主号,个位为级别副号)
    { 36864,    552960,     128,      MAX_UINT, 350,    MAX_UINT, 2, Level::LEVEL1,   "1",   10 },
    { 122880,   3686400,    1500,     MAX_UINT, 1500,   MAX_UINT, 2, Level::LEVEL2,   "2",   20 },
    { 245760,   7372800,    3000,     MAX_UINT, 3000,   MAX_UINT, 2, Level::LEVEL2_1, "2.1", 21 },
    { 552960,   16588800,   6000,     MAX_UINT, 6000,   MAX_UINT, 2, Level::LEVEL3,   "3",   30 },
    { 983040,   33177600,   10000,    MAX_UINT, 10000,  MAX_UINT, 2, Level::LEVEL3_1, "3.1", 31 },
    { 2228224,  66846720,   12000,    30000,    12000,  30000,    4, Level::LEVEL4,   "4",   40 },
    { 2228224,  133693440,  20000,    50000,    20000,  50000,    4, Level::LEVEL4_1, "4.1", 41 },
    { 8912896,  267386880,  25000,    100000,   25000,  100000,   6, Level::LEVEL5,   "5",   50 },
    { 8912896,  534773760,  40000,    160000,   40000,  160000,   8, Level::LEVEL5_1, "5.1", 51 },
    { 8912896,  1069547520, 60000,    240000,   60000,  240000,   8, Level::LEVEL5_2, "5.2", 52 },
    { 35651584, 1069547520, 60000,    240000,   60000,  240000,   8, Level::LEVEL6,   "6",   60 },
    { 35651584, 2139095040, 120000,   480000,   120000, 480000,   8, Level::LEVEL6_1, "6.1", 61 },
    { 35651584, 4278190080U, 240000,  800000,   240000, 800000,   6, Level::LEVEL6_2, "6.2", 62 },
    { MAX_UINT, MAX_UINT, MAX_UINT, MAX_UINT, MAX_UINT, MAX_UINT, 1, Level::LEVEL8_5, "8.5", 85 },
};

/* determine minimum decoder level required to decode the described video */
/** 函数功能             : 根据当前配置信息自动设置当前编码序列的档次、层次和级别
/*  调用范围             : 只在x265_encoder *x265_encoder_open函数中被调用
* \参数 param            : 配置参数
* \参数 vps              : encoder类中的vps
* \返回                  : null * */
void determineLevel(const x265_param ¶m, VPS& vps)
{
    vps.ptl.onePictureOnlyConstraintFlag = param.totalFrames == 1;//当前需要编码的是否只有一帧
    vps.ptl.intraConstraintFlag = param.keyframeMax <= 1 || vps.ptl.onePictureOnlyConstraintFlag;//判断是否全I帧
    vps.ptl.bitDepthConstraint = param.internalBitDepth;//像素位宽 8 10 12
    vps.ptl.chromaFormatConstraint = param.internalCsp;//图像格式

    /* TODO: figure out HighThroughput signaling, aka: HbrFactor in section A.4.2, only available
     * for intra-only profiles (vps.ptl.intraConstraintFlag) */
    vps.ptl.lowerBitRateConstraintFlag = true;//置为true 暂不应用

    vps.maxTempSubLayers = param.bEnableTemporalSubLayers ? 2 : 1;//最大时域层个数
    
    if (param.internalCsp == X265_CSP_I420 && param.internalBitDepth <= 10)//如果是420格式 并且位宽小于10
    {
        /* Probably an HEVC v1 profile, but must check to be sure */
        if (param.internalBitDepth <= 8) //如果位宽小于8
        {
            if (vps.ptl.onePictureOnlyConstraintFlag) //当前只需要编码一帧
                vps.ptl.profileIdc = Profile::MAINSTILLPICTURE; //确定为MAINSTILLPICTURE档次 当做静止图像编码
            else if (vps.ptl.intraConstraintFlag)//全I帧
                vps.ptl.profileIdc = Profile::MAINREXT; /* Main Intra */
            else 
                vps.ptl.profileIdc = Profile::MAIN;
        }
        else if (param.internalBitDepth <= 10)//如果是10位位宽
        {
            /* note there is no 10bit still picture profile */
            if (vps.ptl.intraConstraintFlag)//全I帧
                vps.ptl.profileIdc = Profile::MAINREXT; /* Main10 Intra */
            else
                vps.ptl.profileIdc = Profile::MAIN10;
        }
    }
    else
        vps.ptl.profileIdc = Profile::MAINREXT; //其它档次

    /* determine which profiles are compatible with this stream */

    //设置是否应用档次
    /*
    MAIN            : MAIN、 MAIN10 置为true 其它为false
    MAIN10并且8位   : MAIN、 MAIN10 置为true 其它为false
    MAINSTILLPICTURE:  MAIN、 MAIN10 MAINSTILLPICTURE 置为true 其它为false
    MAIN10          : MAIN10 置为true 其它为false
    MAINREXT        : MAINREXT 置为true 其它为false
    **/
    memset(vps.ptl.profileCompatibilityFlag, 0, sizeof(vps.ptl.profileCompatibilityFlag));//全部初始化为0
    vps.ptl.profileCompatibilityFlag[vps.ptl.profileIdc] = true; //将对应档次置为true
    if (vps.ptl.profileIdc == Profile::MAIN10 && param.internalBitDepth == 8)
        vps.ptl.profileCompatibilityFlag[Profile::MAIN] = true;
    else if (vps.ptl.profileIdc == Profile::MAIN)
        vps.ptl.profileCompatibilityFlag[Profile::MAIN10] = true;
    else if (vps.ptl.profileIdc == Profile::MAINSTILLPICTURE)
    {
        vps.ptl.profileCompatibilityFlag[Profile::MAIN] = true;
        vps.ptl.profileCompatibilityFlag[Profile::MAIN10] = true;
    }
    else if (vps.ptl.profileIdc == Profile::MAINREXT)
        vps.ptl.profileCompatibilityFlag[Profile::MAINREXT] = true;

    uint32_t lumaSamples = param.sourceWidth * param.sourceHeight;//一帧亮度像素个数
    uint32_t samplesPerSec = (uint32_t)(lumaSamples * ((double)param.fpsNum / param.fpsDenom));//一秒钟需要传输的亮度像素点个数
    uint32_t bitrate = param.rc.vbvMaxBitrate ? param.rc.vbvMaxBitrate : param.rc.bitrate;//获取当前配置的最大每秒比特率 Kpbs

    const uint32_t MaxDpbPicBuf = 6; //用于计算当前level的 DPB的最大长度
    vps.ptl.levelIdc = Level::NONE;//初始化Level为0
    vps.ptl.tierFlag = Level::MAIN;//初始化层次为Main
    const size_t NumLevels = sizeof(levels) / sizeof(levels[0]);//获取当前编码器Level个数
    uint32_t i;//用于记录当前level在在levels数组标号
    if (param.bLossless)//如果当前配置的是无损压缩
    {
        i = 13;//level_8_5 在levels数组标号
        vps.ptl.minCrForLevel = 1;// 当前的最小压缩比 CR 表示 CompressionRatio 无损压缩1:1
        vps.ptl.maxLumaSrForLevel = MAX_UINT;//该等级每帧最大亮度像素个数
        vps.ptl.levelIdc = Level::LEVEL8_5; //当前等级
        vps.ptl.tierFlag = Level::MAIN;     //当前层次
    }
    else for (i = 0; i < NumLevels; i++) //遍历所有level
    {
        if (lumaSamples > levels[i].maxLumaSamples)//如果当前一帧亮度个数大于当前级别规定个数 继续遍历下一个级别
            continue;
        else if (samplesPerSec > levels[i].maxLumaSamplesPerSecond)//如果当前一秒钟需要传输的亮度像素点个数大于当前级别规定个数 继续遍历下一个级别
            continue;
        else if (bitrate > levels[i].maxBitrateMain && levels[i].maxBitrateHigh == MAX_UINT)//如果当前配置最大码率大于当前级别规定码率 继续遍历下一个级别 (当前级别无High层次)
            continue;
        else if (bitrate > levels[i].maxBitrateHigh)//如果当前配置最大码率大于当前级别规定码率 继续遍历下一个级别 
            continue;
        else if (param.sourceWidth > sqrt(levels[i].maxLumaSamples * 8.0f))//图像宽高受到该级别定义参数MaxLumaPS的限制—图像的宽和高均小于等于8倍的MaxLumaPS再开方
            continue;
        else if (param.sourceHeight > sqrt(levels[i].maxLumaSamples * 8.0f))//图像宽高受到该级别定义参数MaxLumaPS的限制—图像的宽和高均小于等于8倍的MaxLumaPS再开方
            continue;
        //最大参考帧个数为16  确定当前level的 DPB的最大长度
        uint32_t maxDpbSize = MaxDpbPicBuf;//当前level的 DPB的最大长度
        if (lumaSamples <= (levels[i].maxLumaSamples >> 2))
            maxDpbSize = X265_MIN(4 * MaxDpbPicBuf, 16);
        else if (lumaSamples <= (levels[i].maxLumaSamples >> 1))
            maxDpbSize = X265_MIN(2 * MaxDpbPicBuf, 16);
        else if (lumaSamples <= ((3 * levels[i].maxLumaSamples) >> 2))
            maxDpbSize = X265_MIN((4 * MaxDpbPicBuf) / 3, 16);

        /* The value of sps_max_dec_pic_buffering_minus1[ HighestTid ] + 1 shall be less than
         * or equal to MaxDpbSize */
        if (vps.maxDecPicBuffering > maxDpbSize)//如果当前DPB的长度不符合规则,继续遍历下一个级别
            continue;

        /* For level 5 and higher levels, the value of CtbSizeY shall be equal to 32 or 64 */
        if (levels[i].levelEnum >= Level::LEVEL5 && param.maxCUSize < 32)//level 大于等于 Level::LEVEL5时,CTB必须大于等于32
        {
            x265_log(¶m, X265_LOG_WARNING, "level %s detected, but CTU size 16 is non-compliant\n", levels[i].name);
            vps.ptl.profileIdc = Profile::NONE;
            vps.ptl.levelIdc = Level::NONE;
            vps.ptl.tierFlag = Level::MAIN;
            x265_log(¶m, X265_LOG_INFO, "NONE profile, Level-NONE (Main tier)\n");
            return;
        }

        /* The value of NumPocTotalCurr shall be less than or equal to 8 */
        int numPocTotalCurr = param.maxNumReferences + vps.numReorderPics;//全部参考帧个数
        if (numPocTotalCurr > 8)//全部参考帧个数不能大于8
        {
            x265_log(¶m, X265_LOG_WARNING, "level %s detected, but NumPocTotalCurr (total references) is non-compliant\n", levels[i].name);
            vps.ptl.profileIdc = Profile::NONE;
            vps.ptl.levelIdc = Level::NONE;
            vps.ptl.tierFlag = Level::MAIN;
            x265_log(¶m, X265_LOG_INFO, "NONE profile, Level-NONE (Main tier)\n");
            return;
        }

#define CHECK_RANGE(value, main, high) (high != MAX_UINT && value > main && value <= high)

        if (CHECK_RANGE(bitrate, levels[i].maxBitrateMain, levels[i].maxBitrateHigh) ||
            CHECK_RANGE((uint32_t)param.rc.vbvBufferSize, levels[i].maxCpbSizeMain, levels[i].maxCpbSizeHigh)) //bits是否超出范围
        {
            /* The bitrate or buffer size are out of range for Main tier, but in
             * range for High tier. If the user requested High tier then give
             * them High tier at this level.  Otherwise allow the loop to
             * progress to the Main tier of the next level */
            if (param.bHighTier)//如果采用HIGH层次
                vps.ptl.tierFlag = Level::HIGH;
            else
                continue;
        }
        else
            vps.ptl.tierFlag = Level::MAIN;
#undef CHECK_RANGE

        vps.ptl.levelIdc = levels[i].levelEnum;//设置等级
        vps.ptl.minCrForLevel = levels[i].minCompressionRatio;//设置当前的最小压缩比 CR 表示 CompressionRatio 
        vps.ptl.maxLumaSrForLevel = levels[i].maxLumaSamplesPerSecond;//该等级每帧最大亮度像素个数
        break;
    }//for (i = 0; i < NumLevels; i++) 遍历所有level

    static const char *profiles[] = { "None", "Main", "Main 10", "Main Still Picture", "RExt" };
    static const char *tiers[]    = { "Main", "High" };

    char profbuf[64];//用于存储档次名称
    strcpy(profbuf, profiles[vps.ptl.profileIdc]);//copy当前的档次名称

    bool bStillPicture = false;//是否只编码一帧
    if (vps.ptl.profileIdc == Profile::MAINREXT) //如果属于扩展档次或者全I帧
    {
        if (vps.ptl.bitDepthConstraint > 12 && vps.ptl.intraConstraintFlag)//如果12位宽 并且全I帧
        {
            if (vps.ptl.onePictureOnlyConstraintFlag)//是否只编码一帧
            {
                strcpy(profbuf, "Main 4:4:4 16 Still Picture");
                bStillPicture = true;
            }
            else
                strcpy(profbuf, "Main 4:4:4 16");
        }
        else if (param.internalCsp == X265_CSP_I420)//如果是420格式 确定相应档次
        {
            X265_CHECK(vps.ptl.intraConstraintFlag || vps.ptl.bitDepthConstraint > 10, "rext fail\n");
            if (vps.ptl.bitDepthConstraint <= 8)
                strcpy(profbuf, "Main");
            else if (vps.ptl.bitDepthConstraint <= 10)
                strcpy(profbuf, "Main 10");
            else if (vps.ptl.bitDepthConstraint <= 12)
                strcpy(profbuf, "Main 12");
        }
        else if (param.internalCsp == X265_CSP_I422)//4:2:2格式
        {
            /* there is no Main 4:2:2 profile, so it must be signaled as Main10 4:2:2 */
            if (param.internalBitDepth <= 10)
                strcpy(profbuf, "Main 4:2:2 10");
            else if (vps.ptl.bitDepthConstraint <= 12)
                strcpy(profbuf, "Main 4:2:2 12");
        }
        else if (param.internalCsp == X265_CSP_I444)//4:4:4格式
        {
            if (vps.ptl.bitDepthConstraint <= 8)
            {
                if (vps.ptl.onePictureOnlyConstraintFlag)
                {
                    strcpy(profbuf, "Main 4:4:4 Still Picture");
                    bStillPicture = true;
                }
                else
                    strcpy(profbuf, "Main 4:4:4");
            }
            else if (vps.ptl.bitDepthConstraint <= 10)
                strcpy(profbuf, "Main 4:4:4 10");
            else if (vps.ptl.bitDepthConstraint <= 12)
                strcpy(profbuf, "Main 4:4:4 12");
        }
        else
            strcpy(profbuf, "Unknown");

        if (vps.ptl.intraConstraintFlag && !bStillPicture)
            strcat(profbuf, " Intra");
    }
    x265_log(¶m, X265_LOG_INFO, "%s profile, Level-%s (%s tier)\n",
             profbuf, levels[i].name, tiers[vps.ptl.tierFlag]); //打印log信息
}

/* enforce a maximum decoder level requirement, in other words assure that a
 * decoder of the specified level may decode the video about to be created.
 * Lower parameters where necessary to ensure the video will be decodable by a
 * decoder meeting this level of requirement.  Some parameters (resolution and
 * frame rate) are non-negotiable and thus this function may fail. In those
 * circumstances it will be quite noisy */
/** 函数功能             : ???分析加权信息(每个list的第一帧分析加权与否,其它不加权)
/*  调用范围             : 只在x265_encoder *x265_encoder_open函数中被调用
* \参数 param            : 配置参数
* \参数 vps              : encoder类中的vps
* \返回                  : ??null * */
bool enforceLevel(x265_param& param, VPS& vps)
{
    vps.numReorderPics = (param.bBPyramid && param.bframes > 1) ? 2 : !!param.bframes;//需要重排序的帧数
    vps.maxDecPicBuffering = X265_MIN(MAX_NUM_REF, X265_MAX(vps.numReorderPics + 2, (uint32_t)param.maxNumReferences) + vps.numReorderPics);//解码需要的buffer大小

    /* no level specified by user, just auto-detect from the configuration */
    if (param.levelIdc <= 0)//????
        return true;

    uint32_t level = 0;
    while (levels[level].levelIdc != param.levelIdc && level + 1 < sizeof(levels) / sizeof(levels[0]))
        level++;
    if (levels[level].levelIdc != param.levelIdc)
    {
        x265_log(¶m, X265_LOG_WARNING, "specified level %d does not exist\n", param.levelIdc);
        return false;
    }

    LevelSpec& l = levels[level];
    bool highTier = !!param.bHighTier;
    if (highTier && l.maxBitrateHigh == MAX_UINT)
    {
        highTier = false;
        x265_log(¶m, X265_LOG_WARNING, "Level %s has no High tier, using Main tier\n", l.name);
    }

    uint32_t lumaSamples = param.sourceWidth * param.sourceHeight;
    uint32_t samplesPerSec = (uint32_t)(lumaSamples * ((double)param.fpsNum / param.fpsDenom));
    bool ok = true;
    if (lumaSamples > l.maxLumaSamples)
        ok = false;
    else if (param.sourceWidth > sqrt(l.maxLumaSamples * 8.0f))
        ok = false;
    else if (param.sourceHeight > sqrt(l.maxLumaSamples * 8.0f))
        ok = false;
    if (!ok)
    {
        x265_log(¶m, X265_LOG_WARNING, "picture dimensions are out of range for specified level\n");
        return false;
    }
    else if (samplesPerSec > l.maxLumaSamplesPerSecond)
    {
        x265_log(¶m, X265_LOG_WARNING, "frame rate is out of range for specified level\n");
        return false;
    }

    if ((uint32_t)param.rc.vbvMaxBitrate > (highTier ? l.maxBitrateHigh : l.maxBitrateMain))
    {
        param.rc.vbvMaxBitrate = highTier ? l.maxBitrateHigh : l.maxBitrateMain;
        x265_log(¶m, X265_LOG_INFO, "lowering VBV max bitrate to %dKbps\n", param.rc.vbvMaxBitrate);
    }
    if ((uint32_t)param.rc.vbvBufferSize > (highTier ? l.maxCpbSizeHigh : l.maxCpbSizeMain))
    {
        param.rc.vbvBufferSize = highTier ? l.maxCpbSizeHigh : l.maxCpbSizeMain;
        x265_log(¶m, X265_LOG_INFO, "lowering VBV buffer size to %dKb\n", param.rc.vbvBufferSize);
    }

    switch (param.rc.rateControlMode)
    {
    case X265_RC_ABR:
        if ((uint32_t)param.rc.bitrate > (highTier ? l.maxBitrateHigh : l.maxBitrateMain))
        {
            param.rc.bitrate = l.maxBitrateHigh;
            x265_log(¶m, X265_LOG_INFO, "lowering target bitrate to High tier limit of %dKbps\n", param.rc.bitrate);
        }
        break;

    case X265_RC_CQP:
        x265_log(¶m, X265_LOG_WARNING, "Constant QP is inconsistent with specifying a decoder level, no bitrate guarantee is possible.\n");
        return false;

    case X265_RC_CRF:
        if (!param.rc.vbvBufferSize || !param.rc.vbvMaxBitrate)
        {
            if (!param.rc.vbvMaxBitrate)
                param.rc.vbvMaxBitrate = highTier ? l.maxBitrateHigh : l.maxBitrateMain;
            if (!param.rc.vbvBufferSize)
                param.rc.vbvBufferSize = highTier ? l.maxCpbSizeHigh : l.maxCpbSizeMain;
            x265_log(¶m, X265_LOG_WARNING, "Specifying a decoder level with constant rate factor rate-control requires\n");
            x265_log(¶m, X265_LOG_WARNING, "enabling VBV with vbv-bufsize=%dkb vbv-maxrate=%dkbps. VBV outputs are non-deterministic!\n",
                     param.rc.vbvBufferSize, param.rc.vbvMaxBitrate);
        }
        break;

    default:
        x265_log(¶m, X265_LOG_ERROR, "Unknown rate control mode is inconsistent with specifying a decoder level\n");
        return false;
    }

    /* The value of sps_max_dec_pic_buffering_minus1[ HighestTid ] + 1 shall be less than or equal to MaxDpbSize */
    const uint32_t MaxDpbPicBuf = 6;
    uint32_t maxDpbSize = MaxDpbPicBuf;
    if (lumaSamples <= (l.maxLumaSamples >> 2))
        maxDpbSize = X265_MIN(4 * MaxDpbPicBuf, 16);
    else if (lumaSamples <= (l.maxLumaSamples >> 1))
        maxDpbSize = X265_MIN(2 * MaxDpbPicBuf, 16);
    else if (lumaSamples <= ((3 * l.maxLumaSamples) >> 2))
        maxDpbSize = X265_MIN((4 * MaxDpbPicBuf) / 3, 16);

    int savedRefCount = param.maxNumReferences;
    while (vps.maxDecPicBuffering > maxDpbSize && param.maxNumReferences > 1)
    {
        param.maxNumReferences--;
        vps.maxDecPicBuffering = X265_MIN(MAX_NUM_REF, X265_MAX(vps.numReorderPics + 1, (uint32_t)param.maxNumReferences) + vps.numReorderPics);
    }
    if (param.maxNumReferences != savedRefCount)
        x265_log(¶m, X265_LOG_INFO, "Lowering max references to %d to meet level requirement\n", param.maxNumReferences);

    /* For level 5 and higher levels, the value of CtbSizeY shall be equal to 32 or 64 */
    if (param.levelIdc >= 50 && param.maxCUSize < 32)
    {
        param.maxCUSize = 32;
        x265_log(¶m, X265_LOG_INFO, "Levels 5.0 and above require a maximum CTU size of at least 32, using --ctu 32\n");
    }

    /* The value of NumPocTotalCurr shall be less than or equal to 8 */
    int numPocTotalCurr = param.maxNumReferences + !!param.bframes;
    if (numPocTotalCurr > 8)
    {
        param.maxNumReferences = 8 - !!param.bframes;
        x265_log(¶m, X265_LOG_INFO, "Lowering max references to %d to meet numPocTotalCurr requirement\n", param.maxNumReferences);
    }

    return true;
}
}

#if EXPORT_C_API

/* these functions are exported as C functions (default) */
using namespace X265_NS;
extern "C" {

#else

/* these functions exist within private namespace (multilib) */
namespace X265_NS {

#endif

int x265_param_apply_profile(x265_param *param, const char *profile)
{
    if (!param || !profile)
        return 0;

    /* Check if profile bit-depth requirement is exceeded by internal bit depth */
    bool bInvalidDepth = false;
#if X265_DEPTH > 8
    if (!strcmp(profile, "main") || !strcmp(profile, "mainstillpicture") || !strcmp(profile, "msp") ||
        !strcmp(profile, "main444-8") || !strcmp(profile, "main-intra") ||
        !strcmp(profile, "main444-intra") || !strcmp(profile, "main444-stillpicture"))
        bInvalidDepth = true;
#endif
#if X265_DEPTH > 10
    if (!strcmp(profile, "main10") || !strcmp(profile, "main422-10") || !strcmp(profile, "main444-10") ||
        !strcmp(profile, "main10-intra") || !strcmp(profile, "main422-10-intra") || !strcmp(profile, "main444-10-intra"))
        bInvalidDepth = true;
#endif
#if X265_DEPTH > 12
    if (!strcmp(profile, "main12") || !strcmp(profile, "main422-12") || !strcmp(profile, "main444-12") ||
        !strcmp(profile, "main12-intra") || !strcmp(profile, "main422-12-intra") || !strcmp(profile, "main444-12-intra"))
        bInvalidDepth = true;
#endif

    if (bInvalidDepth)
    {
        x265_log(param, X265_LOG_ERROR, "%s profile not supported, internal bit depth %d.\n", profile, X265_DEPTH);
        return -1;
    }

    size_t l = strlen(profile);
    bool bBoolIntra = (l > 6 && !strcmp(profile + l - 6, "-intra")) ||
                      !strcmp(profile, "mainstillpicture") || !strcmp(profile, "msp");
    if (bBoolIntra)
    {
        /* The profile may be detected as still picture if param->totalFrames is 1 */
        param->keyframeMax = 1;
    }
    
    /* check that input color space is supported by profile */
    if (!strcmp(profile, "main") || !strcmp(profile, "main-intra") ||
        !strcmp(profile, "main10") || !strcmp(profile, "main10-intra") ||
        !strcmp(profile, "main12") || !strcmp(profile, "main12-intra") ||
        !strcmp(profile, "mainstillpicture") || !strcmp(profile, "msp"))
    {
        if (param->internalCsp != X265_CSP_I420)
        {
            x265_log(param, X265_LOG_ERROR, "%s profile not compatible with %s input color space.\n",
                     profile, x265_source_csp_names[param->internalCsp]);
            return -1;
        }
    }
    else if (!strcmp(profile, "main422-10") || !strcmp(profile, "main422-10-intra") ||
             !strcmp(profile, "main422-12") || !strcmp(profile, "main422-12-intra"))
    {
        if (param->internalCsp != X265_CSP_I420 && param->internalCsp != X265_CSP_I422)
        {
            x265_log(param, X265_LOG_ERROR, "%s profile not compatible with %s input color space.\n",
                     profile, x265_source_csp_names[param->internalCsp]);
            return -1;
        }
    }
    else if (!strcmp(profile, "main444-8") ||
             !strcmp(profile, "main444-intra") || !strcmp(profile, "main444-stillpicture") ||
             !strcmp(profile, "main444-10") || !strcmp(profile, "main444-10-intra") ||
             !strcmp(profile, "main444-12") || !strcmp(profile, "main444-12-intra") ||
             !strcmp(profile, "main444-16-intra") || !strcmp(profile, "main444-16-stillpicture"))
    {
        /* any color space allowed */
    }
    else
    {
        x265_log(param, X265_LOG_ERROR, "unknown profile <%s>\n", profile);
        return -1;
    }

    return 0;
}
}


 

你可能感兴趣的:(x265代码注释)