x265-1.8版本-common/cudata.cpp注释

HEVC编码技术解析与应用
本文深入探讨了HEVC编码技术的核心原理与实践应用,包括几何信息计算、CU数据初始化、熵编码参数获取等内容,重点阐述了尺寸小的TU(Luma8x8/4x4,Chroma4x4/2x2)的扫描方式选择以及预测方向对扫描顺序的影响。文章旨在为理解和优化HEVC编码提供技术支持。

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

/*****************************************************************************
 * Copyright (C) 2015 x265 project
 *
 * Authors: Steve Borho <steve@borho.org>
 *
 * 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 "frame.h"
#include "framedata.h"
#include "picyuv.h"
#include "mv.h"
#include "cudata.h"

using namespace X265_NS;

/* for all bcast* and copy* functions, dst and src are aligned to MIN(size, 32) */

static void bcast1(uint8_t* dst, uint8_t val)  { dst[0] = val; }//一次性set 1个数据  

static void copy4(uint8_t* dst, uint8_t* src)  { ((uint32_t*)dst)[0] = ((uint32_t*)src)[0]; }//一次性copy 4个数据  分成1个32位数字赋值
static void bcast4(uint8_t* dst, uint8_t val)  { ((uint32_t*)dst)[0] = 0x01010101u * val; }//一次性set 4个数据  分成1个32为数字赋值

static void copy16(uint8_t* dst, uint8_t* src) { ((uint64_t*)dst)[0] = ((uint64_t*)src)[0]; ((uint64_t*)dst)[1] = ((uint64_t*)src)[1]; }//一次性copy 16个数据  分成2个64位数字赋值
static void bcast16(uint8_t* dst, uint8_t val) { uint64_t bval = 0x0101010101010101ULL * val; ((uint64_t*)dst)[0] = bval; ((uint64_t*)dst)[1] = bval; }//一次性set 16个数据  分成2个64位数字赋值

static void copy64(uint8_t* dst, uint8_t* src) { ((uint64_t*)dst)[0] = ((uint64_t*)src)[0]; ((uint64_t*)dst)[1] = ((uint64_t*)src)[1]; 
                                                 ((uint64_t*)dst)[2] = ((uint64_t*)src)[2]; ((uint64_t*)dst)[3] = ((uint64_t*)src)[3];
                                                 ((uint64_t*)dst)[4] = ((uint64_t*)src)[4]; ((uint64_t*)dst)[5] = ((uint64_t*)src)[5];
                                                 ((uint64_t*)dst)[6] = ((uint64_t*)src)[6]; ((uint64_t*)dst)[7] = ((uint64_t*)src)[7]; }//一次性copy 64个数据  分成8个64位数字赋值
static void bcast64(uint8_t* dst, uint8_t val) { uint64_t bval = 0x0101010101010101ULL * val;
                                                 ((uint64_t*)dst)[0] = bval; ((uint64_t*)dst)[1] = bval; ((uint64_t*)dst)[2] = bval; ((uint64_t*)dst)[3] = bval;
                                                 ((uint64_t*)dst)[4] = bval; ((uint64_t*)dst)[5] = bval; ((uint64_t*)dst)[6] = bval; ((uint64_t*)dst)[7] = bval; }//一次性set 64个数据  分成8个64位数字赋值

/* at 256 bytes, memset/memcpy will probably use SIMD more effectively than our uint64_t hack,
 * but hand-written assembly would beat it. */
static void copy256(uint8_t* dst, uint8_t* src) { memcpy(dst, src, 256); }//一次性copy256个数据
static void bcast256(uint8_t* dst, uint8_t val) { memset(dst, val, 256); }//一次性set256个数据

namespace {
// file private namespace

/* Check whether 2 addresses point to the same column */
/** 函数功能             : 判断addrA、addrB是否处于同一列
* \参数 addrA            : PU左上角像素点在CTU中的光栅扫描位置
* \参数 addrB            : 当前CU在CTU的光栅扫描位置
* \参数 numUnits         : 一个CTU中每行或者列有多少4x4块
*   返回值               : 返回addrA、addrB是否处于同一列**/
inline bool isEqualCol(int addrA, int addrB, int numUnits)
{
    // addrA % numUnits == addrB % numUnits
    return ((addrA ^ addrB) &  (numUnits - 1)) == 0;
}

/* Check whether 2 addresses point to the same row */
/** 函数功能             : 判断addrA、addrB是否处于同一行
* \参数 addrA            : PU左上角像素点在CTU中的光栅扫描位置
* \参数 addrB            : 当前CU在CTU的光栅扫描位置
* \参数 numUnits         : 一个CTU中每行或者列有多少4x4块
*   返回值               : 返回addrA、addrB是否处于同一行**/
inline bool isEqualRow(int addrA, int addrB, int numUnits)
{
    // addrA / numUnits == addrB / numUnits
    return ((addrA ^ addrB) & ~(numUnits - 1)) == 0;
}

/* Check whether 2 addresses point to the same row or column */
/** 函数功能             : 返回addrA、addrB是否处于同一行或者同一列
* \参数 addrA            : PU左上角像素点在CTU中的光栅扫描位置
* \参数 addrB            : 当前CU在CTU的光栅扫描位置
* \参数 numUnits         : 一个CTU中每行或者列有多少4x4块
*   返回值               : 返回addrA、addrB是否处于同一行或者同一列**/
inline bool isEqualRowOrCol(int addrA, int addrB, int numUnits)
{
    return isEqualCol(addrA, addrB, numUnits) | isEqualRow(addrA, addrB, numUnits);
}

/* Check whether one address points to the first column */
/** 函数功能             : 返回当前位置是否处在CTU列第一列中(是返回ture 否返回false)
* \参数 addr             : 当前位置在CTU的光栅扫描位置
* \参数 numUnits         : 一个CTU中每行或者列有多少4x4块
*   返回值               : 返回当前位置是否处在CTU列第一列中**/
inline bool isZeroCol(int addr, int numUnits)
{
    // addr % numUnits == 0
    return (addr & (numUnits - 1)) == 0;//判断是否为第一列
}

/* Check whether one address points to the first row */
/** 函数功能             : 返回当前位置是否处在CTU行第一行中(是返回ture 否返回false)
* \参数 addr             : 当前位置在CTU的光栅扫描位置
* \参数 numUnits         : 一个CTU中每行或者列有多少4x4块
*   返回值               : 返回当前位置是否处在CTU列第一行中**/
inline bool isZeroRow(int addr, int numUnits)
{
    // addr / numUnits == 0
    return (addr & ~(numUnits - 1)) == 0;//判断是否是第一行
}

/* Check whether one address points to a column whose index is smaller than a given value */
/** 函数功能             : 返回当前参考块是否在同一个CTU内部 针对列
* \参数 addr             : 当前PU位置在CTU的光栅扫描位置
* \参数 val              : numUnits - 当前计数的4x4块
* \参数 numUnits         : 一个CTU中每行或者列有多少4x4块
*   返回值               : 返回当前参考块是否在同一个CTU内部**/
inline bool lessThanCol(int addr, int val, int numUnits)
{
    // addr % numUnits < val
    return (addr & (numUnits - 1)) < val;//PU右上角位置在X中的坐标  小于 numUnits - 当前计数的4x4块
}

/** 函数功能             : 返回当前参考块是否在同一个CTU内部 针对行
* \参数 addr             : 当前PU位置在CTU的光栅扫描位置
* \参数 val              : numUnits - 当前计数的4x4块
* \参数 numUnits         : 一个CTU中每行或者列有多少4x4块
*   返回值               : 返回当前参考块是否在同一个CTU内部**/
/* Check whether one address points to a row whose index is smaller than a given value */
inline bool lessThanRow(int addr, int val, int numUnits)
{
    // addr / numUnits < val
    return addr < val * numUnits;
}

inline MV scaleMv(MV mv, int scale)
{
    int mvx = x265_clip3(-32768, 32767, (scale * mv.x + 127 + (scale * mv.x < 0)) >> 8);
    int mvy = x265_clip3(-32768, 32767, (scale * mv.y + 127 + (scale * mv.y < 0)) >> 8);

    return MV((int16_t)mvx, (int16_t)mvy);
}

}

cubcast_t CUData::s_partSet[NUM_FULL_DEPTH] = { NULL, NULL, NULL, NULL, NULL };//set 函数指针
uint32_t CUData::s_numPartInCUSize;//存储一个CTU中每行或者列有多少4x4块

CUData::CUData()//初始化
{
    memset(this, 0, sizeof(*this));
}
/** 函数功能             :初始化函数指针,获取CTU/CU数据相应存储位置 
/*  调用范围             :只在FrameData::create和Analysis::create函数中被调用
* \参数 dataPool         :CU存储空间 
* \参数 depth            :CU划分深度(FrameData::create 传入 0 Analysis::create 传入相应深度) 
* \参数 csp              :图像格式
* \参数 instance         :每个CU的标号 
* \返回                  :null* */
void CUData::initialize(const CUDataMemPool& dataPool, uint32_t depth, int csp, int instance)
{
    m_chromaFormat  = csp; //获取图像格式
    m_hChromaShift  = CHROMA_H_SHIFT(csp);//获取移位个数
    m_vChromaShift  = CHROMA_V_SHIFT(csp);//获取移位个数
    m_numPartitions = NUM_4x4_PARTITIONS >> (depth * 2);//获取当前CU的4x4块个数

    if (!s_partSet[0])
    {
        s_numPartInCUSize = 1 << g_unitSizeDepth;//获取一个CTU中每行或者列有多少4x4块
        switch (g_maxLog2CUSize) //根据CTU大小 配置相应set函数指针 (所有CUdata类中 只配置一次 共用)
        {
        case 6:
            s_partSet[0] = bcast256;
            s_partSet[1] = bcast64;
            s_partSet[2] = bcast16;
            s_partSet[3] = bcast4;
            s_partSet[4] = bcast1;
            break;
        case 5:
            s_partSet[0] = bcast64;
            s_partSet[1] = bcast16;
            s_partSet[2] = bcast4;
            s_partSet[3] = bcast1;
            s_partSet[4] = NULL;
            break;
        case 4:
            s_partSet[0] = bcast16;
            s_partSet[1] = bcast4;
            s_partSet[2] = bcast1;
            s_partSet[3] = NULL;
            s_partSet[4] = NULL;
            break;
        default:
            X265_CHECK(0, "unexpected CTU size\n");
            break;
        }
    }

    switch (m_numPartitions)//根据具体的CU 4x4块个数选择具体的copy、set、subcopy、subset函数指针
    {
    case 256: // 64x64 CU
        m_partCopy = copy256;
        m_partSet = bcast256;
        m_subPartCopy = copy64;
        m_subPartSet = bcast64;
        break;
    case 64:  // 32x32 CU
        m_partCopy = copy64;
        m_partSet = bcast64;
        m_subPartCopy = copy16;
        m_subPartSet = bcast16;
        break;
    case 16:  // 16x16 CU
        m_partCopy = copy16;
        m_partSet = bcast16;
        m_subPartCopy = copy4;
        m_subPartSet = bcast4;
        break;
    case 4:   // 8x8 CU
        m_partCopy = copy4;
        m_partSet = bcast4;
        m_subPartCopy = NULL;
        m_subPartSet = NULL;
        break;
    default:
        X265_CHECK(0, "unexpected CU partition count\n");
        break;
    }

    /* Each CU's data is layed out sequentially within the charMemBlock */
    uint8_t *charBuf = dataPool.charMemBlock + (m_numPartitions * BytesPerPartition) * instance;//在dataPool中获取当前CTU标号的首地址

    m_qp        = (int8_t*)charBuf; charBuf += m_numPartitions;//以下获取相应地址
    m_log2CUSize         = charBuf; charBuf += m_numPartitions;
    m_lumaIntraDir       = charBuf; charBuf += m_numPartitions;
    m_tqBypass           = charBuf; charBuf += m_numPartitions;
    m_refIdx[0] = (int8_t*)charBuf; charBuf += m_numPartitions;
    m_refIdx[1] = (int8_t*)charBuf; charBuf += m_numPartitions;
    m_cuDepth            = charBuf; charBuf += m_numPartitions;
    m_predMode           = charBuf; charBuf += m_numPartitions; /* the order up to here is important in initCTU() and initSubCU() */
    m_partSize           = charBuf; charBuf += m_numPartitions;
    m_mergeFlag          = charBuf; charBuf += m_numPartitions;
    m_interDir           = charBuf; charBuf += m_numPartitions;
    m_mvpIdx[0]          = charBuf; charBuf += m_numPartitions;
    m_mvpIdx[1]          = charBuf; charBuf += m_numPartitions;
    m_tuDepth            = charBuf; charBuf += m_numPartitions;
    m_transformSkip[0]   = charBuf; charBuf += m_numPartitions;
    m_transformSkip[1]   = charBuf; charBuf += m_numPartitions;
    m_transformSkip[2]   = charBuf; charBuf += m_numPartitions;
    m_cbf[0]             = charBuf; charBuf += m_numPartitions;
    m_cbf[1]             = charBuf; charBuf += m_numPartitions;
    m_cbf[2]             = charBuf; charBuf += m_numPartitions;
    m_chromaIntraDir     = charBuf; charBuf += m_numPartitions;

    X265_CHECK(charBuf == dataPool.charMemBlock + (m_numPartitions * BytesPerPartition) * (instance + 1), "CU data layout is broken\n");

    m_mv[0]  = dataPool.mvMemBlock + (instance * 4) * m_numPartitions;//获取MV等相应地址
    m_mv[1]  = m_mv[0] +  m_numPartitions;
    m_mvd[0] = m_mv[1] +  m_numPartitions;
    m_mvd[1] = m_mvd[0] + m_numPartitions;

    uint32_t cuSize = g_maxCUSize >> depth;
    uint32_t sizeL = cuSize * cuSize;
    uint32_t sizeC = sizeL >> (m_hChromaShift + m_vChromaShift);
    m_trCoeff[0] = dataPool.trCoeffMemBlock + instance * (sizeL + sizeC * 2);//获取残差系数相应地址
    m_trCoeff[1] = m_trCoeff[0] + sizeL;
    m_trCoeff[2] = m_trCoeff[0] + sizeL + sizeC;
}
/** 函数功能             :初始化CTU
/*  调用范围             :只在processRowEncoder函数中被调用
* \参数 frame            :当前编码帧
* \参数 cuAddr           :CTU在帧中的编号
* \参数 qp               :通过ratecontrolstart估计的QP值
* \返回                  :null* */
void CUData::initCTU(const Frame& frame, uint32_t cuAddr, int qp)
{
    m_encData       = frame.m_encData;//获取当前帧编码数据
    m_slice         = m_encData->m_slice;
    m_cuAddr        = cuAddr;
    m_cuPelX        = (cuAddr % m_slice->m_sps->numCuInWidth) << g_maxLog2CUSize;
    m_cuPelY        = (cuAddr / m_slice->m_sps->numCuInWidth) << g_maxLog2CUSize;
    m_absIdxInCTU   = 0;
    m_numPartitions = NUM_4x4_PARTITIONS;

    /* sequential memsets */
    m_partSet((uint8_t*)m_qp, (uint8_t)qp);
    m_partSet(m_log2CUSize,   (uint8_t)g_maxLog2CUSize);
    m_partSet(m_lumaIntraDir, (uint8_t)DC_IDX);
    m_partSet(m_tqBypass,     (uint8_t)frame.m_encData->m_param->bLossless);
    if (m_slice->m_sliceType != I_SLICE)
    {
        m_partSet((uint8_t*)m_refIdx[0], (uint8_t)REF_NOT_VALID);
        m_partSet((uint8_t*)m_refIdx[1], (uint8_t)REF_NOT_VALID);
    }

    X265_CHECK(!(frame.m_encData->m_param->bLossless && !m_slice->m_pps->bTransquantBypassEnabled), "lossless enabled without TQbypass in PPS\n");

    /* initialize the remaining CU data in one memset */
    memset(m_cuDepth, 0, (BytesPerPartition - 6) * m_numPartitions);

    uint32_t widthInCU = m_slice->m_sps->numCuInWidth;
    m_cuLeft = (m_cuAddr % widthInCU) ? m_encData->getPicCTU(m_cuAddr - 1) : NULL; //获取左边CTU
    m_cuAbove = (m_cuAddr / widthInCU) ? m_encData->getPicCTU(m_cuAddr - widthInCU) : NULL;//获取上边CTU
    m_cuAboveLeft = (m_cuLeft && m_cuAbove) ? m_encData->getPicCTU(m_cuAddr - widthInCU - 1) : NULL;//获取左上CTU
    m_cuAboveRight = (m_cuAbove && ((m_cuAddr % widthInCU) < (widthInCU - 1))) ? m_encData->getPicCTU(m_cuAddr - widthInCU + 1) : NULL;//获取右上CTU
}

// initialize Sub partition
/** 函数功能       : 根据cuGeom初始化当前子块的信息
* \参数 ctu        : 上层大块
* \参数 cuGeom     : 当前子块对应的一些几何(深度,位置等信息)信息
* \参数 qp         : 当前的qp信息
*   返回值         : null**/
void CUData::initSubCU(const CUData& ctu, const CUGeom& cuGeom, int qp)
{
    m_absIdxInCTU   = cuGeom.absPartIdx;//获取子CU左上角在CTU4x4块中的zigzag标号
    m_encData       = ctu.m_encData;    //获取编码数据
    m_slice         = ctu.m_slice;      //获取slice
    m_cuAddr        = ctu.m_cuAddr;     //获取CTU在帧中的编号
    m_cuPelX        = ctu.m_cuPelX + g_zscanToPelX[cuGeom.absPartIdx];//获取子CU左上角像素点在图像中的横向偏移像素个数
    m_cuPelY        = ctu.m_cuPelY + g_zscanToPelY[cuGeom.absPartIdx];//获取子CU左上角像素点在图像中的纵向偏移像素个数
    m_cuLeft        = ctu.m_cuLeft; //获取左边CTU
    m_cuAbove       = ctu.m_cuAbove;//获取上边CTU
    m_cuAboveLeft   = ctu.m_cuAboveLeft;//获取左上CTU
    m_cuAboveRight  = ctu.m_cuAboveRight;//获取右上CTU
    X265_CHECK(m_numPartitions == cuGeom.numPartitions, "initSubCU() size mismatch\n");

    m_partSet((uint8_t*)m_qp, (uint8_t)qp);//获取qp

    m_partSet(m_log2CUSize,   (uint8_t)cuGeom.log2CUSize);//获取当前块的块大小
    m_partSet(m_lumaIntraDir, (uint8_t)DC_IDX);//初始化预测方向为DC
    m_partSet(m_tqBypass,     (uint8_t)m_encData->m_param->bLossless);//初始化跳过模式
    m_partSet((uint8_t*)m_refIdx[0], (uint8_t)REF_NOT_VALID);//初始化最优参考帧标号
    m_partSet((uint8_t*)m_refIdx[1], (uint8_t)REF_NOT_VALID);//初始化最优参考帧标号
    m_partSet(m_cuDepth,      (uint8_t)cuGeom.depth);//初始化当前块的深度

    /* initialize the remaining CU data in one memset */
    memset(m_predMode, 0, (BytesPerPartition - 7) * m_numPartitions);//剩下的所有相关信息全部初始化为0
}

/* Copy the results of a sub-part (split) CU to the parent CU */
/** 函数功能       : 将子块决策最优结果copy到父块对应位置中
* \参数 subCU      : 当前子块
* \参数 childGeom  : 当前子块的几何信息
* \参数 subPartIdx : 当前子块的标号
*   返回值         : null**/
void CUData::copyPartFrom(const CUData& subCU, const CUGeom& childGeom, uint32_t subPartIdx)
{
    X265_CHECK(subPartIdx < 4, "part unit should be less than 4\n");

    uint32_t offset = childGeom.numPartitions * subPartIdx;//获取当前子块相对于父块的偏移4x4块个数

    m_subPartCopy((uint8_t*)m_qp + offset, (uint8_t*)subCU.m_qp);
    m_subPartCopy(m_log2CUSize + offset, subCU.m_log2CUSize);
    m_subPartCopy(m_lumaIntraDir + offset, subCU.m_lumaIntraDir);
    m_subPartCopy(m_tqBypass + offset, subCU.m_tqBypass);
    m_subPartCopy((uint8_t*)m_refIdx[0] + offset, (uint8_t*)subCU.m_refIdx[0]);
    m_subPartCopy((uint8_t*)m_refIdx[1] + offset, (uint8_t*)subCU.m_refIdx[1]);
    m_subPartCopy(m_cuDepth + offset, subCU.m_cuDepth);
    m_subPartCopy(m_predMode + offset, subCU.m_predMode);
    m_subPartCopy(m_partSize + offset, subCU.m_partSize);
    m_subPartCopy(m_mergeFlag + offset, subCU.m_mergeFlag);
    m_subPartCopy(m_interDir + offset, subCU.m_interDir);
    m_subPartCopy(m_mvpIdx[0] + offset, subCU.m_mvpIdx[0]);
    m_subPartCopy(m_mvpIdx[1] + offset, subCU.m_mvpIdx[1]);
    m_subPartCopy(m_tuDepth + offset, subCU.m_tuDepth);
    m_subPartCopy(m_transformSkip[0] + offset, subCU.m_transformSkip[0]);
    m_subPartCopy(m_transformSkip[1] + offset, subCU.m_transformSkip[1]);
    m_subPartCopy(m_transformSkip[2] + offset, subCU.m_transformSkip[2]);
    m_subPartCopy(m_cbf[0] + offset, subCU.m_cbf[0]);
    m_subPartCopy(m_cbf[1] + offset, subCU.m_cbf[1]);
    m_subPartCopy(m_cbf[2] + offset, subCU.m_cbf[2]);
    m_subPartCopy(m_chromaIntraDir + offset, subCU.m_chromaIntraDir);

    memcpy(m_mv[0] + offset, subCU.m_mv[0], childGeom.numPartitions * sizeof(MV));
    memcpy(m_mv[1] + offset, subCU.m_mv[1], childGeom.numPartitions * sizeof(MV));
    memcpy(m_mvd[0] + offset, subCU.m_mvd[0], childGeom.numPartitions * sizeof(MV));
    memcpy(m_mvd[1] + offset, subCU.m_mvd[1], childGeom.numPartitions * sizeof(MV));

    uint32_t tmp = 1 << ((g_maxLog2CUSize - childGeom.depth) * 2);
    uint32_t tmp2 = subPartIdx * tmp;
    memcpy(m_trCoeff[0] + tmp2, subCU.m_trCoeff[0], sizeof(coeff_t) * tmp);

    uint32_t tmpC = tmp >> (m_hChromaShift + m_vChromaShift);
    uint32_t tmpC2 = tmp2 >> (m_hChromaShift + m_vChromaShift);
    memcpy(m_trCoeff[1] + tmpC2, subCU.m_trCoeff[1], sizeof(coeff_t) * tmpC);
    memcpy(m_trCoeff[2] + tmpC2, subCU.m_trCoeff[2], sizeof(coeff_t) * tmpC);
}

/* If a sub-CU part is not present (off the edge of the picture) its depth and
 * log2size should still be configured */
/** 函数功能       : 当前子块全部在图像外,设置当前子块的depth和块大小值
* \参数 childGeom  : 当前子块的几何信息
* \参数 subPartIdx : 当前子块的标号
*   返回值         : null**/
void CUData::setEmptyPart(const CUGeom& childGeom, uint32_t subPartIdx)
{
    uint32_t offset = childGeom.numPartitions * subPartIdx;     //在当前子块与当前父块之间的偏移4x4块个数
    m_subPartSet(m_cuDepth + offset, (uint8_t)childGeom.depth); //赋值当前子块的depth
    m_subPartSet(m_log2CUSize + offset, (uint8_t)childGeom.log2CUSize);//赋值当前子块的cu大小
}

/* Copy all CU data from one instance to the next, except set lossless flag
 * This will only get used when --cu-lossless is enabled but --lossless is not. */
void CUData::initLosslessCU(const CUData& cu, const CUGeom& cuGeom)
{
    /* Start by making an exact copy */
    m_encData      = cu.m_encData;
    m_slice        = cu.m_slice;
    m_cuAddr       = cu.m_cuAddr;
    m_cuPelX       = cu.m_cuPelX;
    m_cuPelY       = cu.m_cuPelY;
    m_cuLeft       = cu.m_cuLeft;
    m_cuAbove      = cu.m_cuAbove;
    m_cuAboveLeft  = cu.m_cuAboveLeft;
    m_cuAboveRight = cu.m_cuAboveRight;
    m_absIdxInCTU  = cuGeom.absPartIdx;
    m_numPartitions = cuGeom.numPartitions;
    memcpy(m_qp, cu.m_qp, BytesPerPartition * m_numPartitions);
    memcpy(m_mv[0],  cu.m_mv[0],  m_numPartitions * sizeof(MV));
    memcpy(m_mv[1],  cu.m_mv[1],  m_numPartitions * sizeof(MV));
    memcpy(m_mvd[0], cu.m_mvd[0], m_numPartitions * sizeof(MV));
    memcpy(m_mvd[1], cu.m_mvd[1], m_numPartitions * sizeof(MV));

    /* force TQBypass to true */
    m_partSet(m_tqBypass, true);

    /* clear residual coding flags */
    m_partSet(m_predMode, cu.m_predMode[0] & (MODE_INTRA | MODE_INTER));
    m_partSet(m_tuDepth, 0);
    m_partSet(m_transformSkip[0], 0);
    m_partSet(m_transformSkip[1], 0);
    m_partSet(m_transformSkip[2], 0);
    m_partSet(m_cbf[0], 0);
    m_partSet(m_cbf[1], 0);
    m_partSet(m_cbf[2], 0);
}

/* Copy completed predicted CU to CTU in picture */
/** 函数功能       : 将当前cu决策信息赋值到CTU对应位置中
* \参数 depth      : 当前的划分深度
*   返回值         : null**/
void CUData::copyToPic(uint32_t depth) const
{
    CUData& ctu = *m_encData->getPicCTU(m_cuAddr);//获取当前CU所在的CTU
    //将当前cu决策信息赋值到CTU对应位置中
    m_partCopy((uint8_t*)ctu.m_qp + m_absIdxInCTU, (uint8_t*)m_qp);
    m_partCopy(ctu.m_log2CUSize + m_absIdxInCTU, m_log2CUSize);
    m_partCopy(ctu.m_lumaIntraDir + m_absIdxInCTU, m_lumaIntraDir);
    m_partCopy(ctu.m_tqBypass + m_absIdxInCTU, m_tqBypass);
    m_partCopy((uint8_t*)ctu.m_refIdx[0] + m_absIdxInCTU, (uint8_t*)m_refIdx[0]);
    m_partCopy((uint8_t*)ctu.m_refIdx[1] + m_absIdxInCTU, (uint8_t*)m_refIdx[1]);
    m_partCopy(ctu.m_cuDepth + m_absIdxInCTU, m_cuDepth);
    m_partCopy(ctu.m_predMode + m_absIdxInCTU, m_predMode);
    m_partCopy(ctu.m_partSize + m_absIdxInCTU, m_partSize);
    m_partCopy(ctu.m_mergeFlag + m_absIdxInCTU, m_mergeFlag);
    m_partCopy(ctu.m_interDir + m_absIdxInCTU, m_interDir);
    m_partCopy(ctu.m_mvpIdx[0] + m_absIdxInCTU, m_mvpIdx[0]);
    m_partCopy(ctu.m_mvpIdx[1] + m_absIdxInCTU, m_mvpIdx[1]);
    m_partCopy(ctu.m_tuDepth + m_absIdxInCTU, m_tuDepth);
    m_partCopy(ctu.m_transformSkip[0] + m_absIdxInCTU, m_transformSkip[0]);
    m_partCopy(ctu.m_transformSkip[1] + m_absIdxInCTU, m_transformSkip[1]);
    m_partCopy(ctu.m_transformSkip[2] + m_absIdxInCTU, m_transformSkip[2]);
    m_partCopy(ctu.m_cbf[0] + m_absIdxInCTU, m_cbf[0]);
    m_partCopy(ctu.m_cbf[1] + m_absIdxInCTU, m_cbf[1]);
    m_partCopy(ctu.m_cbf[2] + m_absIdxInCTU, m_cbf[2]);
    m_partCopy(ctu.m_chromaIntraDir + m_absIdxInCTU, m_chromaIntraDir);

    memcpy(ctu.m_mv[0] + m_absIdxInCTU,  m_mv[0],  m_numPartitions * sizeof(MV));
    memcpy(ctu.m_mv[1] + m_absIdxInCTU,  m_mv[1],  m_numPartitions * sizeof(MV));
    memcpy(ctu.m_mvd[0] + m_absIdxInCTU, m_mvd[0], m_numPartitions * sizeof(MV));
    memcpy(ctu.m_mvd[1] + m_absIdxInCTU, m_mvd[1], m_numPartitions * sizeof(MV));

    uint32_t tmpY = 1 << ((g_maxLog2CUSize - depth) * 2);
    uint32_t tmpY2 = m_absIdxInCTU << (LOG2_UNIT_SIZE * 2);
    memcpy(ctu.m_trCoeff[0] + tmpY2, m_trCoeff[0], sizeof(coeff_t) * tmpY);

    uint32_t tmpC = tmpY >> (m_hChromaShift + m_vChromaShift);
    uint32_t tmpC2 = tmpY2 >> (m_hChromaShift + m_vChromaShift);
    memcpy(ctu.m_trCoeff[1] + tmpC2, m_trCoeff[1], sizeof(coeff_t) * tmpC);
    memcpy(ctu.m_trCoeff[2] + tmpC2, m_trCoeff[2], sizeof(coeff_t) * tmpC);
}

/* The reverse of copyToPic, called only by encodeResidue */
void CUData::copyFromPic(const CUData& ctu, const CUGeom& cuGeom)
{
    m_encData       = ctu.m_encData;
    m_slice         = ctu.m_slice;
    m_cuAddr        = ctu.m_cuAddr;
    m_cuPelX        = ctu.m_cuPelX + g_zscanToPelX[cuGeom.absPartIdx];
    m_cuPelY        = ctu.m_cuPelY + g_zscanToPelY[cuGeom.absPartIdx];
    m_absIdxInCTU   = cuGeom.absPartIdx;
    m_numPartitions = cuGeom.numPartitions;

    /* copy out all prediction info for this part */
    m_partCopy((uint8_t*)m_qp, (uint8_t*)ctu.m_qp + m_absIdxInCTU);
    m_partCopy(m_log2CUSize,   ctu.m_log2CUSize + m_absIdxInCTU);
    m_partCopy(m_lumaIntraDir, ctu.m_lumaIntraDir + m_absIdxInCTU);
    m_partCopy(m_tqBypass,     ctu.m_tqBypass + m_absIdxInCTU);
    m_partCopy((uint8_t*)m_refIdx[0], (uint8_t*)ctu.m_refIdx[0] + m_absIdxInCTU);
    m_partCopy((uint8_t*)m_refIdx[1], (uint8_t*)ctu.m_refIdx[1] + m_absIdxInCTU);
    m_partCopy(m_cuDepth,      ctu.m_cuDepth + m_absIdxInCTU);
    m_partSet(m_predMode, ctu.m_predMode[m_absIdxInCTU] & (MODE_INTRA | MODE_INTER)); /* clear skip flag */
    m_partCopy(m_partSize,     ctu.m_partSize + m_absIdxInCTU);
    m_partCopy(m_mergeFlag,    ctu.m_mergeFlag + m_absIdxInCTU);
    m_partCopy(m_interDir,     ctu.m_interDir + m_absIdxInCTU);
    m_partCopy(m_mvpIdx[0],    ctu.m_mvpIdx[0] + m_absIdxInCTU);
    m_partCopy(m_mvpIdx[1],    ctu.m_mvpIdx[1] + m_absIdxInCTU);
    m_partCopy(m_chromaIntraDir, ctu.m_chromaIntraDir + m_absIdxInCTU);

    memcpy(m_mv[0],  ctu.m_mv[0] + m_absIdxInCTU,  m_numPartitions * sizeof(MV));
    memcpy(m_mv[1],  ctu.m_mv[1] + m_absIdxInCTU,  m_numPartitions * sizeof(MV));
    memcpy(m_mvd[0], ctu.m_mvd[0] + m_absIdxInCTU, m_numPartitions * sizeof(MV));
    memcpy(m_mvd[1], ctu.m_mvd[1] + m_absIdxInCTU, m_numPartitions * sizeof(MV));

    /* clear residual coding flags */
    m_partSet(m_tuDepth, 0);
    m_partSet(m_transformSkip[0], 0);
    m_partSet(m_transformSkip[1], 0);
    m_partSet(m_transformSkip[2], 0);
    m_partSet(m_cbf[0], 0);
    m_partSet(m_cbf[1], 0);
    m_partSet(m_cbf[2], 0);
}

/* Only called by encodeResidue, these fields can be modified during inter/intra coding */
void CUData::updatePic(uint32_t depth) const
{
    CUData& ctu = *m_encData->getPicCTU(m_cuAddr);

    m_partCopy((uint8_t*)ctu.m_qp + m_absIdxInCTU, (uint8_t*)m_qp);
    m_partCopy(ctu.m_transformSkip[0] + m_absIdxInCTU, m_transformSkip[0]);
    m_partCopy(ctu.m_transformSkip[1] + m_absIdxInCTU, m_transformSkip[1]);
    m_partCopy(ctu.m_transformSkip[2] + m_absIdxInCTU, m_transformSkip[2]);
    m_partCopy(ctu.m_predMode + m_absIdxInCTU, m_predMode);
    m_partCopy(ctu.m_tuDepth + m_absIdxInCTU, m_tuDepth);
    m_partCopy(ctu.m_cbf[0] + m_absIdxInCTU, m_cbf[0]);
    m_partCopy(ctu.m_cbf[1] + m_absIdxInCTU, m_cbf[1]);
    m_partCopy(ctu.m_cbf[2] + m_absIdxInCTU, m_cbf[2]);
    m_partCopy(ctu.m_chromaIntraDir + m_absIdxInCTU, m_chromaIntraDir);

    uint32_t tmpY = 1 << ((g_maxLog2CUSize - depth) * 2);
    uint32_t tmpY2 = m_absIdxInCTU << (LOG2_UNIT_SIZE * 2);
    memcpy(ctu.m_trCoeff[0] + tmpY2, m_trCoeff[0], sizeof(coeff_t) * tmpY);
    tmpY  >>= m_hChromaShift + m_vChromaShift;
    tmpY2 >>= m_hChromaShift + m_vChromaShift;
    memcpy(ctu.m_trCoeff[1] + tmpY2, m_trCoeff[1], sizeof(coeff_t) * tmpY);
    memcpy(ctu.m_trCoeff[2] + tmpY2, m_trCoeff[2], sizeof(coeff_t) * tmpY);
}
/** 函数功能             : 获取参考点的CTU或者CU位置,获取参考点在获取CTU或者CU内部的zigzag标号位置
* \参数 lPartUnitIdx     : 用于存储参考像素点在返回CU/CTU 内部的zigzag标号 1.参考像素点不在当前CTU:返回参考像素点所在CTU的zigzag标号2.参考像素点在当前CTU不在当前CU:返回参考像素点在当前CTU的zigzag标号  3.参考像素点在当前CU:回参考像素点在当前CU的zigzag标号
* \参数 curPartUnitIdx   : 当前PU左边行某一4x4块在CTU中的zigzag标号(PU内部的左边)
*   返回值               : 1.参考像素点不在当前CTU:返回参考的所在的CTU 2.参考像素点在当前CTU不在当前CU:返回当前CTU  3.参考像素点在当前CU:返回当前CU
**/
const CUData* CUData::getPULeft(uint32_t& lPartUnitIdx, uint32_t curPartUnitIdx) const
{
    uint32_t absPartIdx = g_zscanToRaster[curPartUnitIdx];//获取当前光栅扫描位置

    if (!isZeroCol(absPartIdx, s_numPartInCUSize))//如果不是CTU列中的第一列  说明参考点在CTU内部
    {
        uint32_t absZorderCUIdx   = g_zscanToRaster[m_absIdxInCTU];//将当前CU在CTU位置的zigzag扫描改为光栅扫描
        lPartUnitIdx = g_rasterToZscan[absPartIdx - 1];//获取当前PU左边参考像素点的zigzag扫描位置
        if (isEqualCol(absPartIdx, absZorderCUIdx, s_numPartInCUSize))//当前PU与CU左上角像素点在同一列 说明参考点不在当前CU
            return m_encData->getPicCTU(m_cuAddr);//返回当前CTU
        else
        {
            lPartUnitIdx -= m_absIdxInCTU;//获取在CU内部的参考像素点的zigzag标号
            return this;//返回当前CU
        }
    }

    lPartUnitIdx = g_rasterToZscan[absPartIdx + s_numPartInCUSize - 1];//获取在左边CTU的内部zigzag编号
    return m_cuLeft;//返回左边的CTU
}
/** 函数功能             : 获取参考点的CTU或者CU位置,获取参考点在获取CTU或者CU内部的zigzag标号位置
* \参数 alPartUnitIdx    : 用于存储参考像素点在返回CU/CTU 内部的zigzag标号 1.参考像素点不在当前CTU:返回参考像素点所在CTU的zigzag标号2.参考像素点在当前CTU不在当前CU:返回参考像素点在当前CTU的zigzag标号  3.参考像素点在当前CU:回参考像素点在当前CU的zigzag标号
* \参数 curPartUnitIdx   : 当前PU上边行某一4x4块在CTU中的zigzag标号
*   返回值               : 1.参考像素点不在当前CTU:返回参考的所在的CTU 2.参考像素点在当前CTU不在当前CU:返回当前CTU  3.参考像素点在当前CU:返回当前CU
**/
const CUData* CUData::getPUAbove(uint32_t& aPartUnitIdx, uint32_t curPartUnitIdx) const
{
    uint32_t absPartIdx = g_zscanToRaster[curPartUnitIdx];//获取当前光栅扫描位置

    if (!isZeroRow(absPartIdx, s_numPartInCUSize))//如果当前不是CTU第一行 (参考像素点在CTU内部)
    {
        uint32_t absZorderCUIdx = g_zscanToRaster[m_absIdxInCTU];//将当前CU在CTU位置的zigzag扫描改为光栅扫描
        aPartUnitIdx = g_rasterToZscan[absPartIdx - s_numPartInCUSize];//获取当前PU上边参考像素点的zigzag扫描位置
        if (isEqualRow(absPartIdx, absZorderCUIdx, s_numPartInCUSize))//如果PU的第一行跟CU块的第一行重合 (说明参考像素点在另一个CU)
            return m_encData->getPicCTU(m_cuAddr);//返回当前CTU
        else
            aPartUnitIdx -= m_absIdxInCTU;//获取在CU内部的参考像素点的zigzag标号
        return this;//返回当前CU
    }
    //当前是CTU的第一行 上边行参考像素点在另一个CTU上
    aPartUnitIdx = g_rasterToZscan[absPartIdx + NUM_4x4_PARTITIONS - s_numPartInCUSize];//获取在上边CTU的内部zigzag编号
    return m_cuAbove;//返回上边的CTU
}
/** 函数功能             : 获取参考点的CTU或者CU位置,获取参考点在获取CTU或者CU内部的zigzag标号位置
* \参数 alPartUnitIdx    : 用于存储参考像素点在返回CU/CTU 内部的zigzag标号 1.参考像素点不在当前CTU:返回参考像素点所在CTU的zigzag标号2.参考像素点在当前CTU不在当前CU:返回参考像素点在当前CTU的zigzag标号  3.参考像素点在当前CU:回参考像素点在当前CU的zigzag标号
* \参数 curPartUnitIdx   : 当前PU左上角像素点在CTU中的zigzag标号
*   返回值               : 1.参考像素点不在当前CTU:返回参考的所在的CTU2.参考像素点在当前CTU不在当前CU:返回当前CTU  3.参考像素点在当前CU:返回当前CU
**/
const CUData* CUData::getPUAboveLeft(uint32_t& alPartUnitIdx, uint32_t curPartUnitIdx) const
{
    uint32_t absPartIdx = g_zscanToRaster[curPartUnitIdx];//获取当前光栅扫描位置

    //以下if 保证左上角参考像素点在本CTU中
    if (!isZeroCol(absPartIdx, s_numPartInCUSize))//如果当前不是CTU第一列
    {
        if (!isZeroRow(absPartIdx, s_numPartInCUSize))//如果当前不是CTU第一行
        {
            uint32_t absZorderCUIdx  = g_zscanToRaster[m_absIdxInCTU];//将当前CU在CTU位置的zigzag扫描改为光栅扫描
            alPartUnitIdx = g_rasterToZscan[absPartIdx - s_numPartInCUSize - 1];//获取当前PU左上角参考像素点的zigzag扫描位置
            /*以intra NxN为例
            ----------------
            |  PU0  |   PU1|
            ----------------
            |  PU2  |   PU3|
            ----------------
            isEqualRowOrCol指的是PU0 和 PU1  PU2  因为其左上角参考像素点在另一个CU中
            **/
            if (isEqualRowOrCol(absPartIdx, absZorderCUIdx, s_numPartInCUSize))//如果当前PU跟CU是同一行或者同一列
                return m_encData->getPicCTU(m_cuAddr);//返回当前所在的CTU
            else
            {
                alPartUnitIdx -= m_absIdxInCTU;//获取在CU内部的参考像素点的zigzag标号
                return this;//返回当前CU
            }
        }
        //不在CTU第一列 但在CTU第一行
        alPartUnitIdx = g_rasterToZscan[absPartIdx + NUM_4x4_PARTITIONS - s_numPartInCUSize - 1];//获取参考像素点在上边CTU的内部zigzag标号
        return m_cuAbove;//返回上边的CTU
    }

    if (!isZeroRow(absPartIdx, s_numPartInCUSize))//是CTU第一列  不是CTU第一行
    {
        alPartUnitIdx = g_rasterToZscan[absPartIdx - 1];//获取参考像素点在左边CTU的内部zigzag标号
        return m_cuLeft;//返回左边的CTU
    }
    //当前PU左上角像素点与CTU左上角像素点是同一个位置
    alPartUnitIdx = g_rasterToZscan[NUM_4x4_PARTITIONS - 1];//获取参考像素点在左上边CTU的内部zigzag标号
    return m_cuAboveLeft;//返回左上边的CTU
}

const CUData* CUData::getPUAboveRight(uint32_t& arPartUnitIdx, uint32_t curPartUnitIdx) const
{
    if ((m_encData->getPicCTU(m_cuAddr)->m_cuPelX + g_zscanToPelX[curPartUnitIdx] + UNIT_SIZE) >= m_slice->m_sps->picWidthInLumaSamples)
        return NULL;

    uint32_t absPartIdxRT = g_zscanToRaster[curPartUnitIdx];

    if (lessThanCol(absPartIdxRT, s_numPartInCUSize - 1, s_numPartInCUSize))
    {
        if (!isZeroRow(absPartIdxRT, s_numPartInCUSize))
        {
            if (curPartUnitIdx > g_rasterToZscan[absPartIdxRT - s_numPartInCUSize + 1])
            {
                uint32_t absZorderCUIdx = g_zscanToRaster[m_absIdxInCTU] + (1 << (m_log2CUSize[0] - LOG2_UNIT_SIZE)) - 1;
                arPartUnitIdx = g_rasterToZscan[absPartIdxRT - s_numPartInCUSize + 1];
                if (isEqualRowOrCol(absPartIdxRT, absZorderCUIdx, s_numPartInCUSize))
                    return m_encData->getPicCTU(m_cuAddr);
                else
                {
                    arPartUnitIdx -= m_absIdxInCTU;
                    return this;
                }
            }
            return NULL;
        }
        arPartUnitIdx = g_rasterToZscan[absPartIdxRT + NUM_4x4_PARTITIONS - s_numPartInCUSize + 1];
        return m_cuAbove;
    }

    if (!isZeroRow(absPartIdxRT, s_numPartInCUSize))
        return NULL;

    arPartUnitIdx = g_rasterToZscan[NUM_4x4_PARTITIONS - s_numPartInCUSize];
    return m_cuAboveRight;
}

const CUData* CUData::getPUBelowLeft(uint32_t& blPartUnitIdx, uint32_t curPartUnitIdx) const
{
    if ((m_encData->getPicCTU(m_cuAddr)->m_cuPelY + g_zscanToPelY[curPartUnitIdx] + UNIT_SIZE) >= m_slice->m_sps->picHeightInLumaSamples)
        return NULL;

    uint32_t absPartIdxLB = g_zscanToRaster[curPartUnitIdx];

    if (lessThanRow(absPartIdxLB, s_numPartInCUSize - 1, s_numPartInCUSize))
    {
        if (!isZeroCol(absPartIdxLB, s_numPartInCUSize))
        {
            if (curPartUnitIdx > g_rasterToZscan[absPartIdxLB + s_numPartInCUSize - 1])
            {
                uint32_t absZorderCUIdxLB = g_zscanToRaster[m_absIdxInCTU] + ((1 << (m_log2CUSize[0] - LOG2_UNIT_SIZE)) - 1) * s_numPartInCUSize;
                blPartUnitIdx = g_rasterToZscan[absPartIdxLB + s_numPartInCUSize - 1];
                if (isEqualRowOrCol(absPartIdxLB, absZorderCUIdxLB, s_numPartInCUSize))
                    return m_encData->getPicCTU(m_cuAddr);
                else
                {
                    blPartUnitIdx -= m_absIdxInCTU;
                    return this;
                }
            }
            return NULL;
        }
        blPartUnitIdx = g_rasterToZscan[absPartIdxLB + s_numPartInCUSize * 2 - 1];
        return m_cuLeft;
    }

    return NULL;
}
/** 函数功能             : 获取参考点的CTU或者CU位置,获取参考点在获取CTU或者CU内部的zigzag标号位置
* \参数 blPartUnitIdx    : 用于存储参考像素点在返回CU/CTU 内部的zigzag标号 1.参考像素点不在当前CTU:返回参考像素点所在CTU的zigzag标号2.参考像素点在当前CTU不在当前CU:返回参考像素点在当前CTU的zigzag标号  3.参考像素点在当前CU:回参考像素点在当前CU的zigzag标号
* \参数 curPartUnitIdx   : 当前PU右上角像素点在CTU中的zigzag标号
* \参数 partUnitOffset   : 当前4x4块距离PU左下点位置的偏移值
*   返回值               : 1.参考像素点不在当前CTU:返回参考的所在的CTU 2.参考像素点在当前CTU不在当前CU:返回当前CTU  3.参考像素点在当前CU:返回当前CU
**/
const CUData* CUData::getPUBelowLeftAdi(uint32_t& blPartUnitIdx,  uint32_t curPartUnitIdx, uint32_t partUnitOffset) const
{
    if ((m_encData->getPicCTU(m_cuAddr)->m_cuPelY + g_zscanToPelY[curPartUnitIdx] + (partUnitOffset << LOG2_UNIT_SIZE)) >= m_slice->m_sps->picHeightInLumaSamples)//判断是否越过图像边界
        return NULL;

    uint32_t absPartIdxLB = g_zscanToRaster[curPartUnitIdx];//获取当前光栅扫描位置

    if (lessThanRow(absPartIdxLB, s_numPartInCUSize - partUnitOffset, s_numPartInCUSize))//如果被参考块没有超过当前CTU行的边界 (在同一个CTU中)
    {
        if (!isZeroCol(absPartIdxLB, s_numPartInCUSize))//如果当前不是CTU第一列
        {
            if (curPartUnitIdx > g_rasterToZscan[absPartIdxLB + partUnitOffset * s_numPartInCUSize - 1])//必须保证左下块已经编码完毕 即当前的zigzag号要大于参考块的zigzag号(因为当前在同一个CTU下)
            {
                uint32_t absZorderCUIdxLB = g_zscanToRaster[m_absIdxInCTU] + ((1 << (m_log2CUSize[0] - LOG2_UNIT_SIZE)) - 1) * s_numPartInCUSize;//将当前CU左下角在CTU位置的zigzag扫描改为光栅扫描
                blPartUnitIdx = g_rasterToZscan[absPartIdxLB + partUnitOffset * s_numPartInCUSize - 1];//获取左下位置
                if (isEqualRowOrCol(absPartIdxLB, absZorderCUIdxLB, s_numPartInCUSize))//如果当前PU左下角与CU处于同一行 或者同一列
                    return m_encData->getPicCTU(m_cuAddr);//返回当前CTU
                else
                {
                    //同一CU下不可能获取左下可用块
                    blPartUnitIdx -= m_absIdxInCTU;//获取在CU内部的参考像素点的zigzag标号
                    return this;//返回当前CU
                }
            }
            return NULL;//左下不可用 返回null
        }
        blPartUnitIdx = g_rasterToZscan[absPartIdxLB + (1 + partUnitOffset) * s_numPartInCUSize - 1];//获取参考像素点在左边CTU的内部zigzag标号
        return m_cuLeft;//返回左边CTU
    }

    return NULL;//返回null
}
/** 函数功能             : 获取参考点的CTU或者CU位置,获取参考点在获取CTU或者CU内部的zigzag标号位置
* \参数 alPartUnitIdx    : 用于存储参考像素点在返回CU/CTU 内部的zigzag标号 1.参考像素点不在当前CTU:返回参考像素点所在CTU的zigzag标号2.参考像素点在当前CTU不在当前CU:返回参考像素点在当前CTU的zigzag标号  3.参考像素点在当前CU:回参考像素点在当前CU的zigzag标号
* \参数 curPartUnitIdx   : 当前PU右上角像素点在CTU中的zigzag标号
* \参数 partUnitOffset   : 当前4x4块距离PU右上点位置的偏移值
*   返回值               : 1.参考像素点不在当前CTU:返回参考的所在的CTU 2.参考像素点在当前CTU不在当前CU:返回当前CTU  3.参考像素点在当前CU:返回当前CU
**/
const CUData* CUData::getPUAboveRightAdi(uint32_t& arPartUnitIdx, uint32_t curPartUnitIdx, uint32_t partUnitOffset) const
{
    if ((m_encData->getPicCTU(m_cuAddr)->m_cuPelX + g_zscanToPelX[curPartUnitIdx] + (partUnitOffset << LOG2_UNIT_SIZE)) >= m_slice->m_sps->picWidthInLumaSamples)//判断是否越过图像边界
        return NULL;

    uint32_t absPartIdxRT = g_zscanToRaster[curPartUnitIdx];//获取当前光栅扫描位置

    if (lessThanCol(absPartIdxRT, s_numPartInCUSize - partUnitOffset, s_numPartInCUSize))//如果被参考块没有超过当前CTU列的边界 (在同一个CTU中)
    {
        if (!isZeroRow(absPartIdxRT, s_numPartInCUSize))//如果当前不是CTU第一行
        {
            if (curPartUnitIdx > g_rasterToZscan[absPartIdxRT - s_numPartInCUSize + partUnitOffset])//必须保证右上块已经编码完毕 即当前的zigzag号要大于参考块的zigzag号(因为当前在同一个CTU下)
            {
                uint32_t absZorderCUIdx = g_zscanToRaster[m_absIdxInCTU] + (1 << (m_log2CUSize[0] - LOG2_UNIT_SIZE)) - 1;//将当前CU左上角在CTU位置的zigzag扫描改为光栅扫描
                arPartUnitIdx = g_rasterToZscan[absPartIdxRT - s_numPartInCUSize + partUnitOffset];//获取右上位置
                /*以intra NxN为例
                ----------------
                |  PU0  |   PU1|
                ----------------
                |  PU2  |   PU3|
                ----------------
                isEqualRowOrCol指的是PU0 和 PU1  PU3  因为其右上角参考像素点在另一个CU中
                注意:这里指的是PU右上角像素点
                **/
                if (isEqualRowOrCol(absPartIdxRT, absZorderCUIdx, s_numPartInCUSize))//如果当前PU右上角与CU处于同一行 或者同一列
                    return m_encData->getPicCTU(m_cuAddr);//返回当前CTU
                else
                {
                    arPartUnitIdx -= m_absIdxInCTU;//获取在CU内部的参考像素点的zigzag标号
                    return this;//返回当前CU
                }
            }
            return NULL;//右上不可用 返回null
        }
        //当前PU右上角像素点是CTU的第一行
        arPartUnitIdx = g_rasterToZscan[absPartIdxRT + NUM_4x4_PARTITIONS - s_numPartInCUSize + partUnitOffset];//获取参考像素点在上边CTU的内部zigzag标号
        return m_cuAbove;//返回上边CTU (因为当前右上角参考像素行在上边CTU中)
    }

    if (!isZeroRow(absPartIdxRT, s_numPartInCUSize))//当前PU不在CTU第一行 说明右上参考像素点在右边CTU(尚未编码)
        return NULL;//返回null

    arPartUnitIdx = g_rasterToZscan[NUM_4x4_PARTITIONS - s_numPartInCUSize + partUnitOffset - 1];//获取参考像素点在右上边CTU的内部zigzag标号
    return m_cuAboveRight;//返回右上CTU
}

/* Get left QpMinCu */
const CUData* CUData::getQpMinCuLeft(uint32_t& lPartUnitIdx, uint32_t curAbsIdxInCTU) const
{
    uint32_t absZorderQpMinCUIdx = curAbsIdxInCTU & (0xFF << (g_unitSizeDepth - m_slice->m_pps->maxCuDQPDepth) * 2);
    uint32_t absRorderQpMinCUIdx = g_zscanToRaster[absZorderQpMinCUIdx];

    // check for left CTU boundary
    if (isZeroCol(absRorderQpMinCUIdx, s_numPartInCUSize))
        return NULL;

    // get index of left-CU relative to top-left corner of current quantization group
    lPartUnitIdx = g_rasterToZscan[absRorderQpMinCUIdx - 1];

    // return pointer to current CTU
    return m_encData->getPicCTU(m_cuAddr);
}

/* Get above QpMinCu */
const CUData* CUData::getQpMinCuAbove(uint32_t& aPartUnitIdx, uint32_t curAbsIdxInCTU) const
{
    uint32_t absZorderQpMinCUIdx = curAbsIdxInCTU & (0xFF << (g_unitSizeDepth - m_slice->m_pps->maxCuDQPDepth) * 2);
    uint32_t absRorderQpMinCUIdx = g_zscanToRaster[absZorderQpMinCUIdx];

    // check for top CTU boundary
    if (isZeroRow(absRorderQpMinCUIdx, s_numPartInCUSize))
        return NULL;

    // get index of top-CU relative to top-left corner of current quantization group
    aPartUnitIdx = g_rasterToZscan[absRorderQpMinCUIdx - s_numPartInCUSize];

    // return pointer to current CTU
    return m_encData->getPicCTU(m_cuAddr);
}

/* Get reference QP from left QpMinCu or latest coded QP */
int8_t CUData::getRefQP(uint32_t curAbsIdxInCTU) const
{
    uint32_t lPartIdx = 0, aPartIdx = 0;
    const CUData* cULeft = getQpMinCuLeft(lPartIdx, m_absIdxInCTU + curAbsIdxInCTU);
    const CUData* cUAbove = getQpMinCuAbove(aPartIdx, m_absIdxInCTU + curAbsIdxInCTU);

    return ((cULeft ? cULeft->m_qp[lPartIdx] : getLastCodedQP(curAbsIdxInCTU)) + (cUAbove ? cUAbove->m_qp[aPartIdx] : getLastCodedQP(curAbsIdxInCTU)) + 1) >> 1;
}

int CUData::getLastValidPartIdx(int absPartIdx) const
{
    int lastValidPartIdx = absPartIdx - 1;

    while (lastValidPartIdx >= 0 && m_predMode[lastValidPartIdx] == MODE_NONE)
    {
        uint32_t depth = m_cuDepth[lastValidPartIdx];
        lastValidPartIdx -= m_numPartitions >> (depth << 1);
    }

    return lastValidPartIdx;
}

int8_t CUData::getLastCodedQP(uint32_t absPartIdx) const
{
    uint32_t quPartIdxMask = 0xFF << (g_unitSizeDepth - m_slice->m_pps->maxCuDQPDepth) * 2;
    int lastValidPartIdx = getLastValidPartIdx(absPartIdx & quPartIdxMask);

    if (lastValidPartIdx >= 0)
        return m_qp[lastValidPartIdx];
    else
    {
        if (m_absIdxInCTU)
            return m_encData->getPicCTU(m_cuAddr)->getLastCodedQP(m_absIdxInCTU);
        else if (m_cuAddr > 0 && !(m_slice->m_pps->bEntropyCodingSyncEnabled && !(m_cuAddr % m_slice->m_sps->numCuInWidth)))
            return m_encData->getPicCTU(m_cuAddr - 1)->getLastCodedQP(NUM_4x4_PARTITIONS);
        else
            return (int8_t)m_slice->m_sliceQp;
    }
}

/* Get allowed chroma intra modes */
void CUData::getAllowedChromaDir(uint32_t absPartIdx, uint32_t* modeList) const
{
    modeList[0] = PLANAR_IDX;
    modeList[1] = VER_IDX;
    modeList[2] = HOR_IDX;
    modeList[3] = DC_IDX;
    modeList[4] = DM_CHROMA_IDX;

    uint32_t lumaMode = m_lumaIntraDir[absPartIdx];

    for (int i = 0; i < NUM_CHROMA_MODE - 1; i++)
    {
        if (lumaMode == modeList[i])
        {
            modeList[i] = 34; // VER+8 mode
            break;
        }
    }
}

/* Get most probable intra modes */
/** 函数功能             : 获取3个最有可能的帧内预测模式 并A(左边)与B(上边)方向相同(或者都不是intra块)则返回1 不同返回2
/*  调用范围             : 只在codeIntraDirLumaAng和getIntraRemModeBits函数中被调用
* \参数 absPartIdx       : PU在CU的zigzag标号
* \参数 intraDirPred     : 存储3个最有可能的帧内预测模式
*   返回值               : A(左边)与B(上边)方向相同(或者都不是intra块)则返回1 不同返回2**/
int CUData::getIntraDirLumaPredictor(uint32_t absPartIdx, uint32_t* intraDirPred) const
{
    const CUData* tempCU;//用于临时存储CU
    uint32_t tempPartIdx;//用于临时存储相邻块的zigzag编号
    uint32_t leftIntraDir, aboveIntraDir;//分别存储 左边 和上边的预测方向
    /* B:aboveIntraDir A:leftIntraDir
      B
     -------------
   A |           |
     |  当前PU   |
     -------------
    **/

    // Get intra direction of left PU
    tempCU = getPULeft(tempPartIdx, m_absIdxInCTU + absPartIdx);//获取A所在的CU:tempCU  tempPartIdx:A在tempCU的zigzag编号

    leftIntraDir = (tempCU && tempCU->isIntra(tempPartIdx)) ? tempCU->m_lumaIntraDir[tempPartIdx] : DC_IDX;//获取A的方向 无则置为DC

    // Get intra direction of above PU
    tempCU = g_zscanToPelY[m_absIdxInCTU + absPartIdx] > 0 ? getPUAbove(tempPartIdx, m_absIdxInCTU + absPartIdx) : NULL;//获取B所在的CU:tempCU  tempPartIdx:B在tempCU的zigzag编号

    aboveIntraDir = (tempCU && tempCU->isIntra(tempPartIdx)) ? tempCU->m_lumaIntraDir[tempPartIdx] : DC_IDX;//获取B的方向 无则置为DC

    if (leftIntraDir == aboveIntraDir)//如果A与B的方向相同
    {
        if (leftIntraDir >= 2) //如果A与B都为角度模式 angular modes
        {
            /*角度模式:
            (左33) 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 (右3)
            **/
            intraDirPred[0] = leftIntraDir; //0:获取A的方向
            intraDirPred[1] = ((leftIntraDir - 2 + 31) & 31) + 2;//1:获取A相邻的左边方向  
            intraDirPred[2] = ((leftIntraDir - 2 +  1) & 31) + 2;//2:获取A相邻的右边方向
        }
        else //如果A与B都不为角度模式non-angular
        {
            intraDirPred[0] = PLANAR_IDX;//0:为 PLANar模式
            intraDirPred[1] = DC_IDX;//1:DC模式
            intraDirPred[2] = VER_IDX;//2:垂直模式
        }
        return 1;//A(左边)与B(上边)方向相同(或者都不是intra块)则返回1
    }
    else//如果A与B的方向不同
    {
        intraDirPred[0] = leftIntraDir;//0:A 左边预测方向
        intraDirPred[1] = aboveIntraDir;//1:B 上边预测方向

        if (leftIntraDir && aboveIntraDir) //A与B任意一个都不为Planar模式 both modes are non-planar
            intraDirPred[2] = PLANAR_IDX;//2:置为planar模式
        else
            intraDirPred[2] =  (leftIntraDir + aboveIntraDir) < 2 ? VER_IDX : DC_IDX;//A与B任意一个都不为DC或者PLANAR 则2:DC  否则 2:垂直模式  注意:因为此处已经排除A=B=DC模式 所有 小于2即可
        return 2;//A(左边)与B(上边)方向不同 则返回1
    }
}

uint32_t CUData::getCtxSplitFlag(uint32_t absPartIdx, uint32_t depth) const
{
    const CUData* tempCU;
    uint32_t    tempPartIdx;
    uint32_t    ctx;

    // Get left split flag
    tempCU = getPULeft(tempPartIdx, m_absIdxInCTU + absPartIdx);
    ctx  = (tempCU) ? ((tempCU->m_cuDepth[tempPartIdx] > depth) ? 1 : 0) : 0;

    // Get above split flag
    tempCU = getPUAbove(tempPartIdx, m_absIdxInCTU + absPartIdx);
    ctx += (tempCU) ? ((tempCU->m_cuDepth[tempPartIdx] > depth) ? 1 : 0) : 0;

    return ctx;
}
/** 函数功能           : 分别获取intraCU下最小TU,最大TU
* \参数 tuDepthRange[2]: 分别存储最小TU,最大TU
* \参数 absPartIdx     : 在Entropy::encodeCU为当前CU的左上角标号,其它位置为0
*   返回值             : null
**/
void CUData::getIntraTUQtDepthRange(uint32_t tuDepthRange[2], uint32_t absPartIdx) const
{
    /*
    样例:m_slice->m_sps->quadtreeTULog2MinSize =2  m_slice->m_sps->quadtreeTULog2MaxSize = 5 m_slice->m_sps->quadtreeTUMaxDepthIntra =2
    cu:6 split:0  tu[0]=5 tu[1]=5
    cu:6 split:1  tu[0]=4 tu[1]=5
    cu:5 split:0  tu[0]=4 tu[1]=5
    cu:5 split:1  tu[0]=3 tu[1]=5
    cu:4 split:0  tu[0]=3 tu[1]=5
    cu:4 split:1  tu[0]=2 tu[1]=5
    cu:3 split:0  tu[0]=2 tu[1]=5
    cu:3 split:1  tu[0]=2 tu[1]=5
    **/
    uint32_t log2CUSize = m_log2CUSize[absPartIdx];//获取当前CU大小 6:64x64 5:32x32 .....
    uint32_t splitFlag = m_partSize[absPartIdx] != SIZE_2Nx2N;//是否划分 2Nx2N 为0 其它为1

    tuDepthRange[0] = m_slice->m_sps->quadtreeTULog2MinSize; // 最大TU尺寸
    tuDepthRange[1] = m_slice->m_sps->quadtreeTULog2MaxSize; // 最小TU尺寸

    tuDepthRange[0] = x265_clip3(tuDepthRange[0], tuDepthRange[1], log2CUSize - (m_slice->m_sps->quadtreeTUMaxDepthIntra - 1 + splitFlag));//获取最小TU CU-(TUintra - 1 + split)
}

void CUData::getInterTUQtDepthRange(uint32_t tuDepthRange[2], uint32_t absPartIdx) const
{
    uint32_t log2CUSize = m_log2CUSize[absPartIdx];
    uint32_t quadtreeTUMaxDepth = m_slice->m_sps->quadtreeTUMaxDepthInter;
    uint32_t splitFlag = quadtreeTUMaxDepth == 1 && m_partSize[absPartIdx] != SIZE_2Nx2N;

    tuDepthRange[0] = m_slice->m_sps->quadtreeTULog2MinSize;
    tuDepthRange[1] = m_slice->m_sps->quadtreeTULog2MaxSize;

    tuDepthRange[0] = x265_clip3(tuDepthRange[0], tuDepthRange[1], log2CUSize - (quadtreeTUMaxDepth - 1 + splitFlag));
}

uint32_t CUData::getCtxSkipFlag(uint32_t absPartIdx) const
{
    const CUData* tempCU;
    uint32_t tempPartIdx;
    uint32_t ctx;

    // Get BCBP of left PU
    tempCU = getPULeft(tempPartIdx, m_absIdxInCTU + absPartIdx);
    ctx    = tempCU ? tempCU->isSkipped(tempPartIdx) : 0;

    // Get BCBP of above PU
    tempCU = getPUAbove(tempPartIdx, m_absIdxInCTU + absPartIdx);
    ctx   += tempCU ? tempCU->isSkipped(tempPartIdx) : 0;

    return ctx;
}

bool CUData::setQPSubCUs(int8_t qp, uint32_t absPartIdx, uint32_t depth)
{
    uint32_t curPartNumb = NUM_4x4_PARTITIONS >> (depth << 1);
    uint32_t curPartNumQ = curPartNumb >> 2;

    if (m_cuDepth[absPartIdx] > depth)
    {
        for (uint32_t subPartIdx = 0; subPartIdx < 4; subPartIdx++)
            if (setQPSubCUs(qp, absPartIdx + subPartIdx * curPartNumQ, depth + 1))
                return true;
    }
    else
    {
        if (getQtRootCbf(absPartIdx))
            return true;
        else
            setQPSubParts(qp, absPartIdx, depth);
    }

    return false;
}

void CUData::setPUInterDir(uint8_t dir, uint32_t absPartIdx, uint32_t puIdx)
{
    uint32_t curPartNumQ = m_numPartitions >> 2;
    X265_CHECK(puIdx < 2, "unexpected part unit index\n");

    switch (m_partSize[absPartIdx])
    {
    case SIZE_2Nx2N:
        memset(m_interDir + absPartIdx, dir, 4 * curPartNumQ);
        break;
    case SIZE_2NxN:
        memset(m_interDir + absPartIdx, dir, 2 * curPartNumQ);
        break;
    case SIZE_Nx2N:
        memset(m_interDir + absPartIdx, dir, curPartNumQ);
        memset(m_interDir + absPartIdx + 2 * curPartNumQ, dir, curPartNumQ);
        break;
    case SIZE_NxN:
        memset(m_interDir + absPartIdx, dir, curPartNumQ);
        break;
    case SIZE_2NxnU:
        if (!puIdx)
        {
            memset(m_interDir + absPartIdx, dir, (curPartNumQ >> 1));
            memset(m_interDir + absPartIdx + curPartNumQ, dir, (curPartNumQ >> 1));
        }
        else
        {
            memset(m_interDir + absPartIdx, dir, (curPartNumQ >> 1));
            memset(m_interDir + absPartIdx + curPartNumQ, dir, ((curPartNumQ >> 1) + (curPartNumQ << 1)));
        }
        break;
    case SIZE_2NxnD:
        if (!puIdx)
        {
            memset(m_interDir + absPartIdx, dir, ((curPartNumQ << 1) + (curPartNumQ >> 1)));
            memset(m_interDir + absPartIdx + (curPartNumQ << 1) + curPartNumQ, dir, (curPartNumQ >> 1));
        }
        else
        {
            memset(m_interDir + absPartIdx, dir, (curPartNumQ >> 1));
            memset(m_interDir + absPartIdx + curPartNumQ, dir, (curPartNumQ >> 1));
        }
        break;
    case SIZE_nLx2N:
        if (!puIdx)
        {
            memset(m_interDir + absPartIdx, dir, (curPartNumQ >> 2));
            memset(m_interDir + absPartIdx + (curPartNumQ >> 1), dir, (curPartNumQ >> 2));
            memset(m_interDir + absPartIdx + (curPartNumQ << 1), dir, (curPartNumQ >> 2));
            memset(m_interDir + absPartIdx + (curPartNumQ << 1) + (curPartNumQ >> 1), dir, (curPartNumQ >> 2));
        }
        else
        {
            memset(m_interDir + absPartIdx, dir, (curPartNumQ >> 2));
            memset(m_interDir + absPartIdx + (curPartNumQ >> 1), dir, (curPartNumQ + (curPartNumQ >> 2)));
            memset(m_interDir + absPartIdx + (curPartNumQ << 1), dir, (curPartNumQ >> 2));
            memset(m_interDir + absPartIdx + (curPartNumQ << 1) + (curPartNumQ >> 1), dir, (curPartNumQ + (curPartNumQ >> 2)));
        }
        break;
    case SIZE_nRx2N:
        if (!puIdx)
        {
            memset(m_interDir + absPartIdx, dir, (curPartNumQ + (curPartNumQ >> 2)));
            memset(m_interDir + absPartIdx + curPartNumQ + (curPartNumQ >> 1), dir, (curPartNumQ >> 2));
            memset(m_interDir + absPartIdx + (curPartNumQ << 1), dir, (curPartNumQ + (curPartNumQ >> 2)));
            memset(m_interDir + absPartIdx + (curPartNumQ << 1) + curPartNumQ + (curPartNumQ >> 1), dir, (curPartNumQ >> 2));
        }
        else
        {
            memset(m_interDir + absPartIdx, dir, (curPartNumQ >> 2));
            memset(m_interDir + absPartIdx + (curPartNumQ >> 1), dir, (curPartNumQ >> 2));
            memset(m_interDir + absPartIdx + (curPartNumQ << 1), dir, (curPartNumQ >> 2));
            memset(m_interDir + absPartIdx + (curPartNumQ << 1) + (curPartNumQ >> 1), dir, (curPartNumQ >> 2));
        }
        break;
    default:
        X265_CHECK(0, "unexpected part type\n");
        break;
    }
}

template<typename T>
void CUData::setAllPU(T* p, const T& val, int absPartIdx, int puIdx)
{
    int i;

    p += absPartIdx;
    int numElements = m_numPartitions;

    switch (m_partSize[absPartIdx])
    {
    case SIZE_2Nx2N:
        for (i = 0; i < numElements; i++)
            p[i] = val;
        break;

    case SIZE_2NxN:
        numElements >>= 1;
        for (i = 0; i < numElements; i++)
            p[i] = val;
        break;

    case SIZE_Nx2N:
        numElements >>= 2;
        for (i = 0; i < numElements; i++)
        {
            p[i] = val;
            p[i + 2 * numElements] = val;
        }
        break;

    case SIZE_2NxnU:
    {
        int curPartNumQ = numElements >> 2;
        if (!puIdx)
        {
            T *pT  = p;
            T *pT2 = p + curPartNumQ;
            for (i = 0; i < (curPartNumQ >> 1); i++)
            {
                pT[i] = val;
                pT2[i] = val;
            }
        }
        else
        {
            T *pT  = p;
            for (i = 0; i < (curPartNumQ >> 1); i++)
                pT[i] = val;

            pT = p + curPartNumQ;
            for (i = 0; i < ((curPartNumQ >> 1) + (curPartNumQ << 1)); i++)
                pT[i] = val;
        }
        break;
    }

    case SIZE_2NxnD:
    {
        int curPartNumQ = numElements >> 2;
        if (!puIdx)
        {
            T *pT  = p;
            for (i = 0; i < ((curPartNumQ >> 1) + (curPartNumQ << 1)); i++)
                pT[i] = val;

            pT = p + (numElements - curPartNumQ);
            for (i = 0; i < (curPartNumQ >> 1); i++)
                pT[i] = val;
        }
        else
        {
            T *pT  = p;
            T *pT2 = p + curPartNumQ;
            for (i = 0; i < (curPartNumQ >> 1); i++)
            {
                pT[i] = val;
                pT2[i] = val;
            }
        }
        break;
    }

    case SIZE_nLx2N:
    {
        int curPartNumQ = numElements >> 2;
        if (!puIdx)
        {
            T *pT  = p;
            T *pT2 = p + (curPartNumQ << 1);
            T *pT3 = p + (curPartNumQ >> 1);
            T *pT4 = p + (curPartNumQ << 1) + (curPartNumQ >> 1);

            for (i = 0; i < (curPartNumQ >> 2); i++)
            {
                pT[i] = val;
                pT2[i] = val;
                pT3[i] = val;
                pT4[i] = val;
            }
        }
        else
        {
            T *pT  = p;
            T *pT2 = p + (curPartNumQ << 1);
            for (i = 0; i < (curPartNumQ >> 2); i++)
            {
                pT[i] = val;
                pT2[i] = val;
            }

            pT  = p + (curPartNumQ >> 1);
            pT2 = p + (curPartNumQ << 1) + (curPartNumQ >> 1);
            for (i = 0; i < ((curPartNumQ >> 2) + curPartNumQ); i++)
            {
                pT[i] = val;
                pT2[i] = val;
            }
        }
        break;
    }

    case SIZE_nRx2N:
    {
        int curPartNumQ = numElements >> 2;
        if (!puIdx)
        {
            T *pT  = p;
            T *pT2 = p + (curPartNumQ << 1);
            for (i = 0; i < ((curPartNumQ >> 2) + curPartNumQ); i++)
            {
                pT[i] = val;
                pT2[i] = val;
            }

            pT  = p + curPartNumQ + (curPartNumQ >> 1);
            pT2 = p + numElements - curPartNumQ + (curPartNumQ >> 1);
            for (i = 0; i < (curPartNumQ >> 2); i++)
            {
                pT[i] = val;
                pT2[i] = val;
            }
        }
        else
        {
            T *pT  = p;
            T *pT2 = p + (curPartNumQ >> 1);
            T *pT3 = p + (curPartNumQ << 1);
            T *pT4 = p + (curPartNumQ << 1) + (curPartNumQ >> 1);
            for (i = 0; i < (curPartNumQ >> 2); i++)
            {
                pT[i] = val;
                pT2[i] = val;
                pT3[i] = val;
                pT4[i] = val;
            }
        }
        break;
    }

    case SIZE_NxN:
    default:
        X265_CHECK(0, "unknown partition type\n");
        break;
    }
}

void CUData::setPUMv(int list, const MV& mv, int absPartIdx, int puIdx)
{
    setAllPU(m_mv[list], mv, absPartIdx, puIdx);
}

void CUData::setPURefIdx(int list, int8_t refIdx, int absPartIdx, int puIdx)
{
    setAllPU(m_refIdx[list], refIdx, absPartIdx, puIdx);
}

void CUData::getPartIndexAndSize(uint32_t partIdx, uint32_t& outPartAddr, int& outWidth, int& outHeight) const
{
    int cuSize = 1 << m_log2CUSize[0];
    int partType = m_partSize[0];

    int tmp = partTable[partType][partIdx][0];
    outWidth = ((tmp >> 4) * cuSize) >> 2;
    outHeight = ((tmp & 0xF) * cuSize) >> 2;
    outPartAddr = (partAddrTable[partType][partIdx] * m_numPartitions) >> 4;
}

void CUData::getMvField(const CUData* cu, uint32_t absPartIdx, int picList, MVField& outMvField) const
{
    if (cu)
    {
        outMvField.mv = cu->m_mv[picList][absPartIdx];
        outMvField.refIdx = cu->m_refIdx[picList][absPartIdx];
    }
    else
    {
        // OUT OF BOUNDARY
        outMvField.mv = 0;
        outMvField.refIdx = REF_NOT_VALID;
    }
}

void CUData::deriveLeftRightTopIdx(uint32_t partIdx, uint32_t& partIdxLT, uint32_t& partIdxRT) const
{
    partIdxLT = m_absIdxInCTU;
    partIdxRT = g_rasterToZscan[g_zscanToRaster[partIdxLT] + (1 << (m_log2CUSize[0] - LOG2_UNIT_SIZE)) - 1];

    switch (m_partSize[0])
    {
    case SIZE_2Nx2N: break;
    case SIZE_2NxN:
        partIdxLT += (partIdx == 0) ? 0 : m_numPartitions >> 1;
        partIdxRT += (partIdx == 0) ? 0 : m_numPartitions >> 1;
        break;
    case SIZE_Nx2N:
        partIdxLT += (partIdx == 0) ? 0 : m_numPartitions >> 2;
        partIdxRT -= (partIdx == 1) ? 0 : m_numPartitions >> 2;
        break;
    case SIZE_NxN:
        partIdxLT += (m_numPartitions >> 2) * partIdx;
        partIdxRT +=  (m_numPartitions >> 2) * (partIdx - 1);
        break;
    case SIZE_2NxnU:
        partIdxLT += (partIdx == 0) ? 0 : m_numPartitions >> 3;
        partIdxRT += (partIdx == 0) ? 0 : m_numPartitions >> 3;
        break;
    case SIZE_2NxnD:
        partIdxLT += (partIdx == 0) ? 0 : (m_numPartitions >> 1) + (m_numPartitions >> 3);
        partIdxRT += (partIdx == 0) ? 0 : (m_numPartitions >> 1) + (m_numPartitions >> 3);
        break;
    case SIZE_nLx2N:
        partIdxLT += (partIdx == 0) ? 0 : m_numPartitions >> 4;
        partIdxRT -= (partIdx == 1) ? 0 : (m_numPartitions >> 2) + (m_numPartitions >> 4);
        break;
    case SIZE_nRx2N:
        partIdxLT += (partIdx == 0) ? 0 : (m_numPartitions >> 2) + (m_numPartitions >> 4);
        partIdxRT -= (partIdx == 1) ? 0 : m_numPartitions >> 4;
        break;
    default:
        X265_CHECK(0, "unexpected part index\n");
        break;
    }
}

uint32_t CUData::deriveLeftBottomIdx(uint32_t puIdx) const
{
    uint32_t outPartIdxLB;
    outPartIdxLB = g_rasterToZscan[g_zscanToRaster[m_absIdxInCTU] + ((1 << (m_log2CUSize[0] - LOG2_UNIT_SIZE - 1)) - 1) * s_numPartInCUSize];

    switch (m_partSize[0])
    {
    case SIZE_2Nx2N:
        outPartIdxLB += m_numPartitions >> 1;
        break;
    case SIZE_2NxN:
        outPartIdxLB += puIdx ? m_numPartitions >> 1 : 0;
        break;
    case SIZE_Nx2N:
        outPartIdxLB += puIdx ? (m_numPartitions >> 2) * 3 : m_numPartitions >> 1;
        break;
    case SIZE_NxN:
        outPartIdxLB += (m_numPartitions >> 2) * puIdx;
        break;
    case SIZE_2NxnU:
        outPartIdxLB += puIdx ? m_numPartitions >> 1 : -((int)m_numPartitions >> 3);
        break;
    case SIZE_2NxnD:
        outPartIdxLB += puIdx ? m_numPartitions >> 1 : (m_numPartitions >> 2) + (m_numPartitions >> 3);
        break;
    case SIZE_nLx2N:
        outPartIdxLB += puIdx ? (m_numPartitions >> 1) + (m_numPartitions >> 4) : m_numPartitions >> 1;
        break;
    case SIZE_nRx2N:
        outPartIdxLB += puIdx ? (m_numPartitions >> 1) + (m_numPartitions >> 2) + (m_numPartitions >> 4) : m_numPartitions >> 1;
        break;
    default:
        X265_CHECK(0, "unexpected part index\n");
        break;
    }
    return outPartIdxLB;
}

/* Derives the partition index of neighboring bottom right block */
uint32_t CUData::deriveRightBottomIdx(uint32_t puIdx) const
{
    uint32_t outPartIdxRB;
    outPartIdxRB = g_rasterToZscan[g_zscanToRaster[m_absIdxInCTU] +
                                   ((1 << (m_log2CUSize[0] - LOG2_UNIT_SIZE - 1)) - 1) * s_numPartInCUSize +
                                   (1 << (m_log2CUSize[0] - LOG2_UNIT_SIZE)) - 1];

    switch (m_partSize[0])
    {
    case SIZE_2Nx2N:
        outPartIdxRB += m_numPartitions >> 1;
        break;
    case SIZE_2NxN:
        outPartIdxRB += puIdx ? m_numPartitions >> 1 : 0;
        break;
    case SIZE_Nx2N:
        outPartIdxRB += puIdx ? m_numPartitions >> 1 : m_numPartitions >> 2;
        break;
    case SIZE_NxN:
        outPartIdxRB += (m_numPartitions >> 2) * (puIdx - 1);
        break;
    case SIZE_2NxnU:
        outPartIdxRB += puIdx ? m_numPartitions >> 1 : -((int)m_numPartitions >> 3);
        break;
    case SIZE_2NxnD:
        outPartIdxRB += puIdx ? m_numPartitions >> 1 : (m_numPartitions >> 2) + (m_numPartitions >> 3);
        break;
    case SIZE_nLx2N:
        outPartIdxRB += puIdx ? m_numPartitions >> 1 : (m_numPartitions >> 3) + (m_numPartitions >> 4);
        break;
    case SIZE_nRx2N:
        outPartIdxRB += puIdx ? m_numPartitions >> 1 : (m_numPartitions >> 2) + (m_numPartitions >> 3) + (m_numPartitions >> 4);
        break;
    default:
        X265_CHECK(0, "unexpected part index\n");
        break;
    }
    return outPartIdxRB;
}

bool CUData::hasEqualMotion(uint32_t absPartIdx, const CUData& candCU, uint32_t candAbsPartIdx) const
{
    if (m_interDir[absPartIdx] != candCU.m_interDir[candAbsPartIdx])
        return false;

    for (uint32_t refListIdx = 0; refListIdx < 2; refListIdx++)
    {
        if (m_interDir[absPartIdx] & (1 << refListIdx))
        {
            if (m_mv[refListIdx][absPartIdx] != candCU.m_mv[refListIdx][candAbsPartIdx] ||
                m_refIdx[refListIdx][absPartIdx] != candCU.m_refIdx[refListIdx][candAbsPartIdx])
                return false;
        }
    }

    return true;
}

/* Construct list of merging candidates, returns count */
uint32_t CUData::getInterMergeCandidates(uint32_t absPartIdx, uint32_t puIdx, MVField(*candMvField)[2], uint8_t* candDir) const
{
    uint32_t absPartAddr = m_absIdxInCTU + absPartIdx;
    const bool isInterB = m_slice->isInterB();

    const uint32_t maxNumMergeCand = m_slice->m_maxNumMergeCand;

    for (uint32_t i = 0; i < maxNumMergeCand; ++i)
    {
        candMvField[i][0].mv = 0;
        candMvField[i][1].mv = 0;
        candMvField[i][0].refIdx = REF_NOT_VALID;
        candMvField[i][1].refIdx = REF_NOT_VALID;
    }

    /* calculate the location of upper-left corner pixel and size of the current PU */
    int xP, yP, nPSW, nPSH;

    int cuSize = 1 << m_log2CUSize[0];
    int partMode = m_partSize[0];

    int tmp = partTable[partMode][puIdx][0];
    nPSW = ((tmp >> 4) * cuSize) >> 2;
    nPSH = ((tmp & 0xF) * cuSize) >> 2;

    tmp = partTable[partMode][puIdx][1];
    xP = ((tmp >> 4) * cuSize) >> 2;
    yP = ((tmp & 0xF) * cuSize) >> 2;

    uint32_t count = 0;

    uint32_t partIdxLT, partIdxRT, partIdxLB = deriveLeftBottomIdx(puIdx);
    PartSize curPS = (PartSize)m_partSize[absPartIdx];
    
    // left
    uint32_t leftPartIdx = 0;
    const CUData* cuLeft = getPULeft(leftPartIdx, partIdxLB);
    bool isAvailableA1 = cuLeft &&
        cuLeft->isDiffMER(xP - 1, yP + nPSH - 1, xP, yP) &&
        !(puIdx == 1 && (curPS == SIZE_Nx2N || curPS == SIZE_nLx2N || curPS == SIZE_nRx2N)) &&
        cuLeft->isInter(leftPartIdx);
    if (isAvailableA1)
    {
        // get Inter Dir
        candDir[count] = cuLeft->m_interDir[leftPartIdx];
        // get Mv from Left
        cuLeft->getMvField(cuLeft, leftPartIdx, 0, candMvField[count][0]);
        if (isInterB)
            cuLeft->getMvField(cuLeft, leftPartIdx, 1, candMvField[count][1]);

        if (++count == maxNumMergeCand)
            return maxNumMergeCand;
    }

    deriveLeftRightTopIdx(puIdx, partIdxLT, partIdxRT);

    // above
    uint32_t abovePartIdx = 0;
    const CUData* cuAbove = getPUAbove(abovePartIdx, partIdxRT);
    bool isAvailableB1 = cuAbove &&
        cuAbove->isDiffMER(xP + nPSW - 1, yP - 1, xP, yP) &&
        !(puIdx == 1 && (curPS == SIZE_2NxN || curPS == SIZE_2NxnU || curPS == SIZE_2NxnD)) &&
        cuAbove->isInter(abovePartIdx);
    if (isAvailableB1 && (!isAvailableA1 || !cuLeft->hasEqualMotion(leftPartIdx, *cuAbove, abovePartIdx)))
    {
        // get Inter Dir
        candDir[count] = cuAbove->m_interDir[abovePartIdx];
        // get Mv from Left
        cuAbove->getMvField(cuAbove, abovePartIdx, 0, candMvField[count][0]);
        if (isInterB)
            cuAbove->getMvField(cuAbove, abovePartIdx, 1, candMvField[count][1]);

        if (++count == maxNumMergeCand)
            return maxNumMergeCand;
    }

    // above right
    uint32_t aboveRightPartIdx = 0;
    const CUData* cuAboveRight = getPUAboveRight(aboveRightPartIdx, partIdxRT);
    bool isAvailableB0 = cuAboveRight &&
        cuAboveRight->isDiffMER(xP + nPSW, yP - 1, xP, yP) &&
        cuAboveRight->isInter(aboveRightPartIdx);
    if (isAvailableB0 && (!isAvailableB1 || !cuAbove->hasEqualMotion(abovePartIdx, *cuAboveRight, aboveRightPartIdx)))
    {
        // get Inter Dir
        candDir[count] = cuAboveRight->m_interDir[aboveRightPartIdx];
        // get Mv from Left
        cuAboveRight->getMvField(cuAboveRight, aboveRightPartIdx, 0, candMvField[count][0]);
        if (isInterB)
            cuAboveRight->getMvField(cuAboveRight, aboveRightPartIdx, 1, candMvField[count][1]);

        if (++count == maxNumMergeCand)
            return maxNumMergeCand;
    }

    // left bottom
    uint32_t leftBottomPartIdx = 0;
    const CUData* cuLeftBottom = this->getPUBelowLeft(leftBottomPartIdx, partIdxLB);
    bool isAvailableA0 = cuLeftBottom &&
        cuLeftBottom->isDiffMER(xP - 1, yP + nPSH, xP, yP) &&
        cuLeftBottom->isInter(leftBottomPartIdx);
    if (isAvailableA0 && (!isAvailableA1 || !cuLeft->hasEqualMotion(leftPartIdx, *cuLeftBottom, leftBottomPartIdx)))
    {
        // get Inter Dir
        candDir[count] = cuLeftBottom->m_interDir[leftBottomPartIdx];
        // get Mv from Left
        cuLeftBottom->getMvField(cuLeftBottom, leftBottomPartIdx, 0, candMvField[count][0]);
        if (isInterB)
            cuLeftBottom->getMvField(cuLeftBottom, leftBottomPartIdx, 1, candMvField[count][1]);

        if (++count == maxNumMergeCand)
            return maxNumMergeCand;
    }

    // above left
    if (count < 4)
    {
        uint32_t aboveLeftPartIdx = 0;
        const CUData* cuAboveLeft = getPUAboveLeft(aboveLeftPartIdx, absPartAddr);
        bool isAvailableB2 = cuAboveLeft &&
            cuAboveLeft->isDiffMER(xP - 1, yP - 1, xP, yP) &&
            cuAboveLeft->isInter(aboveLeftPartIdx);
        if (isAvailableB2 && (!isAvailableA1 || !cuLeft->hasEqualMotion(leftPartIdx, *cuAboveLeft, aboveLeftPartIdx))
            && (!isAvailableB1 || !cuAbove->hasEqualMotion(abovePartIdx, *cuAboveLeft, aboveLeftPartIdx)))
        {
            // get Inter Dir
            candDir[count] = cuAboveLeft->m_interDir[aboveLeftPartIdx];
            // get Mv from Left
            cuAboveLeft->getMvField(cuAboveLeft, aboveLeftPartIdx, 0, candMvField[count][0]);
            if (isInterB)
                cuAboveLeft->getMvField(cuAboveLeft, aboveLeftPartIdx, 1, candMvField[count][1]);

            if (++count == maxNumMergeCand)
                return maxNumMergeCand;
        }
    }
    if (m_slice->m_sps->bTemporalMVPEnabled)
    {
        uint32_t partIdxRB = deriveRightBottomIdx(puIdx);
        MV colmv;
        int ctuIdx = -1;

        // image boundary check
        if (m_encData->getPicCTU(m_cuAddr)->m_cuPelX + g_zscanToPelX[partIdxRB] + UNIT_SIZE < m_slice->m_sps->picWidthInLumaSamples &&
            m_encData->getPicCTU(m_cuAddr)->m_cuPelY + g_zscanToPelY[partIdxRB] + UNIT_SIZE < m_slice->m_sps->picHeightInLumaSamples)
        {
            uint32_t absPartIdxRB = g_zscanToRaster[partIdxRB];
            uint32_t numUnits = s_numPartInCUSize;
            bool bNotLastCol = lessThanCol(absPartIdxRB, numUnits - 1, numUnits); // is not at the last column of CTU
            bool bNotLastRow = lessThanRow(absPartIdxRB, numUnits - 1, numUnits); // is not at the last row    of CTU

            if (bNotLastCol && bNotLastRow)
            {
                absPartAddr = g_rasterToZscan[absPartIdxRB + numUnits + 1];
                ctuIdx = m_cuAddr;
            }
            else if (bNotLastCol)
                absPartAddr = g_rasterToZscan[(absPartIdxRB + numUnits + 1) & (numUnits - 1)];
            else if (bNotLastRow)
            {
                absPartAddr = g_rasterToZscan[absPartIdxRB + 1];
                ctuIdx = m_cuAddr + 1;
            }
            else // is the right bottom corner of CTU
                absPartAddr = 0;
        }

        int maxList = isInterB ? 2 : 1;
        int dir = 0, refIdx = 0;
        for (int list = 0; list < maxList; list++)
        {
            bool bExistMV = ctuIdx >= 0 && getColMVP(colmv, refIdx, list, ctuIdx, absPartAddr);
            if (!bExistMV)
            {
                uint32_t partIdxCenter = deriveCenterIdx(puIdx);
                bExistMV = getColMVP(colmv, refIdx, list, m_cuAddr, partIdxCenter);
            }
            if (bExistMV)
            {
                dir |= (1 << list);
                candMvField[count][list].mv = colmv;
                candMvField[count][list].refIdx = refIdx;
            }
        }

        if (dir != 0)
        {
            candDir[count] = (uint8_t)dir;

            if (++count == maxNumMergeCand)
                return maxNumMergeCand;
        }
    }

    if (isInterB)
    {
        const uint32_t cutoff = count * (count - 1);
        uint32_t priorityList0 = 0xEDC984; // { 0, 1, 0, 2, 1, 2, 0, 3, 1, 3, 2, 3 }
        uint32_t priorityList1 = 0xB73621; // { 1, 0, 2, 0, 2, 1, 3, 0, 3, 1, 3, 2 }

        for (uint32_t idx = 0; idx < cutoff; idx++, priorityList0 >>= 2, priorityList1 >>= 2)
        {
            int i = priorityList0 & 3;
            int j = priorityList1 & 3;

            if ((candDir[i] & 0x1) && (candDir[j] & 0x2))
            {
                // get Mv from cand[i] and cand[j]
                int refIdxL0 = candMvField[i][0].refIdx;
                int refIdxL1 = candMvField[j][1].refIdx;
                int refPOCL0 = m_slice->m_refPOCList[0][refIdxL0];
                int refPOCL1 = m_slice->m_refPOCList[1][refIdxL1];
                if (!(refPOCL0 == refPOCL1 && candMvField[i][0].mv == candMvField[j][1].mv))
                {
                    candMvField[count][0].mv = candMvField[i][0].mv;
                    candMvField[count][0].refIdx = refIdxL0;
                    candMvField[count][1].mv = candMvField[j][1].mv;
                    candMvField[count][1].refIdx = refIdxL1;
                    candDir[count] = 3;

                    if (++count == maxNumMergeCand)
                        return maxNumMergeCand;
                }
            }
        }
    }
    int numRefIdx = (isInterB) ? X265_MIN(m_slice->m_numRefIdx[0], m_slice->m_numRefIdx[1]) : m_slice->m_numRefIdx[0];
    int r = 0;
    int refcnt = 0;
    while (count < maxNumMergeCand)
    {
        candDir[count] = 1;
        candMvField[count][0].mv.word = 0;
        candMvField[count][0].refIdx = r;

        if (isInterB)
        {
            candDir[count] = 3;
            candMvField[count][1].mv.word = 0;
            candMvField[count][1].refIdx = r;
        }

        count++;

        if (refcnt == numRefIdx - 1)
            r = 0;
        else
        {
            ++r;
            ++refcnt;
        }
    }

    return count;
}

// Create the PMV list. Called for each reference index.
int CUData::getPMV(InterNeighbourMV *neighbours, uint32_t picList, uint32_t refIdx, MV* amvpCand, MV* pmv) const
{
    MV directMV[MD_ABOVE_LEFT + 1];
    MV indirectMV[MD_ABOVE_LEFT + 1];
    bool validDirect[MD_ABOVE_LEFT + 1];
    bool validIndirect[MD_ABOVE_LEFT + 1];

    // Left candidate.
    validDirect[MD_BELOW_LEFT]  = getDirectPMV(directMV[MD_BELOW_LEFT], neighbours + MD_BELOW_LEFT, picList, refIdx);
    validDirect[MD_LEFT]        = getDirectPMV(directMV[MD_LEFT], neighbours + MD_LEFT, picList, refIdx);
    // Top candidate.
    validDirect[MD_ABOVE_RIGHT] = getDirectPMV(directMV[MD_ABOVE_RIGHT], neighbours + MD_ABOVE_RIGHT, picList, refIdx);
    validDirect[MD_ABOVE]       = getDirectPMV(directMV[MD_ABOVE], neighbours + MD_ABOVE, picList, refIdx);
    validDirect[MD_ABOVE_LEFT]  = getDirectPMV(directMV[MD_ABOVE_LEFT], neighbours + MD_ABOVE_LEFT, picList, refIdx);

    // Left candidate.
    validIndirect[MD_BELOW_LEFT]  = getIndirectPMV(indirectMV[MD_BELOW_LEFT], neighbours + MD_BELOW_LEFT, picList, refIdx);
    validIndirect[MD_LEFT]        = getIndirectPMV(indirectMV[MD_LEFT], neighbours + MD_LEFT, picList, refIdx);
    // Top candidate.
    validIndirect[MD_ABOVE_RIGHT] = getIndirectPMV(indirectMV[MD_ABOVE_RIGHT], neighbours + MD_ABOVE_RIGHT, picList, refIdx);
    validIndirect[MD_ABOVE]       = getIndirectPMV(indirectMV[MD_ABOVE], neighbours + MD_ABOVE, picList, refIdx);
    validIndirect[MD_ABOVE_LEFT]  = getIndirectPMV(indirectMV[MD_ABOVE_LEFT], neighbours + MD_ABOVE_LEFT, picList, refIdx);

    int num = 0;
    // Left predictor search
    if (validDirect[MD_BELOW_LEFT])
        amvpCand[num++] = directMV[MD_BELOW_LEFT];
    else if (validDirect[MD_LEFT])
        amvpCand[num++] = directMV[MD_LEFT];
    else if (validIndirect[MD_BELOW_LEFT])
        amvpCand[num++] = indirectMV[MD_BELOW_LEFT];
    else if (validIndirect[MD_LEFT])
        amvpCand[num++] = indirectMV[MD_LEFT];

    bool bAddedSmvp = num > 0;

    // Above predictor search
    if (validDirect[MD_ABOVE_RIGHT])
        amvpCand[num++] = directMV[MD_ABOVE_RIGHT];
    else if (validDirect[MD_ABOVE])
        amvpCand[num++] = directMV[MD_ABOVE];
    else if (validDirect[MD_ABOVE_LEFT])
        amvpCand[num++] = directMV[MD_ABOVE_LEFT];

    if (!bAddedSmvp)
    {
        if (validIndirect[MD_ABOVE_RIGHT])
            amvpCand[num++] = indirectMV[MD_ABOVE_RIGHT];
        else if (validIndirect[MD_ABOVE])
            amvpCand[num++] = indirectMV[MD_ABOVE];
        else if (validIndirect[MD_ABOVE_LEFT])
            amvpCand[num++] = indirectMV[MD_ABOVE_LEFT];
    }

    int numMvc = 0;
    for (int dir = MD_LEFT; dir <= MD_ABOVE_LEFT; dir++)
    {
        if (validDirect[dir] && directMV[dir].notZero())
            pmv[numMvc++] = directMV[dir];

        if (validIndirect[dir] && indirectMV[dir].notZero())
            pmv[numMvc++] = indirectMV[dir];
    }

    if (num == 2)
        num -= amvpCand[0] == amvpCand[1];

    // Get the collocated candidate. At this step, either the first candidate
    // was found or its value is 0.
    if (m_slice->m_sps->bTemporalMVPEnabled && num < 2)
    {
        int tempRefIdx = neighbours[MD_COLLOCATED].refIdx[picList];
        if (tempRefIdx != -1)
        {
            uint32_t cuAddr = neighbours[MD_COLLOCATED].cuAddr[picList];
            const Frame* colPic = m_slice->m_refPicList[m_slice->isInterB() && !m_slice->m_colFromL0Flag][m_slice->m_colRefIdx];
            const CUData* colCU = colPic->m_encData->getPicCTU(cuAddr);

            // Scale the vector
            int colRefPOC = colCU->m_slice->m_refPOCList[tempRefIdx >> 4][tempRefIdx & 0xf];
            int colPOC = colCU->m_slice->m_poc;

            int curRefPOC = m_slice->m_refPOCList[picList][refIdx];
            int curPOC = m_slice->m_poc;

            pmv[numMvc++] = amvpCand[num++] = scaleMvByPOCDist(neighbours[MD_COLLOCATED].mv[picList], curPOC, curRefPOC, colPOC, colRefPOC);
        }
    }

    while (num < AMVP_NUM_CANDS)
        amvpCand[num++] = 0;

    return numMvc;
}

/* Constructs a list of candidates for AMVP, and a larger list of motion candidates */
void CUData::getNeighbourMV(uint32_t puIdx, uint32_t absPartIdx, InterNeighbourMV* neighbours) const
{
    // Set the temporal neighbour to unavailable by default.
    neighbours[MD_COLLOCATED].unifiedRef = -1;

    uint32_t partIdxLT, partIdxRT, partIdxLB = deriveLeftBottomIdx(puIdx);
    deriveLeftRightTopIdx(puIdx, partIdxLT, partIdxRT);

    // Load the spatial MVs.
    getInterNeighbourMV(neighbours + MD_BELOW_LEFT, partIdxLB, MD_BELOW_LEFT);
    getInterNeighbourMV(neighbours + MD_LEFT,       partIdxLB, MD_LEFT);
    getInterNeighbourMV(neighbours + MD_ABOVE_RIGHT,partIdxRT, MD_ABOVE_RIGHT);
    getInterNeighbourMV(neighbours + MD_ABOVE,      partIdxRT, MD_ABOVE);
    getInterNeighbourMV(neighbours + MD_ABOVE_LEFT, partIdxLT, MD_ABOVE_LEFT);

    if (m_slice->m_sps->bTemporalMVPEnabled)
    {
        uint32_t absPartAddr = m_absIdxInCTU + absPartIdx;
        uint32_t partIdxRB = deriveRightBottomIdx(puIdx);

        // co-located RightBottom temporal predictor (H)
        int ctuIdx = -1;

        // image boundary check
        if (m_encData->getPicCTU(m_cuAddr)->m_cuPelX + g_zscanToPelX[partIdxRB] + UNIT_SIZE < m_slice->m_sps->picWidthInLumaSamples &&
            m_encData->getPicCTU(m_cuAddr)->m_cuPelY + g_zscanToPelY[partIdxRB] + UNIT_SIZE < m_slice->m_sps->picHeightInLumaSamples)
        {
            uint32_t absPartIdxRB = g_zscanToRaster[partIdxRB];
            uint32_t numUnits = s_numPartInCUSize;
            bool bNotLastCol = lessThanCol(absPartIdxRB, numUnits - 1, numUnits); // is not at the last column of CTU
            bool bNotLastRow = lessThanRow(absPartIdxRB, numUnits - 1, numUnits); // is not at the last row    of CTU

            if (bNotLastCol && bNotLastRow)
            {
                absPartAddr = g_rasterToZscan[absPartIdxRB + numUnits + 1];
                ctuIdx = m_cuAddr;
            }
            else if (bNotLastCol)
                absPartAddr = g_rasterToZscan[(absPartIdxRB + numUnits + 1) & (numUnits - 1)];
            else if (bNotLastRow)
            {
                absPartAddr = g_rasterToZscan[absPartIdxRB + 1];
                ctuIdx = m_cuAddr + 1;
            }
            else // is the right bottom corner of CTU
                absPartAddr = 0;
        }

        if (!(ctuIdx >= 0 && getCollocatedMV(ctuIdx, absPartAddr, neighbours + MD_COLLOCATED)))
        {
            uint32_t partIdxCenter =  deriveCenterIdx(puIdx);
            uint32_t curCTUIdx = m_cuAddr;
            getCollocatedMV(curCTUIdx, partIdxCenter, neighbours + MD_COLLOCATED);
        }
    }
}

void CUData::getInterNeighbourMV(InterNeighbourMV *neighbour, uint32_t partUnitIdx, MVP_DIR dir) const
{
    const CUData* tmpCU = NULL;
    uint32_t idx = 0;

    switch (dir)
    {
    case MD_LEFT:
        tmpCU = getPULeft(idx, partUnitIdx);
        break;
    case MD_ABOVE:
        tmpCU = getPUAbove(idx, partUnitIdx);
        break;
    case MD_ABOVE_RIGHT:
        tmpCU = getPUAboveRight(idx, partUnitIdx);
        break;
    case MD_BELOW_LEFT:
        tmpCU = getPUBelowLeft(idx, partUnitIdx);
        break;
    case MD_ABOVE_LEFT:
        tmpCU = getPUAboveLeft(idx, partUnitIdx);
        break;
    default:
        break;
    }

    if (!tmpCU)
    {
        // Mark the PMV as unavailable.
        for (int i = 0; i < 2; i++)
            neighbour->refIdx[i] = -1;
        return;
    }

    for (int i = 0; i < 2; i++)
    {
        // Get the MV.
        neighbour->mv[i] = tmpCU->m_mv[i][idx];

        // Get the reference idx.
        neighbour->refIdx[i] = tmpCU->m_refIdx[i][idx];
    }
}

/* Clip motion vector to within slightly padded boundary of picture (the
 * MV may reference a block that is completely within the padded area).
 * Note this function is unaware of how much of this picture is actually
 * available for use (re: frame parallelism) */
void CUData::clipMv(MV& outMV) const
{
    const uint32_t mvshift = 2;
    uint32_t offset = 8;

    int16_t xmax = (int16_t)((m_slice->m_sps->picWidthInLumaSamples + offset - m_cuPelX - 1) << mvshift);
    int16_t xmin = -(int16_t)((g_maxCUSize + offset + m_cuPelX - 1) << mvshift);

    int16_t ymax = (int16_t)((m_slice->m_sps->picHeightInLumaSamples + offset - m_cuPelY - 1) << mvshift);
    int16_t ymin = -(int16_t)((g_maxCUSize + offset + m_cuPelY - 1) << mvshift);

    outMV.x = X265_MIN(xmax, X265_MAX(xmin, outMV.x));
    outMV.y = X265_MIN(ymax, X265_MAX(ymin, outMV.y));
}

// Load direct spatial MV if available.
bool CUData::getDirectPMV(MV& pmv, InterNeighbourMV *neighbours, uint32_t picList, uint32_t refIdx) const
{
    int curRefPOC = m_slice->m_refPOCList[picList][refIdx];
    for (int i = 0; i < 2; i++, picList = !picList)
    {
        int partRefIdx = neighbours->refIdx[picList];
        if (partRefIdx >= 0 && curRefPOC == m_slice->m_refPOCList[picList][partRefIdx])
        {
            pmv = neighbours->mv[picList];
            return true;
        }
    }
    return false;
}

// Load indirect spatial MV if available. An indirect MV has to be scaled.
bool CUData::getIndirectPMV(MV& outMV, InterNeighbourMV *neighbours, uint32_t picList, uint32_t refIdx) const
{
    int curPOC = m_slice->m_poc;
    int neibPOC = curPOC;
    int curRefPOC = m_slice->m_refPOCList[picList][refIdx];

    for (int i = 0; i < 2; i++, picList = !picList)
    {
        int partRefIdx = neighbours->refIdx[picList];
        if (partRefIdx >= 0)
        {
            int neibRefPOC = m_slice->m_refPOCList[picList][partRefIdx];
            MV mvp = neighbours->mv[picList];

            outMV = scaleMvByPOCDist(mvp, curPOC, curRefPOC, neibPOC, neibRefPOC);
            return true;
        }
    }
    return false;
}

bool CUData::getColMVP(MV& outMV, int& outRefIdx, int picList, int cuAddr, int partUnitIdx) const
{
    const Frame* colPic = m_slice->m_refPicList[m_slice->isInterB() && !m_slice->m_colFromL0Flag][m_slice->m_colRefIdx];
    const CUData* colCU = colPic->m_encData->getPicCTU(cuAddr);

    uint32_t absPartAddr = partUnitIdx & TMVP_UNIT_MASK;
    if (colCU->m_predMode[partUnitIdx] == MODE_NONE || colCU->isIntra(absPartAddr))
        return false;

    int colRefPicList = m_slice->m_bCheckLDC ? picList : m_slice->m_colFromL0Flag;

    int colRefIdx = colCU->m_refIdx[colRefPicList][absPartAddr];

    if (colRefIdx < 0)
    {
        colRefPicList = !colRefPicList;
        colRefIdx = colCU->m_refIdx[colRefPicList][absPartAddr];

        if (colRefIdx < 0)
            return false;
    }

    // Scale the vector
    int colRefPOC = colCU->m_slice->m_refPOCList[colRefPicList][colRefIdx];
    int colPOC = colCU->m_slice->m_poc;
    MV colmv = colCU->m_mv[colRefPicList][absPartAddr];

    int curRefPOC = m_slice->m_refPOCList[picList][outRefIdx];
    int curPOC = m_slice->m_poc;

    outMV = scaleMvByPOCDist(colmv, curPOC, curRefPOC, colPOC, colRefPOC);
    return true;
}

// Cache the collocated MV.
bool CUData::getCollocatedMV(int cuAddr, int partUnitIdx, InterNeighbourMV *neighbour) const
{
    const Frame* colPic = m_slice->m_refPicList[m_slice->isInterB() && !m_slice->m_colFromL0Flag][m_slice->m_colRefIdx];
    const CUData* colCU = colPic->m_encData->getPicCTU(cuAddr);

    uint32_t absPartAddr = partUnitIdx & TMVP_UNIT_MASK;
    if (colCU->m_predMode[partUnitIdx] == MODE_NONE || colCU->isIntra(absPartAddr))
        return false;

    for (int list = 0; list < 2; list++)
    {
        neighbour->cuAddr[list] = cuAddr;
        int colRefPicList = m_slice->m_bCheckLDC ? list : m_slice->m_colFromL0Flag;
        int colRefIdx = colCU->m_refIdx[colRefPicList][absPartAddr];

        if (colRefIdx < 0)
            colRefPicList = !colRefPicList;

        neighbour->refIdx[list] = colCU->m_refIdx[colRefPicList][absPartAddr];
        neighbour->refIdx[list] |= colRefPicList << 4;

        neighbour->mv[list] = colCU->m_mv[colRefPicList][absPartAddr];
    }

    return neighbour->unifiedRef != -1;
}

MV CUData::scaleMvByPOCDist(const MV& inMV, int curPOC, int curRefPOC, int colPOC, int colRefPOC) const
{
    int diffPocD = colPOC - colRefPOC;
    int diffPocB = curPOC - curRefPOC;

    if (diffPocD == diffPocB)
        return inMV;
    else
    {
        int tdb   = x265_clip3(-128, 127, diffPocB);
        int tdd   = x265_clip3(-128, 127, diffPocD);
        int x     = (0x4000 + abs(tdd / 2)) / tdd;
        int scale = x265_clip3(-4096, 4095, (tdb * x + 32) >> 6);
        return scaleMv(inMV, scale);
    }
}

uint32_t CUData::deriveCenterIdx(uint32_t puIdx) const
{
    uint32_t absPartIdx;
    int puWidth, puHeight;

    getPartIndexAndSize(puIdx, absPartIdx, puWidth, puHeight);

    return g_rasterToZscan[g_zscanToRaster[m_absIdxInCTU + absPartIdx]
                           + (puHeight >> (LOG2_UNIT_SIZE + 1)) * s_numPartInCUSize
                           + (puWidth  >> (LOG2_UNIT_SIZE + 1))];
}

/** 函数功能       :?得到TU的熵编码参数,主要用于获取扫描方式。
 **                  HEVC中对尺寸小的TU(Luma 8x8/4x4, Chroma 4x4/2x2),使用模式依赖的模式选择(Mode Dependent Coefficient Scanning, MDCS)
* \参数 result     :返回的熵编码参数
* \参数 absPartIdx :当前PU在当前CU下的zigzag偏移地址
* \参数 log2TrSize :TU尺寸
* \参数 bIsLuma    :当前分量是否为亮度
**/
void CUData::getTUEntropyCodingParameters(TUEntropyCodingParameters &result, uint32_t absPartIdx, uint32_t log2TrSize, bool bIsLuma) const
{
    bool bIsIntra = isIntra(absPartIdx); // 判断是否是Intra预测

    // set the group layout
    result.log2TrSizeCG = log2TrSize - 2; // 得到TU按照CG为单位计算的尺寸

    // set the scan orders
    if (bIsIntra) // 如果是Intra
    {
        uint32_t dirMode;

        if (bIsLuma) // 如果是Luma,直接得到Luma的预测方向
            dirMode = m_lumaIntraDir[absPartIdx];
        else // 否则,找到chroma的预测方向
        {
            dirMode = m_chromaIntraDir[absPartIdx]; // 得到chroma的预测方向
            if (dirMode == DM_CHROMA_IDX) // 如果是DM模式(即直接使用Luma的预测方向),则需要找到相应的Luma分量所选择的预测方向
            {
                dirMode = m_lumaIntraDir[(m_chromaFormat == X265_CSP_I444) ? absPartIdx : absPartIdx & 0xFC]; // 得到对应亮度块的预测方向,对Yuv444和Yuv422,需要得到其对应预测方向
                dirMode = (m_chromaFormat == X265_CSP_I422) ? g_chroma422IntraAngleMappingTable[dirMode] : dirMode;
            }
        }
        // 尺寸小的TU(Luma 8x8/4x4, Chroma 4x4/2x2)根据预测方向来选择扫描方式
        // MDCS_LOG2_MAX_SIZE = 3,对于Luma分量m_hChromaShift=0,所以就是log2TrSize<=3(即TU size<=8x8)则可以进行MDCS的操作
        // 对于Chroma分量m_hChromaShift=1,所以log2TrSize<=2(即TU size<=4x4)可以进行MDCS的操作
        // MDCS根据预测方向选择扫描方式,如果预测方向是竖直方向或其临近方向则使用水平扫描,如果预测方向是水平方向或其临近方向则使用竖直扫描方式
        if (log2TrSize <= (MDCS_LOG2_MAX_SIZE - m_hChromaShift) || (bIsLuma && log2TrSize == MDCS_LOG2_MAX_SIZE))
            result.scanType = dirMode >= 22 && dirMode <= 30 ? SCAN_HOR : dirMode >= 6 && dirMode <= 14 ? SCAN_VER : SCAN_DIAG;
        else // 如果不满足MDCS的条件,则使用对角扫描方式
            result.scanType = SCAN_DIAG;
    }
    else // inter预测模式都使用对角扫描方式
        result.scanType = SCAN_DIAG;

    result.scan     = g_scanOrder[result.scanType][log2TrSize - 2]; // 根据扫描类型和TU尺寸得到系数的扫描顺序表
    result.scanCG   = g_scanOrderCG[result.scanType][result.log2TrSizeCG]; // 根据扫描类型和TU尺寸得到系数组CG的扫描顺序表

    // 得到第一个非零系数的context下标
    if (log2TrSize == 2)
        result.firstSignificanceMapContext = 0;
    else if (log2TrSize == 3)
        result.firstSignificanceMapContext = (result.scanType != SCAN_DIAG && bIsLuma) ? 15 : 9;
    else
        result.firstSignificanceMapContext = bIsLuma ? 21 : 12;
}

#define CU_SET_FLAG(bitfield, flag, value) (bitfield) = ((bitfield) & (~(flag))) | ((~((value) - 1)) & (flag))  //设置geom falg  第一步清除当前标记位   第二步 设置当前标记位
/** 函数功能       : 计算CU的几何信息
/*  调用范围       : 只在FrameEncoder::initializeGeoms()函数中被调用
* \参数 ctuWidth   : 宽度的余数
* \参数 ctuHeight  : 高度的余数
* \参数 maxCUSize  : 最大CU
* \参数 minCUSize  : 最小CU
* \参数 cuDataArray: 存储位置
*   返回值         : null
**/
void CUData::calcCTUGeoms(uint32_t ctuWidth, uint32_t ctuHeight, uint32_t maxCUSize, uint32_t minCUSize, CUGeom cuDataArray[CUGeom::MAX_GEOMS])
{
    // Initialize the coding blocks inside the CTB
    for (uint32_t log2CUSize = g_log2Size[maxCUSize], rangeCUIdx = 0; log2CUSize >= g_log2Size[minCUSize]; log2CUSize--) //从最大CU遍历到最小CU
    {
        uint32_t blockSize = 1 << log2CUSize; //当前的块大小
        uint32_t sbWidth   = 1 << (g_log2Size[maxCUSize] - log2CUSize);//最大CU下有宽度上有几个当前块大小 如:64 :1 32 :2 16:4 8:8
        int32_t lastLevelFlag = log2CUSize == g_log2Size[minCUSize];//判断当前位置是否为最小CU

        for (uint32_t sbY = 0; sbY < sbWidth; sbY++) //按行遍历
        {
            for (uint32_t sbX = 0; sbX < sbWidth; sbX++)//遍历当前行的每个块
            {
                uint32_t depthIdx = g_depthScanIdx[sbY][sbX];//获取当前的zigzag号
                uint32_t cuIdx = rangeCUIdx + depthIdx;//当前在geom的存储位置
                uint32_t childIdx = rangeCUIdx + sbWidth * sbWidth + (depthIdx << 2);//对应位置子块在geom的存储位置
                uint32_t px = sbX * blockSize;//在CTU中的pixel地址
                uint32_t py = sbY * blockSize;//在CTU中的pixel地址
                int32_t presentFlag = px < ctuWidth && py < ctuHeight;//判断当前块左上角像素是否在图像内部
                int32_t splitMandatoryFlag = presentFlag && !lastLevelFlag && (px + blockSize > ctuWidth || py + blockSize > ctuHeight);//在图像内部 不是最小CU CU超过边界  
                
                /* Offset of the luma CU in the X, Y direction in terms of pixels from the CTU origin */
                uint32_t xOffset = (sbX * blockSize) >> 3;
                uint32_t yOffset = (sbY * blockSize) >> 3;
                X265_CHECK(cuIdx < CUGeom::MAX_GEOMS, "CU geom index bug\n");

                CUGeom *cu = cuDataArray + cuIdx;//获取存储位置
                cu->log2CUSize = log2CUSize;//记录当前块大小
                cu->childOffset = childIdx - cuIdx;//示从当前位置到第一个子cU的偏移量
                cu->absPartIdx = g_depthScanIdx[yOffset][xOffset] * 4;// 当前CU在LCU中4x4 zizag地址
                cu->numPartitions = (NUM_4x4_PARTITIONS >> ((g_maxLog2CUSize - cu->log2CUSize) * 2)); // 当前CU有多少4x4块
                cu->depth = g_log2Size[maxCUSize] - log2CUSize;// 当前CU的深度

                cu->flags = 0;
                CU_SET_FLAG(cu->flags, CUGeom::PRESENT, presentFlag);//记录是否有PRESENT
                CU_SET_FLAG(cu->flags, CUGeom::SPLIT_MANDATORY | CUGeom::SPLIT, splitMandatoryFlag);//记录 SPLIT_MANDATORY SPLIT
                CU_SET_FLAG(cu->flags, CUGeom::LEAF, lastLevelFlag);//记录LEAF
            }
        }
        rangeCUIdx += sbWidth * sbWidth;//用于计算每个块在geom的位置
    }
}


/openssl.c:1298:3: warning: ‘ENGINE_init’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations] 1298 | if(!ENGINE_init(e)) { | ^~ /usr/include/openssl/engine.h:620:27: note: declared here 620 | OSSL_DEPRECATEDIN_3_0 int ENGINE_init(ENGINE *e); | ^~~~~~~~~~~ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:1301:5: warning: ‘ENGINE_free’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations] 1301 | ENGINE_free(e); | ^~~~~~~~~~~ /usr/include/openssl/engine.h:493:27: note: declared here 493 | OSSL_DEPRECATEDIN_3_0 int ENGINE_free(ENGINE *e); | ^~~~~~~~~~~ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c: In function ‘ossl_set_engine_default’: /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:1321:5: warning: ‘ENGINE_set_default’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations] 1321 | if(ENGINE_set_default(data->state.engine, ENGINE_METHOD_ALL) > 0) { | ^~ /usr/include/openssl/engine.h:708:27: note: declared here 708 | OSSL_DEPRECATEDIN_3_0 int ENGINE_set_default(ENGINE *e, unsigned int flags); | ^~~~~~~~~~~~~~~~~~ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:1323:13: warning: ‘ENGINE_get_id’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations] 1323 | ENGINE_get_id(data->state.engine)); | ^~~~~~~~~~~~~ /usr/include/openssl/engine.h:552:35: note: declared here 552 | OSSL_DEPRECATEDIN_3_0 const char *ENGINE_get_id(const ENGINE *e); | ^~~~~~~~~~~~~ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:1327:13: warning: ‘ENGINE_get_id’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations] 1327 | ENGINE_get_id(data->state.engine)); | ^~~~~~~~~~~~~ /usr/include/openssl/engine.h:552:35: note: declared here 552 | OSSL_DEPRECATEDIN_3_0 const char *ENGINE_get_id(const ENGINE *e); | ^~~~~~~~~~~~~ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c: In function ‘ossl_engines_list’: /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:1346:3: warning: ‘ENGINE_get_first’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations] 1346 | for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) { | ^~~ /usr/include/openssl/engine.h:318:31: note: declared here 318 | OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_get_first(void); | ^~~~~~~~~~~~~~~~ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:1346:3: warning: ‘ENGINE_get_next’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations] 1346 | for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) { | ^~~ /usr/include/openssl/engine.h:323:31: note: declared here 323 | OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_get_next(ENGINE *e); | ^~~~~~~~~~~~~~~ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:1347:5: warning: ‘ENGINE_get_id’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations] 1347 | beg = curl_slist_append(list, ENGINE_get_id(e)); | ^~~ /usr/include/openssl/engine.h:552:35: note: declared here 552 | OSSL_DEPRECATEDIN_3_0 const char *ENGINE_get_id(const ENGINE *e); | ^~~~~~~~~~~~~ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c: In function ‘ossl_close_all’: /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:1507:5: warning: ‘ENGINE_finish’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations] 1507 | ENGINE_finish(data->state.engine); | ^~~~~~~~~~~~~ /usr/include/openssl/engine.h:628:27: note: declared here 628 | OSSL_DEPRECATEDIN_3_0 int ENGINE_finish(ENGINE *e); | ^~~~~~~~~~~~~ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:1508:5: warning: ‘ENGINE_free’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations] 1508 | ENGINE_free(data->state.engine); | ^~~~~~~~~~~ /usr/include/openssl/engine.h:493:27: note: declared here 493 | OSSL_DEPRECATEDIN_3_0 int ENGINE_free(ENGINE *e); | ^~~~~~~~~~~ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c: In function ‘get_cert_chain’: /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:3627:9: warning: ‘EVP_PKEY_get0_RSA’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations] 3627 | rsa = EVP_PKEY_get0_RSA(pubkey); | ^~~ /usr/include/openssl/evp.h:1348:22: note: declared here 1348 | const struct rsa_st *EVP_PKEY_get0_RSA(const EVP_PKEY *pkey); | ^~~~~~~~~~~~~~~~~ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:3627:13: warning: assignment discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers] 3627 | rsa = EVP_PKEY_get0_RSA(pubkey); | ^ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:3637:11: warning: ‘RSA_get0_key’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations] 3637 | RSA_get0_key(rsa, &n, &e, NULL); | ^~~~~~~~~~~~ /usr/include/openssl/rsa.h:217:28: note: declared here 217 | OSSL_DEPRECATEDIN_3_0 void RSA_get0_key(const RSA *r, | ^~~~~~~~~~~~ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:3657:9: warning: ‘EVP_PKEY_get0_DSA’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations] 3657 | dsa = EVP_PKEY_get0_DSA(pubkey); | ^~~ /usr/include/openssl/evp.h:1357:22: note: declared here 1357 | const struct dsa_st *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey); | ^~~~~~~~~~~~~~~~~ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:3657:13: warning: assignment discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers] 3657 | dsa = EVP_PKEY_get0_DSA(pubkey); | ^ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:3668:11: warning: ‘DSA_get0_pqg’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations] 3668 | DSA_get0_pqg(dsa, &p, &q, &g); | ^~~~~~~~~~~~ In file included from /usr/include/openssl/x509.h:37: /usr/include/openssl/dsa.h:201:28: note: declared here 201 | OSSL_DEPRECATEDIN_3_0 void DSA_get0_pqg(const DSA *d, const BIGNUM **p, | ^~~~~~~~~~~~ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:3669:11: warning: ‘DSA_get0_key’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations] 3669 | DSA_get0_key(dsa, &pub_key, NULL); | ^~~~~~~~~~~~ /usr/include/openssl/dsa.h:204:28: note: declared here 204 | OSSL_DEPRECATEDIN_3_0 void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, | ^~~~~~~~~~~~ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:3689:9: warning: ‘EVP_PKEY_get0_DH’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations] 3689 | dh = EVP_PKEY_get0_DH(pubkey); | ^~ /usr/include/openssl/evp.h:1365:43: note: declared here 1365 | OSSL_DEPRECATEDIN_3_0 const struct dh_st *EVP_PKEY_get0_DH(const EVP_PKEY *pkey); | ^~~~~~~~~~~~~~~~ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:3689:12: warning: assignment discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers] 3689 | dh = EVP_PKEY_get0_DH(pubkey); | ^ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:3699:11: warning: ‘DH_get0_pqg’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations] 3699 | DH_get0_pqg(dh, &p, &q, &g); | ^~~~~~~~~~~ In file included from /usr/include/openssl/dsa.h:51: /usr/include/openssl/dh.h:257:28: note: declared here 257 | OSSL_DEPRECATEDIN_3_0 void DH_get0_pqg(const DH *dh, const BIGNUM **p, | ^~~~~~~~~~~ /home/hxwang/realsense_build/librealsense-master/build/third-party/libcurl/lib/vtls/openssl.c:3700:11: warning: ‘DH_get0_key’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations] 3700 | DH_get0_key(dh, &pub_key, NULL); | ^~~~~~~~~~~ /usr/include/openssl/dh.h:260:28: note: declared here 260 | OSSL_DEPRECATEDIN_3_0 void DH_get0_key(const DH *dh, const BIGNUM **pub_key, | ^~~~~~~~~~~ [ 92%] Building C object lib/CMakeFiles/libcurl.dir/vtls/schannel.c.o [ 93%] Building C object lib/CMakeFiles/libcurl.dir/vtls/schannel_verify.c.o [ 94%] Building C object lib/CMakeFiles/libcurl.dir/vtls/sectransp.c.o [ 94%] Building C object lib/CMakeFiles/libcurl.dir/vtls/vtls.c.o [ 95%] Building C object lib/CMakeFiles/libcurl.dir/vtls/wolfssl.c.o [ 96%] Building C object lib/CMakeFiles/libcurl.dir/vquic/ngtcp2.c.o [ 96%] Building C object lib/CMakeFiles/libcurl.dir/vquic/quiche.c.o [ 97%] Building C object lib/CMakeFiles/libcurl.dir/vquic/vquic.c.o [ 98%] Building C object lib/CMakeFiles/libcurl.dir/vssh/libssh.c.o [ 98%] Building C object lib/CMakeFiles/libcurl.dir/vssh/libssh2.c.o [ 99%] Building C object lib/CMakeFiles/libcurl.dir/vssh/wolfssh.c.o [100%] Linking C static library libcurl.a [100%] Built target libcurl [ 5%] Performing install step for 'libcurl' [100%] Built target libcurl Install the project... -- Install configuration: "Release" -- Installing: /home/hxwang/realsense_build/librealsense-master/build/libcurl/libcurl_install/lib/libcurl.a -- Installing: /home/hxwang/realsense_build/librealsense-master/build/libcurl/libcurl_install/bin/curl-config -- Installing: /home/hxwang/realsense_build/librealsense-master/build/libcurl/libcurl_install/lib/pkgconfig/libcurl.pc -- Installing: /home/hxwang/realsense_build/librealsense-master/build/libcurl/libcurl_install/include/curl -- Installing: /home/hxwang/realsense_build/librealsense-master/build/libcurl/libcurl_install/include/curl/curl.h -- Installing: /home/hxwang/realsense_build/librealsense-master/build/libcurl/libcurl_install/include/curl/typecheck-gcc.h -- Installing: /home/hxwang/realsense_build/librealsense-master/build/libcurl/libcurl_install/include/curl/options.h -- Installing: /home/hxwang/realsense_build/librealsense-master/build/libcurl/libcurl_install/include/curl/curlver.h -- Installing: /home/hxwang/realsense_build/librealsense-master/build/libcurl/libcurl_install/include/curl/stdcheaders.h -- Installing: /home/hxwang/realsense_build/librealsense-master/build/libcurl/libcurl_install/include/curl/mprintf.h -- Installing: /home/hxwang/realsense_build/librealsense-master/build/libcurl/libcurl_install/include/curl/urlapi.h -- Installing: /home/hxwang/realsense_build/librealsense-master/build/libcurl/libcurl_install/include/curl/multi.h -- Installing: /home/hxwang/realsense_build/librealsense-master/build/libcurl/libcurl_install/include/curl/easy.h -- Installing: /home/hxwang/realsense_build/librealsense-master/build/libcurl/libcurl_install/include/curl/system.h -- Installing: /home/hxwang/realsense_build/librealsense-master/build/libcurl/libcurl_install/lib/cmake/CURL/CURLTargets.cmake -- Installing: /home/hxwang/realsense_build/librealsense-master/build/libcurl/libcurl_install/lib/cmake/CURL/CURLTargets-release.cmake -- Installing: /home/hxwang/realsense_build/librealsense-master/build/libcurl/libcurl_install/lib/cmake/CURL/CURLConfigVersion.cmake -- Installing: /home/hxwang/realsense_build/librealsense-master/build/libcurl/libcurl_install/lib/cmake/CURL/CURLConfig.cmake [ 5%] No test step for 'libcurl' [ 5%] Completed 'libcurl' [ 5%] Built target libcurl [ 5%] Building C object third-party/realsense-file/CMakeFiles/realsense-file.dir/lz4/lz4.c.o [ 5%] Building CXX object third-party/realsense-file/CMakeFiles/realsense-file.dir/rosbag/console_bridge/src/console.cpp.o [ 5%] Building CXX object third-party/realsense-file/CMakeFiles/realsense-file.dir/rosbag/cpp_common/src/debug.cpp.o [ 6%] Building CXX object third-party/realsense-file/CMakeFiles/realsense-file.dir/rosbag/cpp_common/src/header.cpp.o [ 6%] Building CXX object third-party/realsense-file/CMakeFiles/realsense-file.dir/rosbag/rosbag_storage/src/bag.cpp.o [ 6%] Building CXX object third-party/realsense-file/CMakeFiles/realsense-file.dir/rosbag/rosbag_storage/src/bag_player.cpp.o [ 6%] Building CXX object third-party/realsense-file/CMakeFiles/realsense-file.dir/rosbag/rosbag_storage/src/buffer.cpp.o [ 7%] Building CXX object third-party/realsense-file/CMakeFiles/realsense-file.dir/rosbag/rosbag_storage/src/chunked_file.cpp.o [ 7%] Building CXX object third-party/realsense-file/CMakeFiles/realsense-file.dir/rosbag/rosbag_storage/src/lz4_stream.cpp.o [ 7%] Building CXX object third-party/realsense-file/CMakeFiles/realsense-file.dir/rosbag/rosbag_storage/src/message_instance.cpp.o [ 7%] Building CXX object third-party/realsense-file/CMakeFiles/realsense-file.dir/rosbag/rosbag_storage/src/query.cpp.o [ 8%] Building CXX object third-party/realsense-file/CMakeFiles/realsense-file.dir/rosbag/rosbag_storage/src/stream.cpp.o [ 8%] Building CXX object third-party/realsense-file/CMakeFiles/realsense-file.dir/rosbag/rosbag_storage/src/uncompressed_stream.cpp.o [ 8%] Building CXX object third-party/realsense-file/CMakeFiles/realsense-file.dir/rosbag/rosbag_storage/src/view.cpp.o [ 8%] Building CXX object third-party/realsense-file/CMakeFiles/realsense-file.dir/rosbag/roscpp_serialization/src/serialization.cpp.o [ 9%] Building C object third-party/realsense-file/CMakeFiles/realsense-file.dir/rosbag/roslz4/src/lz4s.c.o [ 9%] Building C object third-party/realsense-file/CMakeFiles/realsense-file.dir/rosbag/roslz4/src/xxhash.c.o [ 9%] Building CXX object third-party/realsense-file/CMakeFiles/realsense-file.dir/rosbag/rostime/src/duration.cpp.o [ 9%] Building CXX object third-party/realsense-file/CMakeFiles/realsense-file.dir/rosbag/rostime/src/rate.cpp.o [ 10%] Building CXX object third-party/realsense-file/CMakeFiles/realsense-file.dir/rosbag/rostime/src/time.cpp.o [ 10%] Linking CXX static library ../../Release/librealsense-file.a [ 10%] Built target realsense-file [ 10%] Building CXX object third-party/rsutils/CMakeFiles/rsutils.dir/__/easyloggingpp/src/easylogging++.cc.o [ 10%] Building CXX object third-party/rsutils/CMakeFiles/rsutils.dir/src/configure-elpp-logger.cpp.o [ 11%] Building CXX object third-party/rsutils/CMakeFiles/rsutils.dir/src/crc32.cpp.o [ 11%] Building CXX object third-party/rsutils/CMakeFiles/rsutils.dir/src/dispatcher.cpp.o [ 11%] Building CXX object third-party/rsutils/CMakeFiles/rsutils.dir/src/ensure-console.cpp.o [ 11%] Building CXX object third-party/rsutils/CMakeFiles/rsutils.dir/src/executable-name.cpp.o [ 12%] Building CXX object third-party/rsutils/CMakeFiles/rsutils.dir/src/float3.cpp.o [ 12%] Building CXX object third-party/rsutils/CMakeFiles/rsutils.dir/src/from.cpp.o [ 12%] Building CXX object third-party/rsutils/CMakeFiles/rsutils.dir/src/hexarray.cpp.o [ 12%] Building CXX object third-party/rsutils/CMakeFiles/rsutils.dir/src/hexdump.cpp.o [ 13%] Building CXX object third-party/rsutils/CMakeFiles/rsutils.dir/src/ip-address.cpp.o [ 13%] Building CXX object third-party/rsutils/CMakeFiles/rsutils.dir/src/json.cpp.o [ 13%] Building CXX object third-party/rsutils/CMakeFiles/rsutils.dir/src/make-less-screamy.cpp.o [ 13%] Building CXX object third-party/rsutils/CMakeFiles/rsutils.dir/src/os.cpp.o [ 14%] Building CXX object third-party/rsutils/CMakeFiles/rsutils.dir/src/shorten-json-string.cpp.o [ 14%] Building CXX object third-party/rsutils/CMakeFiles/rsutils.dir/src/special-folder.cpp.o [ 14%] Building CXX object third-party/rsutils/CMakeFiles/rsutils.dir/src/version.cpp.o [ 14%] Building CXX object third-party/rsutils/CMakeFiles/rsutils.dir/src/work-week.cpp.o [ 15%] Linking CXX static library ../../Release/librsutils.a [ 15%] Built target rsutils [ 15%] Building CXX object CMakeFiles/realsense2.dir/src/core/matcher-factory.cpp.o [ 15%] Building CXX object CMakeFiles/realsense2.dir/src/core/notification.cpp.o [ 15%] Building CXX object CMakeFiles/realsense2.dir/src/core/options-container.cpp.o [ 16%] Building CXX object CMakeFiles/realsense2.dir/src/core/options-registry.cpp.o [ 16%] Building CXX object CMakeFiles/realsense2.dir/src/core/options-watcher.cpp.o [ 16%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d400/d400-options.cpp.o [ 16%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d400/d400-private.cpp.o [ 16%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d400/d400-motion.cpp.o [ 17%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d400/d400-nonmonochrome.cpp.o [ 17%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d400/d400-device.cpp.o [ 17%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d400/d400-color.cpp.o [ 17%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d400/d400-active.cpp.o [ 18%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d400/d400-factory.cpp.o [ 18%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d400/d400-fw-update-device.cpp.o [ 18%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d400/d400-auto-calibration.cpp.o [ 18%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d400/d400-thermal-monitor.cpp.o [ 19%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d500/d500-device.cpp.o [ 19%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d500/d500-color.cpp.o [ 19%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d500/d500-motion.cpp.o [ 19%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d500/d500-active.cpp.o [ 20%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d500/d500-private.cpp.o [ 20%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d500/d500-factory.cpp.o [ 20%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d500/hw_monitor_extended_buffers.cpp.o [ 20%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d500/d500-options.cpp.o [ 21%] Building CXX object CMakeFiles/realsense2.dir/src/ds/d500/d500-fw-update-device.cpp.o [ 21%] Building CXX object CMakeFiles/realsense2.dir/src/ds/ds-device-common.cpp.o [ 21%] Building CXX object CMakeFiles/realsense2.dir/src/ds/ds-motion-common.cpp.o [ 21%] Building CXX object CMakeFiles/realsense2.dir/src/ds/ds-color-common.cpp.o [ 22%] Building CXX object CMakeFiles/realsense2.dir/src/ds/ds-active-common.cpp.o [ 22%] Building CXX object CMakeFiles/realsense2.dir/src/ds/ds-private.cpp.o [ 22%] Building CXX object CMakeFiles/realsense2.dir/src/ds/ds-timestamp.cpp.o [ 22%] Building CXX object CMakeFiles/realsense2.dir/src/ds/ds-options.cpp.o [ 23%] Building CXX object CMakeFiles/realsense2.dir/src/ds/advanced_mode/rs_advanced_mode.cpp.o [ 23%] Building CXX object CMakeFiles/realsense2.dir/src/ds/advanced_mode/presets.cpp.o [ 23%] Building CXX object CMakeFiles/realsense2.dir/src/ds/advanced_mode/advanced_mode.cpp.o [ 23%] Building CXX object CMakeFiles/realsense2.dir/src/ds/ds-calib-parsers.cpp.o [ 24%] Building CXX object CMakeFiles/realsense2.dir/src/ds/features/amplitude-factor-feature.cpp.o [ 24%] Building CXX object CMakeFiles/realsense2.dir/src/ds/features/emitter-frequency-feature.cpp.o [ 24%] Building CXX object CMakeFiles/realsense2.dir/src/ds/features/auto-exposure-roi-feature.cpp.o [ 24%] Building CXX object CMakeFiles/realsense2.dir/src/ds/features/remove-ir-pattern-feature.cpp.o [ 25%] Building CXX object CMakeFiles/realsense2.dir/src/ds/features/auto-exposure-limit-feature.cpp.o [ 25%] Building CXX object CMakeFiles/realsense2.dir/src/ds/features/gain-limit-feature.cpp.o [ 25%] Building CXX object CMakeFiles/realsense2.dir/src/ds/features/gyro-sensitivity-feature.cpp.o [ 25%] Building CXX object CMakeFiles/realsense2.dir/src/media/record/record_device.cpp.o [ 26%] Building CXX object CMakeFiles/realsense2.dir/src/media/record/record_sensor.cpp.o [ 26%] Building CXX object CMakeFiles/realsense2.dir/src/media/playback/playback_device.cpp.o [ 26%] Building CXX object CMakeFiles/realsense2.dir/src/media/playback/playback_sensor.cpp.o [ 26%] Building CXX object CMakeFiles/realsense2.dir/src/media/ros/ros_reader.cpp.o [ 27%] Building CXX object CMakeFiles/realsense2.dir/src/media/ros/ros_writer.cpp.o [ 27%] Building CXX object CMakeFiles/realsense2.dir/src/proc/sse/sse-align.cpp.o [ 27%] Building CXX object CMakeFiles/realsense2.dir/src/proc/sse/sse-pointcloud.cpp.o [ 27%] Building CXX object CMakeFiles/realsense2.dir/src/proc/processing-blocks-factory.cpp.o [ 28%] Building CXX object CMakeFiles/realsense2.dir/src/proc/align.cpp.o [ 28%] Building CXX object CMakeFiles/realsense2.dir/src/proc/colorizer.cpp.o [ 28%] Building CXX object CMakeFiles/realsense2.dir/src/proc/pointcloud.cpp.o [ 28%] Building CXX object CMakeFiles/realsense2.dir/src/proc/occlusion-filter.cpp.o [ 29%] Building CXX object CMakeFiles/realsense2.dir/src/proc/synthetic-stream.cpp.o [ 29%] Building CXX object CMakeFiles/realsense2.dir/src/proc/syncer-processing-block.cpp.o [ 29%] Building CXX object CMakeFiles/realsense2.dir/src/proc/decimation-filter.cpp.o [ 29%] Building CXX object CMakeFiles/realsense2.dir/src/proc/spatial-filter.cpp.o [ 30%] Building CXX object CMakeFiles/realsense2.dir/src/proc/temporal-filter.cpp.o [ 30%] Building CXX object CMakeFiles/realsense2.dir/src/proc/hdr-merge.cpp.o [ 30%] Building CXX object CMakeFiles/realsense2.dir/src/proc/sequence-id-filter.cpp.o [ 30%] Building CXX object CMakeFiles/realsense2.dir/src/proc/hole-filling-filter.cpp.o [ 31%] Building CXX object CMakeFiles/realsense2.dir/src/proc/disparity-transform.cpp.o [ 31%] Building CXX object CMakeFiles/realsense2.dir/src/proc/y8i-to-y8y8.cpp.o [ 31%] Building CXX object CMakeFiles/realsense2.dir/src/proc/y12i-to-y16y16.cpp.o [ 31%] Building CXX object CMakeFiles/realsense2.dir/src/proc/y12i-to-y16y16-mipi.cpp.o [ 32%] Building CXX object CMakeFiles/realsense2.dir/src/proc/y16i-to-y10msby10msb.cpp.o [ 32%] Building CXX object CMakeFiles/realsense2.dir/src/proc/identity-processing-block.cpp.o [ 32%] Building CXX object CMakeFiles/realsense2.dir/src/proc/threshold.cpp.o [ 32%] Building CXX object CMakeFiles/realsense2.dir/src/proc/rates-printer.cpp.o [ 33%] Building CXX object CMakeFiles/realsense2.dir/src/proc/units-transform.cpp.o [ 33%] Building CXX object CMakeFiles/realsense2.dir/src/proc/rotation-transform.cpp.o [ 33%] Building CXX object CMakeFiles/realsense2.dir/src/proc/color-formats-converter.cpp.o [ 33%] Building CXX object CMakeFiles/realsense2.dir/src/proc/depth-formats-converter.cpp.o [ 34%] Building CXX object CMakeFiles/realsense2.dir/src/proc/motion-transform.cpp.o [ 34%] Building CXX object CMakeFiles/realsense2.dir/src/proc/auto-exposure-processor.cpp.o [ 34%] Building CXX object CMakeFiles/realsense2.dir/src/proc/y411-converter.cpp.o [ 34%] Building CXX object CMakeFiles/realsense2.dir/src/proc/formats-converter.cpp.o [ 35%] Building CXX object CMakeFiles/realsense2.dir/src/pipeline/pipeline.cpp.o [ 35%] Building CXX object CMakeFiles/realsense2.dir/src/pipeline/config.cpp.o [ 35%] Building CXX object CMakeFiles/realsense2.dir/src/pipeline/profile.cpp.o [ 35%] Building CXX object CMakeFiles/realsense2.dir/src/pipeline/aggregator.cpp.o [ 36%] Building CXX object CMakeFiles/realsense2.dir/src/fw-logs/fw-log-data.cpp.o [ 36%] Building CXX object CMakeFiles/realsense2.dir/src/fw-logs/fw-logs-formating-options.cpp.o [ 36%] Building CXX object CMakeFiles/realsense2.dir/src/fw-logs/fw-logs-parser.cpp.o [ 36%] Building CXX object CMakeFiles/realsense2.dir/src/fw-logs/fw-logs-xml-helper.cpp.o [ 37%] Building CXX object CMakeFiles/realsense2.dir/src/fw-logs/fw-string-formatter.cpp.o [ 37%] Building CXX object CMakeFiles/realsense2.dir/src/fw-update/fw-update-device.cpp.o [ 37%] Building CXX object CMakeFiles/realsense2.dir/src/fw-update/fw-update-factory.cpp.o [ 37%] Building CXX object CMakeFiles/realsense2.dir/src/fw-update/fw-update-unsigned.cpp.o [ 38%] Building CXX object CMakeFiles/realsense2.dir/src/libusb/context-libusb.cpp.o [ 38%] Building CXX object CMakeFiles/realsense2.dir/src/libusb/interface-libusb.cpp.o [ 38%] Building CXX object CMakeFiles/realsense2.dir/src/libusb/device-libusb.cpp.o [ 38%] Building CXX object CMakeFiles/realsense2.dir/src/libusb/messenger-libusb.cpp.o [ 39%] Building CXX object CMakeFiles/realsense2.dir/src/libusb/request-libusb.cpp.o [ 39%] Building CXX object CMakeFiles/realsense2.dir/src/libusb/enumerator-libusb.cpp.o [ 39%] Building CXX object CMakeFiles/realsense2.dir/src/hid/hid-device.cpp.o [ 39%] Building CXX object CMakeFiles/realsense2.dir/src/uvc/uvc-device.cpp.o [ 40%] Building CXX object CMakeFiles/realsense2.dir/src/uvc/uvc-parser.cpp.o [ 40%] Building CXX object CMakeFiles/realsense2.dir/src/uvc/uvc-streamer.cpp.o [ 40%] Building CXX object CMakeFiles/realsense2.dir/src/rsusb-backend/rsusb-backend.cpp.o [ 40%] Building CXX object CMakeFiles/realsense2.dir/src/libuvc/rsusb-backend-linux.cpp.o [ 41%] Building CXX object CMakeFiles/realsense2.dir/src/algo.cpp.o [ 41%] Building CXX object CMakeFiles/realsense2.dir/src/archive.cpp.o [ 41%] Building CXX object CMakeFiles/realsense2.dir/src/backend.cpp.o [ 41%] Building CXX object CMakeFiles/realsense2.dir/src/backend-device-factory.cpp.o [ 41%] Building CXX object CMakeFiles/realsense2.dir/src/context.cpp.o [ 42%] Building CXX object CMakeFiles/realsense2.dir/src/device.cpp.o [ 42%] Building CXX object CMakeFiles/realsense2.dir/src/device-info.cpp.o [ 42%] Building CXX object CMakeFiles/realsense2.dir/src/device_hub.cpp.o [ 42%] Building CXX object CMakeFiles/realsense2.dir/src/environment.cpp.o [ 43%] Building CXX object CMakeFiles/realsense2.dir/src/error-handling.cpp.o [ 43%] Building CXX object CMakeFiles/realsense2.dir/src/firmware_logger_device.cpp.o [ 43%] Building CXX object CMakeFiles/realsense2.dir/src/global_timestamp_reader.cpp.o [ 43%] Building CXX object CMakeFiles/realsense2.dir/src/hdr-config.cpp.o [ 44%] Building CXX object CMakeFiles/realsense2.dir/src/hw-monitor.cpp.o [ 44%] Building CXX object CMakeFiles/realsense2.dir/src/image.cpp.o [ 44%] Building CXX object CMakeFiles/realsense2.dir/src/image-avx.cpp.o [ 44%] Building CXX object CMakeFiles/realsense2.dir/src/log.cpp.o [ 45%] Building CXX object CMakeFiles/realsense2.dir/src/option.cpp.o [ 45%] Building CXX object CMakeFiles/realsense2.dir/src/platform-camera.cpp.o [ 45%] Building CXX object CMakeFiles/realsense2.dir/src/rs.cpp.o [ 45%] Building CXX object CMakeFiles/realsense2.dir/src/sensor.cpp.o [ 46%] Building CXX object CMakeFiles/realsense2.dir/src/hid-sensor.cpp.o [ 46%] Building CXX object CMakeFiles/realsense2.dir/src/uvc-sensor.cpp.o [ 46%] Building CXX object CMakeFiles/realsense2.dir/src/rscore-pp-block-factory.cpp.o [ 46%] Building CXX object CMakeFiles/realsense2.dir/src/software-device.cpp.o [ 47%] Building CXX object CMakeFiles/realsense2.dir/src/software-device-info.cpp.o [ 47%] Building CXX object CMakeFiles/realsense2.dir/src/software-sensor.cpp.o [ 47%] Building CXX object CMakeFiles/realsense2.dir/src/source.cpp.o [ 47%] Building CXX object CMakeFiles/realsense2.dir/src/stream.cpp.o [ 48%] Building CXX object CMakeFiles/realsense2.dir/src/sync.cpp.o /home/hxwang/realsense_build/librealsense-master/src/sync.cpp: In function ‘std::pair<double, double> librealsense::extract_timestamps(frame_holder&, frame_holder&)’: /home/hxwang/realsense_build/librealsense-master/src/sync.cpp:547:84: note: parameter passing for argument of type ‘std::pair<double, double>’ when C++17 is enabled changed to match C++14 in GCC 10.1 547 | <double, double> extract_timestamps(frame_holder & a, frame_holder & b) | ^ [ 48%] Building CXX object CMakeFiles/realsense2.dir/src/terminal-parser.cpp.o [ 48%] Building CXX object CMakeFiles/realsense2.dir/src/types.cpp.o [ 48%] Building C object CMakeFiles/realsense2.dir/src/verify.c.o [ 49%] Building CXX object CMakeFiles/realsense2.dir/src/serialized-utilities.cpp.o [ 49%] Building CXX object CMakeFiles/realsense2.dir/src/frame.cpp.o [ 49%] Building CXX object CMakeFiles/realsense2.dir/src/points.cpp.o [ 49%] Building CXX object CMakeFiles/realsense2.dir/src/to-string.cpp.o [ 50%] Building CXX object CMakeFiles/realsense2.dir/src/platform/platform-utils.cpp.o [ 50%] Building CXX object CMakeFiles/realsense2.dir/src/platform/uvc-option.cpp.o [ 50%] Building CXX object CMakeFiles/realsense2.dir/src/synthetic-options-watcher.cpp.o [ 50%] Building CXX object CMakeFiles/realsense2.dir/third-party/easyloggingpp/src/easylogging++.cc.o [ 51%] Linking CXX shared library Release/librealsense2.so [ 51%] Built target realsense2 [ 51%] Building CXX object third-party/rsutils/py/CMakeFiles/pyrsutils.dir/pyrsutils.cpp.o [ 51%] Building CXX object third-party/rsutils/py/CMakeFiles/pyrsutils.dir/__/include/rsutils/easylogging/elpp-init.cpp.o [ 52%] Linking CXX shared library ../../../Release/pyrsutils.cpython-311-aarch64-linux-gnu.so lto-wrapper: warning: using serial compilation of 5 LTRANS jobs lto-wrapper: note: see the ‘-flto’ option documentation for more information [ 52%] Built target pyrsutils [ 52%] Building CXX object wrappers/python/CMakeFiles/pyrealsense2.dir/pyrealsense2.cpp.o [ 52%] Building CXX object wrappers/python/CMakeFiles/pyrealsense2.dir/c_files.cpp.o [ 52%] Building CXX object wrappers/python/CMakeFiles/pyrealsense2.dir/pyrs_advanced_mode.cpp.o [ 53%] Building CXX object wrappers/python/CMakeFiles/pyrealsense2.dir/pyrs_context.cpp.o [ 53%] Building CXX object wrappers/python/CMakeFiles/pyrealsense2.dir/pyrs_device.cpp.o [ 53%] Building CXX object wrappers/python/CMakeFiles/pyrealsense2.dir/pyrs_export.cpp.o [ 53%] Building CXX object wrappers/python/CMakeFiles/pyrealsense2.dir/pyrs_frame.cpp.o [ 54%] Building CXX object wrappers/python/CMakeFiles/pyrealsense2.dir/pyrs_internal.cpp.o [ 54%] Building CXX object wrappers/python/CMakeFiles/pyrealsense2.dir/pyrs_options.cpp.o [ 54%] Building CXX object wrappers/python/CMakeFiles/pyrealsense2.dir/pyrs_pipeline.cpp.o [ 54%] Building CXX object wrappers/python/CMakeFiles/pyrealsense2.dir/pyrs_processing.cpp.o [ 55%] Building CXX object wrappers/python/CMakeFiles/pyrealsense2.dir/pyrs_record_playback.cpp.o [ 55%] Building CXX object wrappers/python/CMakeFiles/pyrealsense2.dir/pyrs_sensor.cpp.o [ 55%] Building CXX object wrappers/python/CMakeFiles/pyrealsense2.dir/pyrs_types.cpp.o [ 55%] Building CXX object wrappers/python/CMakeFiles/pyrealsense2.dir/pyrsutil.cpp.o [ 56%] Building CXX object wrappers/python/CMakeFiles/pyrealsense2.dir/__/__/common/metadata-helper.cpp.o [ 56%] Linking CXX shared library ../../Release/pyrealsense2.cpython-311-aarch64-linux-gnu.so lto-wrapper: warning: using serial compilation of 30 LTRANS jobs lto-wrapper: note: see the ‘-flto’ option documentation for more information [ 56%] Built target pyrealsense2 [ 56%] Building CXX object src/gl/CMakeFiles/realsense2-gl.dir/synthetic-stream-gl.cpp.o [ 56%] Building CXX object src/gl/CMakeFiles/realsense2-gl.dir/yuy2rgb-gl.cpp.o [ 56%] Building CXX object src/gl/CMakeFiles/realsense2-gl.dir/y4112rgb-gl.cpp.o [ 57%] Building CXX object src/gl/CMakeFiles/realsense2-gl.dir/pointcloud-gl.cpp.o [ 57%] Building CXX object src/gl/CMakeFiles/realsense2-gl.dir/rs-gl.cpp.o [ 57%] Building C object src/gl/CMakeFiles/realsense2-gl.dir/__/__/third-party/glad/glad.c.o [ 57%] Building CXX object src/gl/CMakeFiles/realsense2-gl.dir/__/__/common/opengl3.cpp.o [ 58%] Building CXX object src/gl/CMakeFiles/realsense2-gl.dir/pc-shader.cpp.o [ 58%] Building CXX object src/gl/CMakeFiles/realsense2-gl.dir/camera-shader.cpp.o [ 58%] Building CXX object src/gl/CMakeFiles/realsense2-gl.dir/upload.cpp.o [ 58%] Building CXX object src/gl/CMakeFiles/realsense2-gl.dir/colorizer-gl.cpp.o [ 59%] Building CXX object src/gl/CMakeFiles/realsense2-gl.dir/align-gl.cpp.o [ 59%] Building C object src/gl/CMakeFiles/realsense2-gl.dir/__/__/third-party/realsense-file/lz4/lz4.c.o [ 59%] Building CXX object src/gl/CMakeFiles/realsense2-gl.dir/__/__/third-party/easyloggingpp/src/easylogging++.cc.o [ 59%] Linking CXX shared library ../../Release/librealsense2-gl.so [ 59%] Built target realsense2-gl [ 59%] Building CXX object examples/hello-realsense/CMakeFiles/rs-hello-realsense.dir/rs-hello-realsense.cpp.o [ 59%] Linking CXX executable ../../Release/rs-hello-realsense [ 59%] Built target rs-hello-realsense [ 59%] Building CXX object examples/software-device/CMakeFiles/rs-software-device.dir/rs-software-device.cpp.o [ 59%] Linking CXX executable ../../Release/rs-software-device [ 59%] Built target rs-software-device [ 60%] Building CXX object examples/capture/CMakeFiles/rs-capture.dir/rs-capture.cpp.o [ 60%] Linking CXX executable ../../Release/rs-capture [ 60%] Built target rs-capture [ 60%] Building CXX object examples/callback/CMakeFiles/rs-callback.dir/rs-callback.cpp.o [ 60%] Linking CXX executable ../../Release/rs-callback [ 60%] Built target rs-callback [ 60%] Building CXX object examples/save-to-disk/CMakeFiles/rs-save-to-disk.dir/rs-save-to-disk.cpp.o [ 60%] Linking CXX executable ../../Release/rs-save-to-disk [ 60%] Built target rs-save-to-disk [ 61%] Building CXX object examples/multicam/CMakeFiles/rs-multicam.dir/rs-multicam.cpp.o [ 61%] Linking CXX executable ../../Release/rs-multicam [ 61%] Built target rs-multicam [ 61%] Building CXX object examples/pointcloud/CMakeFiles/rs-pointcloud.dir/rs-pointcloud.cpp.o [ 61%] Linking CXX executable ../../Release/rs-pointcloud [ 61%] Built target rs-pointcloud [ 62%] Building CXX object examples/align/CMakeFiles/rs-align.dir/rs-align.cpp.o [ 62%] Building CXX object examples/align/CMakeFiles/rs-align.dir/__/__/third-party/imgui/imgui.cpp.o [ 62%] Building CXX object examples/align/CMakeFiles/rs-align.dir/__/__/third-party/imgui/imgui_draw.cpp.o [ 62%] Building CXX object examples/align/CMakeFiles/rs-align.dir/__/__/third-party/imgui/imgui_impl_glfw.cpp.o [ 63%] Linking CXX executable ../../Release/rs-align [ 63%] Built target rs-align [ 63%] Building CXX object examples/align-gl/CMakeFiles/rs-align-gl.dir/rs-align-gl.cpp.o [ 63%] Building CXX object examples/align-gl/CMakeFiles/rs-align-gl.dir/__/__/third-party/imgui/imgui.cpp.o [ 64%] Building CXX object examples/align-gl/CMakeFiles/rs-align-gl.dir/__/__/third-party/imgui/imgui_draw.cpp.o [ 64%] Building CXX object examples/align-gl/CMakeFiles/rs-align-gl.dir/__/__/third-party/imgui/imgui_impl_glfw.cpp.o [ 64%] Linking CXX executable ../../Release/rs-align-gl [ 64%] Built target rs-align-gl [ 64%] Building CXX object examples/align-advanced/CMakeFiles/rs-align-advanced.dir/rs-align-advanced.cpp.o [ 64%] Building CXX object examples/align-advanced/CMakeFiles/rs-align-advanced.dir/__/__/third-party/imgui/imgui.cpp.o [ 64%] Building CXX object examples/align-advanced/CMakeFiles/rs-align-advanced.dir/__/__/third-party/imgui/imgui_draw.cpp.o [ 65%] Building CXX object examples/align-advanced/CMakeFiles/rs-align-advanced.dir/__/__/third-party/imgui/imgui_impl_glfw.cpp.o [ 65%] Linking CXX executable ../../Release/rs-align-advanced [ 65%] Built target rs-align-advanced [ 65%] Building CXX object examples/sensor-control/CMakeFiles/rs-sensor-control.dir/rs-sensor-control.cpp.o [ 66%] Linking CXX executable ../../Release/rs-sensor-control [ 66%] Built target rs-sensor-control [ 66%] Building CXX object examples/measure/CMakeFiles/rs-measure.dir/rs-measure.cpp.o [ 67%] Linking CXX executable ../../Release/rs-measure [ 67%] Built target rs-measure [ 67%] Building C object examples/C/depth/CMakeFiles/rs-depth.dir/rs-depth.c.o [ 67%] Linking CXX executable ../../../Release/rs-depth [ 67%] Built target rs-depth [ 67%] Building C object examples/C/color/CMakeFiles/rs-color.dir/rs-color.c.o [ 67%] Linking CXX executable ../../../Release/rs-color [ 67%] Built target rs-color [ 67%] Building C object examples/C/distance/CMakeFiles/rs-distance.dir/rs-distance.c.o [ 68%] Linking CXX executable ../../../Release/rs-distance [ 68%] Built target rs-distance [ 69%] Building CXX object examples/post-processing/CMakeFiles/rs-post-processing.dir/rs-post-processing.cpp.o [ 69%] Building CXX object examples/post-processing/CMakeFiles/rs-post-processing.dir/__/__/third-party/imgui/imgui.cpp.o [ 69%] Building CXX object examples/post-processing/CMakeFiles/rs-post-processing.dir/__/__/third-party/imgui/imgui_draw.cpp.o [ 69%] Building CXX object examples/post-processing/CMakeFiles/rs-post-processing.dir/__/__/third-party/imgui/imgui_impl_glfw.cpp.o [ 70%] Linking CXX executable ../../Release/rs-post-processing [ 70%] Built target rs-post-processing [ 70%] Building CXX object examples/record-playback/CMakeFiles/rs-record-playback.dir/rs-record-playback.cpp.o [ 71%] Building CXX object examples/record-playback/CMakeFiles/rs-record-playback.dir/__/__/third-party/imgui/imgui.cpp.o [ 71%] Building CXX object examples/record-playback/CMakeFiles/rs-record-playback.dir/__/__/third-party/imgui/imgui_draw.cpp.o [ 71%] Building CXX object examples/record-playback/CMakeFiles/rs-record-playback.dir/__/__/third-party/imgui/imgui_impl_glfw.cpp.o [ 71%] Linking CXX executable ../../Release/rs-record-playback [ 71%] Built target rs-record-playback [ 71%] Building CXX object examples/motion/CMakeFiles/rs-motion.dir/rs-motion.cpp.o [ 71%] Building C object examples/motion/CMakeFiles/rs-motion.dir/__/__/third-party/realsense-file/lz4/lz4.c.o [ 71%] Linking CXX executable ../../Release/rs-motion [ 71%] Built target rs-motion [ 71%] Building CXX object examples/gl/CMakeFiles/rs-gl.dir/rs-gl.cpp.o [ 71%] Linking CXX executable ../../Release/rs-gl [ 71%] Built target rs-gl [ 72%] Building CXX object examples/hdr/CMakeFiles/rs-hdr.dir/rs-hdr.cpp.o [ 72%] Building CXX object examples/hdr/CMakeFiles/rs-hdr.dir/__/__/third-party/imgui/imgui.cpp.o [ 72%] Building CXX object examples/hdr/CMakeFiles/rs-hdr.dir/__/__/third-party/imgui/imgui_draw.cpp.o [ 72%] Building CXX object examples/hdr/CMakeFiles/rs-hdr.dir/__/__/third-party/imgui/imgui_impl_glfw.cpp.o [ 73%] Linking CXX executable ../../Release/rs-hdr [ 73%] Built target rs-hdr [ 74%] Building CXX object tools/convert/CMakeFiles/rs-convert.dir/rs-convert.cpp.o [ 74%] Building CXX object tools/convert/CMakeFiles/rs-convert.dir/converter.cpp.o [ 74%] Building CXX object tools/convert/CMakeFiles/rs-convert.dir/converters/converter-csv.cpp.o [ 74%] Linking CXX executable ../../Release/rs-convert [ 74%] Built target rs-convert [ 75%] Building CXX object tools/enumerate-devices/CMakeFiles/rs-enumerate-devices.dir/rs-enumerate-devices.cpp.o [ 75%] Linking CXX executable ../../Release/rs-enumerate-devices [ 75%] Built target rs-enumerate-devices [ 75%] Building CXX object tools/fw-logger/CMakeFiles/rs-fw-logger.dir/rs-fw-logger.cpp.o [ 75%] Linking CXX executable ../../Release/rs-fw-logger [ 75%] Built target rs-fw-logger [ 75%] Building CXX object tools/terminal/CMakeFiles/rs-terminal.dir/rs-terminal.cpp.o [ 76%] Building CXX object tools/terminal/CMakeFiles/rs-terminal.dir/auto-complete.cpp.o [ 76%] Linking CXX executable ../../Release/rs-terminal [ 76%] Built target rs-terminal [ 76%] Building CXX object tools/recorder/CMakeFiles/rs-record.dir/rs-record.cpp.o [ 76%] Linking CXX executable ../../Release/rs-record [ 76%] Built target rs-record [ 77%] Building CXX object tools/fw-update/CMakeFiles/rs-fw-update.dir/rs-fw-update.cpp.o [ 77%] Linking CXX executable ../../Release/rs-fw-update [ 77%] Built target rs-fw-update [ 77%] Building CXX object tools/embed/CMakeFiles/rs-embed.dir/rs-embed.cpp.o [ 77%] Building C object tools/embed/CMakeFiles/rs-embed.dir/__/__/third-party/realsense-file/lz4/lz4.c.o [ 77%] Linking CXX executable ../../Release/rs-embed [ 77%] Built target rs-embed [ 78%] Building CXX object tools/data-collect/CMakeFiles/rs-data-collect.dir/rs-data-collect.cpp.o [ 78%] Linking CXX executable ../../Release/rs-data-collect [ 78%] Built target rs-data-collect [ 78%] Building C object common/fw/CMakeFiles/fw.dir/empty.c.o [ 78%] Building C object common/fw/CMakeFiles/fw.dir/D4XX_FW_Image.c.o [ 78%] Linking C static library ../../Release/libfw.a [ 78%] Built target fw [ 78%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/third-party/rsutils/include/rsutils/easylogging/elpp-init.cpp.o [ 78%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/model-views.cpp.o [ 79%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/notifications.cpp.o [ 79%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/calibration-model.cpp.o In file included from /home/hxwang/realsense_build/librealsense-master/src/core/options-watcher.h:8, from /home/hxwang/realsense_build/librealsense-master/tools/realsense-viewer/../../src/fw-update/../core/sensor-interface.h:12, from /home/hxwang/realsense_build/librealsense-master/tools/realsense-viewer/../../src/fw-update/../sensor.h:5, from /home/hxwang/realsense_build/librealsense-master/tools/realsense-viewer/../../src/fw-update/../uvc-sensor.h:6, from /home/hxwang/realsense_build/librealsense-master/tools/realsense-viewer/../../src/fw-update/../hw-monitor.h:6, from /home/hxwang/realsense_build/librealsense-master/tools/realsense-viewer/../../src/fw-update/fw-update-unsigned.h:6, from /home/hxwang/realsense_build/librealsense-master/tools/realsense-viewer/../../src/ds/ds-private.h:7, from /home/hxwang/realsense_build/librealsense-master/common/../src/ds/d400/d400-private.h:6, from /home/hxwang/realsense_build/librealsense-master/common/calibration-model.cpp:10: /home/hxwang/realsense_build/librealsense-master/third-party/rsutils/include/rsutils/signal.h: In member function ‘rsutils::subscription rsutils::signal<Args>::subscribe(callback&&)’: /home/hxwang/realsense_build/librealsense-master/third-party/rsutils/include/rsutils/signal.h:84:20: warning: lambda capture initializers only available with ‘-std=c++14’ or ‘-std=gnu++14’ [-Wc++14-extensions] 84 | [slot, weak = std::weak_ptr< impl >( _impl )] | ^~~~ [ 79%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/viewer.cpp.o [ 79%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/ux-window.cpp.o [ 80%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/ux-alignment.cpp.o [ 80%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/opengl3.cpp.o [ 80%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/rs-config.cpp.o [ 80%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/os.cpp.o [ 81%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/fw-update-helper.cpp.o [ 81%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/metadata-helper.cpp.o [ 81%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/output-model.cpp.o [ 81%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/skybox.cpp.o [ 82%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/measurement.cpp.o [ 82%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/on-chip-calib.cpp.o [ 82%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/updates-model.cpp.o [ 82%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/option-model.cpp.o [ 83%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/device-model.cpp.o [ 83%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/subdevice-model.cpp.o [ 83%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/processing-block-model.cpp.o [ 83%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/stream-model.cpp.o [ 84%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/post-processing-filters.cpp.o [ 84%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/sw-update/http-downloader.cpp.o [ 84%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/sw-update/dev-updates-profile.cpp.o [ 84%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/sw-update/versions-db-manager.cpp.o [ 85%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/reflectivity/reflectivity.cpp.o [ 85%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/common/utilities/imgui/wrap.cpp.o [ 85%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/realsense-viewer.cpp.o /home/hxwang/realsense_build/librealsense-master/tools/realsense-viewer/realsense-viewer.cpp: In function ‘void add_playback_device(rs2::context&, std::shared_ptr<std::vector<std::unique_ptr<rs2::device_model> > >, std::string&, rs2::viewer_model&, const std::string&)’: /home/hxwang/realsense_build/librealsense-master/tools/realsense-viewer/realsense-viewer.cpp:69:33: warning: lambda capture initializers only available with ‘-std=c++14’ or ‘-std=gnu++14’ [-Wc++14-extensions] 69 | [&viewer_model, weak_device_models = std::weak_ptr< device_models_list >( device_models ), filename]( | ^~~~~~~~~~~~~~~~~~ [ 85%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/third-party/imgui/imgui.cpp.o [ 86%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/third-party/imgui/imgui_draw.cpp.o [ 86%] Building CXX object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/third-party/imgui/imgui_impl_glfw.cpp.o [ 86%] Building C object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/third-party/glad/glad.c.o [ 86%] Building C object tools/realsense-viewer/CMakeFiles/realsense-viewer.dir/__/__/third-party/tinyfiledialogs/tinyfiledialogs.c.o [ 87%] Linking CXX executable ../../Release/realsense-viewer [ 87%] Built target realsense-viewer [ 88%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/third-party/rsutils/include/rsutils/easylogging/elpp-init.cpp.o [ 88%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/model-views.cpp.o [ 88%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/notifications.cpp.o [ 88%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/calibration-model.cpp.o [ 89%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/viewer.cpp.o [ 89%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/ux-window.cpp.o [ 89%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/ux-alignment.cpp.o [ 89%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/opengl3.cpp.o [ 90%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/rs-config.cpp.o [ 90%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/os.cpp.o [ 90%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/fw-update-helper.cpp.o [ 90%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/metadata-helper.cpp.o [ 91%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/output-model.cpp.o [ 91%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/skybox.cpp.o [ 91%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/measurement.cpp.o [ 91%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/on-chip-calib.cpp.o [ 91%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/updates-model.cpp.o [ 92%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/option-model.cpp.o [ 92%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/device-model.cpp.o [ 92%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/subdevice-model.cpp.o [ 92%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/processing-block-model.cpp.o [ 93%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/stream-model.cpp.o [ 93%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/post-processing-filters.cpp.o [ 93%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/sw-update/http-downloader.cpp.o [ 93%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/sw-update/dev-updates-profile.cpp.o [ 94%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/sw-update/versions-db-manager.cpp.o [ 94%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/reflectivity/reflectivity.cpp.o [ 94%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/common/utilities/imgui/wrap.cpp.o [ 94%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/rs-depth-quality.cpp.o [ 95%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/depth-quality-model.cpp.o [ 95%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/third-party/imgui/imgui.cpp.o [ 95%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/third-party/imgui/imgui_draw.cpp.o [ 95%] Building CXX object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/third-party/imgui/imgui_impl_glfw.cpp.o [ 96%] Building C object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/third-party/glad/glad.c.o [ 96%] Building C object tools/depth-quality/CMakeFiles/rs-depth-quality.dir/__/__/third-party/tinyfiledialogs/tinyfiledialogs.c.o [ 96%] Linking CXX executable ../../Release/rs-depth-quality [ 96%] Built target rs-depth-quality [ 97%] Building CXX object tools/rosbag-inspector/CMakeFiles/rs-rosbag-inspector.dir/rs-rosbag-inspector.cpp.o [ 97%] Building CXX object tools/rosbag-inspector/CMakeFiles/rs-rosbag-inspector.dir/__/__/common/os.cpp.o [ 97%] Building C object tools/rosbag-inspector/CMakeFiles/rs-rosbag-inspector.dir/__/__/third-party/glad/glad.c.o [ 97%] Building CXX object tools/rosbag-inspector/CMakeFiles/rs-rosbag-inspector.dir/__/__/third-party/imgui/imgui.cpp.o [ 98%] Building CXX object tools/rosbag-inspector/CMakeFiles/rs-rosbag-inspector.dir/__/__/third-party/imgui/imgui_draw.cpp.o [ 98%] Building CXX object tools/rosbag-inspector/CMakeFiles/rs-rosbag-inspector.dir/__/__/third-party/imgui/imgui_impl_glfw.cpp.o [ 98%] Building C object tools/rosbag-inspector/CMakeFiles/rs-rosbag-inspector.dir/__/__/third-party/tinyfiledialogs/tinyfiledialogs.c.o [ 98%] Building CXX object tools/rosbag-inspector/CMakeFiles/rs-rosbag-inspector.dir/__/__/third-party/rsutils/include/rsutils/easylogging/elpp-init.cpp.o [ 99%] Linking CXX executable ../../Release/rs-rosbag-inspector [ 99%] Built target rs-rosbag-inspector [ 99%] Building CXX object tools/benchmark/CMakeFiles/rs-benchmark.dir/rs-benchmark.cpp.o [100%] Building C object tools/benchmark/CMakeFiles/rs-benchmark.dir/__/__/third-party/glad/glad.c.o [100%] Linking CXX executable ../../Release/rs-benchmark [100%] Built target rs-benchmark (base) hxwang@raspberrypi:~/realsense_build/librealsense-master/build $ cd ~/realsense_build/librealsense-master/build/wrappers/python/ (base) hxwang@raspberrypi:~/realsense_build/librealsense-master/build/wrappers/python $ find . -name "*.so" (base) hxwang@raspberrypi:~/realsense_build/librealsense-master/build/wrappers/python $ ls CMakeFiles Makefile pyrealsense2ConfigVersion.cmake cmake_install.cmake pyrealsense2Config.cmake (base) hxwang@raspberrypi:~/realsense_build/librealsense-master/build/wrappers/python $ 还是没有
最新发布
07-07
从你的输出来看: ```bash find . -name "*.so" <无输出> ``` ```bash ls CMakeFiles Makefile pyrealsense2ConfigVersion.cmake cmake_install.cmake pyrealsense2Config.cmake ``` 虽然编译过程显示: ``` [56%] Built target pyrealsense2 ``` 但实际上 **并没有生成 `.so` 文件**,也没有 `setup.py`。 --- ### ❗ 根本原因分析 #### ✅ 编译成功 ≠ 模块文件生成成功 虽然 CMake 和 make 报告说构建了 `pyrealsense2` 目标,但可能由于以下原因导致最终没有生成 `.so` 文件: | 原因 | 说明 | |------|------| | 📦 构建路径错误 | `.so` 被生成到了其他目录(如 `Release/` 或上级目录) | | ⚙️ 编译器优化或 LTO 导致静默失败 | 特别是树莓派上资源不足时容易出错 | | 🧱 CMake 配置不完整 | 没有启用 Python 绑定或路径错误 | | 📁 文件权限问题 | 没有写入权限导致无法生成文件 | --- ### ✅ 解决方案 #### ✅ 步骤 1:检查整个 build 目录中是否存在 `.so` 文件 ```bash cd ~/realsense_build/librealsense-master/build find . -name "*.so" ``` 你可能会看到类似输出: ``` ./wrappers/python/../../Release/pyrealsense2.cpython-311-aarch64-linux-gnu.so ``` 如果找到了 `.so` 文件,请继续下一步。 --- #### ✅ 步骤 2:手动复制 `.so` 文件到 python 目录 假设你找到了: ``` ./Release/pyrealsense2.cpython-311-aarch64-linux-gnu.so ``` 进入 wrappers 目录并复制: ```bash cd ~/realsense_build/librealsense-master/build/wrappers/python/ cp ../../Release/pyrealsense2.*.so . ``` --- #### ✅ 步骤 3:创建 `setup.py` 和 `__init__.py` ##### 创建 `setup.py` ```bash nano setup.py ``` 粘贴如下内容: ```python from setuptools import setup, Extension setup( name='pyrealsense2', version='2.55.1', description='Python bindings for Intel RealSense SDK', packages=['pyrealsense2'], package_dir={'pyrealsense2': '.'}, package_data={'pyrealsense2': ['*.so']}, ) ``` ##### 创建空的 `__init__.py` ```bash touch __init__.py ``` --- #### ✅ 步骤 4:安装模块 如果你希望使用系统 Python: ```bash sudo pip install . --break-system-packages ``` 或者推荐使用虚拟环境: ```bash python3 -m venv ~/rs_env source ~/rs_env/bin/activate pip install . ``` --- ### ✅ 成功标志 运行以下命令测试是否成功导入: ```bash python3 -c "import pyrealsense2 as rs; print(rs.__version__); print(dir(rs))" ``` 你应该看到类似输出: ``` 2.55.1 ['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'context', 'device', 'pipeline', ...] ``` --- ### 🛠️ 小结 | 问题 | 原因 | 解决办法 | |------|------|-----------| | 编译成功但找不到 `.so` | 实际生成在 `Release/` 目录下 | 手动复制 `.so` 文件 | | 没有 `setup.py` | 构建系统未生成 | 手动创建 | | 模块无法导入 | 安装路径或环境问题 | 使用虚拟环境或加 `--break-system-packages` | --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值