之前在HEVC代码学习35:xEncodeCU函数中介绍过xEncodeCU函数,今天来看JEM中的xEncodeCU,其中难点在于QTBT编码结构。

HM中使用compressCtu对每个CTU进行划分并预测,然后使用encodeCtu对每个CTU进行编码。JEM中也是如此,会在xEncodeCU,迭代完成CU各种信息的编码。所以在这里,当前的CTU已经进行了划分和预测,如果要看CU的划分和预测结果就可以到这里找。

JEM中与HM主要区别:
1.JEM中使用了QTBT(四叉树加二叉树)的编码结构,因此xEncodeCU中在四叉树划分之后,增加了二叉树划分的迭代操作。
2.由于使用QTBT,划分中增加了一些尺寸的限定条件,需要得到当前块尺寸,因此xEncodeCU中输入参数中增加了当前块的宽和高。
3.增加了新增模式的flag的编码。

流程如下:
1.从CTU开始,此时深度为0,尺寸为uiCTUSize,默认为128。
2.如果当前块为2Nx2N,宽度为uiCTUSize>>uiDepth,且块尺寸大于四叉树最小尺寸uiMinQTSize(在cfg中可以设置),当前划分深度小于四叉树深度(存储在TComDataCUm_puhDepth中)时,递归对四个分块进行编码;否则即达到最大深度,不再递归调用xEncodeCU
3.四叉树达到最大深度之后,如果当前块长或块大于二叉树最小尺寸且两者都小于二叉树最大尺寸时,进行二叉树划分。通过getBTSplitModeForBTDepth获取二叉树划分模式,为1时,进行横向划分,分别对两个块递归划分;为2时,进行纵向划分,分别对两个块递归划分。
4.如果当前块长和块都小于二叉树最小尺寸时,停止划分,调用encodeXXXXX函数,对CU的预测信息进行编码,这里就不列举具体函数了。

划分示例:
这样说很模糊,我随便编了一个序列,以第一个CTU为例,说明一下这个递归过程。第一个CTU的最上角32x32 CU的划分结果为:四叉树深度为2,二叉树模式为2,划分结果如下图(点击看大图):

CU(0,0) depth=0 Width=128 Height=128:
当前进入的是第一个CTU,此时深度为0,长宽均为128,此时长宽相等,且等于uiCTUSize>>uiDepth=128(uiCTUSize默认为128)。判断是否达到最小四叉树尺寸uiMinQTSize(默认为8),当前方块尺寸为128大于uiMinQTSizepcCU->getDepth( uiAbsPartIdx )获取到的四叉树深度为2,当前深度小于2,分别对四个子块调用encodeCtu进行编码。

CU(0,0) depth=1 Width=64 Height=64:
重复刚才的判断,满足四叉树划分条件,进行四叉树划分,调用encodeCtu进行编码。

CU(0,0) depth=2 Width=32 Height=32:
重复刚才的判断,当前深度2,长宽为32,等于uiCTUSize>>uiDepth=32,大于uiMinQTSize,当前深度不小于2,不再进行四叉树划分 ,下面将进行二叉树划分。
当前块长和高为32,大于最小二叉树尺寸4,且小于等于最大二叉树尺寸32,二叉树深度为0,小于最大二叉树深度3。通过pcCU->getBTSplitModeForBTDepth获取到二叉树模式为2,进行垂直划分,分别对两个子块调用encodeCtu进行编码。

CU(0,0) depth=3 Width=16 Height=32:
重复二叉树划分的判断,获取到二叉树模式为0,结束划分。

CU(16,0) depth=3 Width=16 Height=32:
重复二叉树划分的判断,获取到二叉树模式为0,结束划分。

语言表达能力较差,大家凑合着看。

代码分析:

//递归编码CU,相比HM增加了CU尺寸
/** encode a CU block recursively* \param pcCU* \param uiAbsPartIdx      CU索引* \param uiDepth               划分深度* \returns Void*/
#if JVET_C0024_QTBT
Void TEncCu::xEncodeCU( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiWidth, UInt uiHeight, UInt uiSplitConstrain )
#else
Void TEncCu::xEncodeCU( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth )
#endif
{
#if JVET_C0024_BT_RMV_REDUNDANTpcCU->setSplitConstrain( uiSplitConstrain );Bool bQTreeValid = false;
#endifTComPic   *const pcPic   = pcCU->getPic();      //当前帧TComSlice *const pcSlice = pcCU->getSlice();    //当前sliceconst TComSPS   &sps =*(pcSlice->getSPS());           //SPSconst TComPPS   &pps =*(pcSlice->getPPS());       //PPS#if !JVET_C0024_QTBTconst UInt maxCUWidth  = sps.getMaxCUWidth();const UInt maxCUHeight = sps.getMaxCUHeight();Bool bBoundary = false;
#endif//CU左上角X坐标UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
#if JVET_C0024_QTBT//CU右侧X坐标const UInt uiRPelX   = uiLPelX + uiWidth  - 1;
#elseconst UInt uiRPelX   = uiLPelX + (maxCUWidth>>uiDepth)  - 1;
#endif//CU左上角Y坐标UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
#if JVET_C0024_QTBT//CU下侧Y坐标const UInt uiBPelY   = uiTPelY + uiHeight - 1;
#elseconst UInt uiBPelY   = uiTPelY + (maxCUHeight>>uiDepth) - 1;
#endif#if JVET_C0024_QTBT//当块宽度大于TU最大尺寸MAX_TU_SIZE时,强制使用四叉树划分Bool bForceQT = uiWidth > MAX_TU_SIZE;if( bForceQT )        //当强制四叉树划分时,块尺寸必须是2Nx2N{assert(uiWidth == uiHeight);}//CTU尺寸UInt uiCTUSize = pcCU->getSlice()->getSPS()->getCTUSize();
#if JVET_C0024_DELTA_QP_FIX//四叉树的宽和高UInt uiQTWidth = uiCTUSize>>uiDepth;UInt uiQTHeight = uiCTUSize>>uiDepth;//二叉树的深度const UInt uiQTBTDepth = (uiDepth<<1) + (g_aucConvertToBit[uiQTWidth]-g_aucConvertToBit[uiWidth] + g_aucConvertToBit[uiQTHeight]-g_aucConvertToBit[uiHeight]);const UInt uiMaxDQPDepthQTBT = pps.getMaxCuDQPDepth() << 1;
#endif//当前块为2Nx2N且尺寸等于uiCTUSize>>uiDepth时if (uiCTUSize>>uiDepth == uiWidth && uiWidth==uiHeight){
#endif//CU坐标小于亮度图像的宽和高if( ( uiRPelX < sps.getPicWidthInLumaSamples() ) && ( uiBPelY < sps.getPicHeightInLumaSamples() ) ){
#if JVET_C0024_QTBT//强制四叉树划分if( bForceQT ){//划分深度一定小于当前CU的深度assert(uiDepth < pcCU->getDepth( uiAbsPartIdx ) ); }else
#endif//编码划分Flagm_pcEntropyCoder->encodeSplitFlag( pcCU, uiAbsPartIdx, uiDepth );}else  //CU坐标不小于亮度图像的宽和高时,检测边缘{
#if JVET_C0024_QTBTassert(uiDepth < pcCU->getDepth( uiAbsPartIdx ) );
#elsebBoundary = true;
#endif}#if JVET_C0024_BT_RMV_REDUNDANT//四叉树是否可用bQTreeValid = true;   //获取最小四叉树尺寸UInt uiMinQTSize = sps.getMinQTSize(pcCU->getSlice()->getSliceType(), pcCU->getTextType());//如果uiCTUSize>>uiDepth小于最小四叉树尺寸,此时四叉树不可用if ((uiCTUSize>>uiDepth) <= uiMinQTSize){bQTreeValid = false;}
#endif#if JVET_C0024_QTBT//当前划分深度小于当前CU深度时if( uiDepth < pcCU->getDepth( uiAbsPartIdx ) )
#elseif( ( ( uiDepth < pcCU->getDepth( uiAbsPartIdx ) ) && ( uiDepth < sps.getLog2DiffMaxMinCodingBlockSize() ) ) || bBoundary )
#endif{UInt uiQNumParts = ( pcPic->getNumPartitionsInCtu() >> (uiDepth<<1) )>>2;
#if JVET_C0024_DELTA_QP_FIX//使用DQP时,默认关闭if( uiQTBTDepth == uiMaxDQPDepthQTBT && pps.getUseDQP())
#elseif( uiDepth == pps.getMaxCuDQPDepth() && pps.getUseDQP())
#endif{setdQPFlag(true);
#if JVET_C0024_DELTA_QP_FIXpcCU->setQuPartIdx( uiAbsPartIdx );pcCU->setQuLastCodedQP( pcCU->getCodedQP() );
#endif}if( uiDepth == pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth() && pcSlice->getUseChromaQpAdj()){setCodeChromaQpAdjFlag(true);}//递归调用,对四个分块进行编码for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++, uiAbsPartIdx+=uiQNumParts ){//当前CU的坐标uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];//在亮度范围内if( ( uiLPelX < sps.getPicWidthInLumaSamples() ) && ( uiTPelY < sps.getPicHeightInLumaSamples() ) ){
#if JVET_C0024_QTBTxEncodeCU( pcCU, uiAbsPartIdx, uiDepth+1, uiWidth>>1, uiHeight>>1 );
#elsexEncodeCU( pcCU, uiAbsPartIdx, uiDepth+1 );
#endif}
#if JVET_C0024_QTBTelse{pcCU->getPic()->addCodedAreaInCTU(uiWidth*uiHeight>>2);}
#endif}return;}#if JVET_C0024_QTBT}
#if JVET_C0024_BT_RMV_REDUNDANTBool bBTHorRmvEnable = false;Bool bBTVerRmvEnable = false;if (pcCU->getSlice()->getSliceType() != I_SLICE){bBTHorRmvEnable = true;bBTVerRmvEnable = bQTreeValid;}
#endif
#if JVET_C0024_SPS_MAX_BT_DEPTH//最大二叉树深度UInt uiMaxBTD = pcSlice->isIntra() ? (isLuma(pcCU->getTextType())?sps.getMaxBTDepthISliceL():sps.getMaxBTDepthISliceC()): sps.getMaxBTDepth();
#elseUInt uiMaxBTD = pcCU->getSlice()->isIntra() ? (isLuma(pcCU->getTextType())?MAX_BT_DEPTH:MAX_BT_DEPTH_C): MAX_BT_DEPTH_INTER;
#endif
#if JVET_C0024_SPS_MAX_BT_SIZEUInt uiMaxBTSize = pcSlice->isIntra() ? (isLuma(pcCU->getTextType())?sps.getMaxBTSizeISliceL():sps.getMaxBTSizeISliceC()): sps.getMaxBTSize();
#else//最大二叉树尺寸UInt uiMaxBTSize = isLuma(pcCU->getTextType()) ? pcCU->getSlice()->getMaxBTSize(): MAX_BT_SIZE_C;
#endif//最小二叉树尺寸UInt uiMinBTSize = pcCU->getSlice()->isIntra() ? (isLuma(pcCU->getTextType())?MIN_BT_SIZE:MIN_BT_SIZE_C): MIN_BT_SIZE_INTER;//最小二叉树深度UInt uiBTDepth = pcCU->getBTDepth(uiAbsPartIdx, uiWidth, uiHeight);//当前块符合二叉树划分的深度和尺寸条件时if ( (uiHeight>uiMinBTSize || uiWidth>uiMinBTSize) && uiWidth<=uiMaxBTSize && uiHeight<=uiMaxBTSize && uiBTDepth<uiMaxBTD) {
#if JVET_C0024_BT_RMV_REDUNDANTuiSplitConstrain = 0;
#endif//编码二叉树划分m_pcEntropyCoder->encodeBTSplitMode(pcCU, uiAbsPartIdx, uiWidth, uiHeight);//二叉树划分模式为1,横向划分if (pcCU->getBTSplitModeForBTDepth(uiAbsPartIdx, uiBTDepth)==1){
#if JVET_C0024_DELTA_QP_FIXif( uiQTBTDepth == uiMaxDQPDepthQTBT && pps.getUseDQP()){setdQPFlag(true);
#if JVET_C0024_DELTA_QP_FIXpcCU->setQuPartIdx( uiAbsPartIdx );pcCU->setQuLastCodedQP( pcCU->getCodedQP() );
#endif}
#endif//对两个分块进行编码for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 2; uiPartUnitIdx++ ){if (uiPartUnitIdx==1){uiAbsPartIdx = g_auiRasterToZscan[g_auiZscanToRaster[uiAbsPartIdx] + (uiHeight>>1)/pcCU->getPic()->getMinCUHeight()*pcCU->getPic()->getNumPartInCtuWidth()];}
#if JVET_C0024_BT_RMV_REDUNDANTxEncodeCU( pcCU, uiAbsPartIdx, uiDepth, uiWidth, uiHeight>>1, uiSplitConstrain );if (pcCU->getBTSplitModeForBTDepth(uiAbsPartIdx, uiBTDepth+1) == 2 && bBTHorRmvEnable && uiPartUnitIdx==0){uiSplitConstrain = 2;}
#elsexEncodeCU( pcCU, uiAbsPartIdx, uiDepth, uiWidth, uiHeight>>1 );
#endif}return;}//二叉树划分模式为2,纵向划分else if (pcCU->getBTSplitModeForBTDepth(uiAbsPartIdx, uiBTDepth)==2){
#if JVET_C0024_DELTA_QP_FIXif( uiQTBTDepth == uiMaxDQPDepthQTBT && pps.getUseDQP()){setdQPFlag(true);
#if JVET_C0024_DELTA_QP_FIXpcCU->setQuPartIdx( uiAbsPartIdx );pcCU->setQuLastCodedQP( pcCU->getCodedQP() );
#endif}
#endiffor ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 2; uiPartUnitIdx++ ){if (uiPartUnitIdx==1){uiAbsPartIdx = g_auiRasterToZscan[g_auiZscanToRaster[uiAbsPartIdx] + (uiWidth>>1)/pcCU->getPic()->getMinCUWidth()];}
#if JVET_C0024_BT_RMV_REDUNDANTxEncodeCU( pcCU, uiAbsPartIdx, uiDepth, uiWidth>>1, uiHeight, uiSplitConstrain );if (pcCU->getBTSplitModeForBTDepth(uiAbsPartIdx, uiBTDepth+1) == 1 && bBTVerRmvEnable && uiPartUnitIdx==0){uiSplitConstrain = 1;}
#elsexEncodeCU( pcCU, uiAbsPartIdx, uiDepth, uiWidth>>1, uiHeight );
#endif}return;}}pcCU->getPic()->addCodedAreaInCTU(uiWidth*uiHeight);UInt uiBlkX = g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ] >> MIN_CU_LOG2;UInt uiBlkY = g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ] >> MIN_CU_LOG2;pcCU->getPic()->setCodedBlkInCTU(true, uiBlkX, uiBlkY, uiWidth>> MIN_CU_LOG2, uiHeight>> MIN_CU_LOG2);#endif#if JVET_C0024_AMAX_BTif (!pcCU->getSlice()->isIntra()){g_uiBlkSize[pcCU->getSlice()->getDepth()] += uiWidth*uiHeight;g_uiNumBlk[pcCU->getSlice()->getDepth()]++;}
#endif
#if JVET_C0024_DELTA_QP_FIXif( uiQTBTDepth <= uiMaxDQPDepthQTBT && pps.getUseDQP())
#elseif( uiDepth <= pps.getMaxCuDQPDepth() && pps.getUseDQP())
#endif{setdQPFlag(true);
#if JVET_C0024_DELTA_QP_FIXpcCU->setQuPartIdx( uiAbsPartIdx );pcCU->setQuLastCodedQP( pcCU->getCodedQP() );
#endif}//编码其他flagif( uiDepth <= pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth() && pcSlice->getUseChromaQpAdj()){setCodeChromaQpAdjFlag(true);}if (pps.getTransquantBypassEnableFlag()){m_pcEntropyCoder->encodeCUTransquantBypassFlag( pcCU, uiAbsPartIdx );}if( !pcSlice->isIntra() ){m_pcEntropyCoder->encodeSkipFlag( pcCU, uiAbsPartIdx );}if( pcCU->isSkipped( uiAbsPartIdx ) ){
#if VCEG_AZ07_FRUC_MERGEm_pcEntropyCoder->encodeFRUCMgrMode( pcCU , uiAbsPartIdx , 0 );if( !pcCU->getFRUCMgrMode( uiAbsPartIdx ) )
#endif
#if COM16_C1016_AFFINE{if ( pcCU->isAffineMrgFlagCoded(uiAbsPartIdx, 0) ){m_pcEntropyCoder->encodeAffineFlag( pcCU, uiAbsPartIdx, 0 );}if ( !pcCU->isAffine(uiAbsPartIdx) ){m_pcEntropyCoder->encodeMergeIndex( pcCU, uiAbsPartIdx );}}
#elsem_pcEntropyCoder->encodeMergeIndex( pcCU, uiAbsPartIdx );
#endif
#if VCEG_AZ06_ICm_pcEntropyCoder->encodeICFlag  ( pcCU, uiAbsPartIdx );
#endif
#if !JVET_C0024_QTBTfinishCU(pcCU,uiAbsPartIdx);
#endif
#if JVET_C0024_DELTA_QP_FIXif( pps.getUseDQP() ){ pcCU->setCodedQP( pcCU->getQP(uiAbsPartIdx) );}
#endifreturn;}m_pcEntropyCoder->encodePredMode( pcCU, uiAbsPartIdx );
#if JVET_C0024_QTBTif (isLuma(pcCU->getTextType())){
#endif
#if VCEG_AZ05_INTRA_MPIm_pcEntropyCoder->encodeMPIIdx(pcCU, uiAbsPartIdx);
#endif
#if COM16_C1046_PDPC_INTRA && !JVET_G0104_PLANAR_PDPCm_pcEntropyCoder->encodePDPCIdx(pcCU, uiAbsPartIdx);
#endif
#if JVET_C0024_QTBT}
#elsem_pcEntropyCoder->encodePartSize( pcCU, uiAbsPartIdx, uiDepth );
#endif#if JVET_C0024_QTBTif (pcCU->isIntra( uiAbsPartIdx ) )
#elseif (pcCU->isIntra( uiAbsPartIdx ) && pcCU->getPartitionSize( uiAbsPartIdx ) == SIZE_2Nx2N )
#endif{m_pcEntropyCoder->encodeIPCMInfo( pcCU, uiAbsPartIdx );if(pcCU->getIPCMFlag(uiAbsPartIdx)){
#if !JVET_C0024_QTBT// Encode slice finishfinishCU(pcCU,uiAbsPartIdx);
#endif
#if JVET_C0024_DELTA_QP_FIXif( pps.getUseDQP() ){ pcCU->setCodedQP( pcCU->getQP(uiAbsPartIdx) );}
#endifreturn;}}// prediction Info ( Intra : direction mode, Inter : Mv, reference idx )m_pcEntropyCoder->encodePredInfo( pcCU, uiAbsPartIdx );
#if COM16_C806_OBMCm_pcEntropyCoder->encodeOBMCFlag( pcCU, uiAbsPartIdx );
#endif
#if VCEG_AZ06_ICm_pcEntropyCoder->encodeICFlag  ( pcCU, uiAbsPartIdx );
#endif// Encode CoefficientsBool bCodeDQP = getdQPFlag();Bool codeChromaQpAdj = getCodeChromaQpAdjFlag();
#if  VCEG_AZ05_ROT_TR  || VCEG_AZ05_INTRA_MPI || COM16_C1044_NSST || COM16_C1046_PDPC_INTRAInt bNonZeroCoeff = false;
#endif
#if JVET_C0045_C0053_NO_NSST_FOR_TSInt iNonZeroCoeffNonTs;
#endifm_pcEntropyCoder->encodeCoeff( pcCU, uiAbsPartIdx, uiDepth, bCodeDQP, codeChromaQpAdj
#if VCEG_AZ05_ROT_TR  || VCEG_AZ05_INTRA_MPI || COM16_C1044_NSST || COM16_C1046_PDPC_INTRA, bNonZeroCoeff
#endif
#if JVET_C0045_C0053_NO_NSST_FOR_TS, iNonZeroCoeffNonTs
#endif);setCodeChromaQpAdjFlag( codeChromaQpAdj );setdQPFlag( bCodeDQP );
#if JVET_C0024_DELTA_QP_FIXif( pps.getUseDQP() ){ pcCU->setCodedQP( pcCU->getQP(uiAbsPartIdx) );}
#endif#if !JVET_C0024_QTBT// --- write terminating bit ---finishCU(pcCU,uiAbsPartIdx);
#endif
}

H.266代码学习:xEncodeCU函数相关推荐

  1. H.266代码学习:decodeCtu和xDecodeCU函数

    之前 HEVC代码学习39:decodeCtu和xDecodeCU函数 中对HM中的CTU解码函数进行了学习,这里来学习一下JEM中的. 首先需要强调的是,这里只是用来解码flag.系数等,没有进行预 ...

  2. H.266代码学习:decompressCtu和xDecompressCU函数

    今天来学习一下JEM的decompressCtu和xDecompressCU函数.之前在 H.266代码学习:decodeCtu和xDecodeCU函数 学习了的学习中提到,decodeCtu和xDe ...

  3. H.266代码学习:xIntraCodingTUBlock函数

    今天来继续学习帧内编码的重要函数xIntraCodingTUBlock,上次 H.266代码学习:xRecurIntraCodingLumaQT函数 学习中提到,xIntraCodingTUBlock ...

  4. H.266代码学习:estIntraPredLumaQT函数

    之前 HEVC代码学习42:estIntraPredLumaQT函数 对HM中的estIntraPredLumaQT函数进行了学习,下面将对JEM中的该函数进行学习. estIntraPredLuma ...

  5. H.266代码学习:JEM使用方法

    之前在HEVC代码学习0:HM使用+码流分析教程中详细介绍了HM使用方法,而H.266参考代码JEM已经成型,因此这里简单介绍下JEM的使用方法. 阅读建议: JEM使用方法与HM类似,使用中改动在于 ...

  6. VVC/H.266代码阅读(VTM8.0)(三. Slice到CTU的处理 )

    本文是本系列的第三篇博客,内容是分析从Slice到CTU的处理代码. 该系列相关博客为: VVC/H.266代码阅读(VTM8.0)(一. NALU提取) VVC/H.266代码阅读(VTM8.0)( ...

  7. AV1代码学习:函数encode_frame和aom_codec_encode

    1.encode_frame函数 在编码端aomenc.c的main函数中,在进入编码过程循环后,循环读取视频的每一帧数据,然后通过encode_frame函数对每一帧进行编码. encode_fra ...

  8. H.266/VVC代码学习:帧内预测之角度预测函数(predIntraAng、xPredIntraAng)

    predIntraAng函数 VTM中,帧内预测的角度预测的入口函数为predIntraAng函数,该函数主要是用于进行传统的帧内预测(Planar.DC.角度预测),然后对Planar和DC模式使用 ...

  9. H.266/VVC-VTM代码学习27-VTM中编码器主函数逻辑

    H.266/VVC专栏传送 上一篇:H.266/VVC-VTM代码学习26-VTM中RDcost的计算与λ的设定(二) 下一篇:持续创作中- 目录 H.266/VVC专栏传送 前言 一.简介 二.代码 ...

最新文章

  1. TBContact -- 导出ThunderBird邮件地址本
  2. Elasticsearch之分页变量
  3. java中HashMap,LinkedHashMap,TreeMap,HashTable的区别
  4. linux pci扫描链表,Linux Kernel ---- PCI Driver 分析
  5. Yii 框架学习--01 框架入门
  6. 上海电力学院计算机学院怎么样,上海电力学院计算机科学与技术学院在职研究生_上海电力学院在职研究生_在职研究生招生信息网...
  7. 看完就入门系列!吞吐量、消息持久化、负载均衡和持久化、伸缩性…… 你真的了解 Kafka 了吗?...
  8. 电气与计算机学院院长论坛报告,我校电子系举办2019年电子信息学科院长论坛暨工程教育新进展研讨会...
  9. shiro、cas、pac4j 实现单点登陆
  10. Bailian2746 约瑟夫问题【 约瑟夫问题】
  11. Spring的核心思想,这篇文章短小精悍的总结透了
  12. matlab可以写类,matlab如何写一个类
  13. linux超级终端配置交换机路由器
  14. 9.4SAS软件入门
  15. 递归与自我指涉标识牌Top 5
  16. behavior3editor环境搭建
  17. Gateway NV47H18C BIOS 密码清除
  18. 苹果 Mac Big Sur 如何更改锁屏时间?
  19. 数显电接点压力表与指针电接点压力表的区别
  20. Linux修改系统时间、时区

热门文章

  1. 硕博连读,985院校在夹缝中求生,众多强者中面试Python成功上岸
  2. php打开页面的快捷键,窗口切换快捷键是什么
  3. 【软件建模与UML】
  4. ipad平板哪个比较好一点
  5. 100分与99分的区别
  6. Cesium雷达效果
  7. 一副对联,16个外国典故
  8. mysql 导入数据库sql语句_mysql中导入数据与导出数据库sql语句
  9. 飞讯管理员端群组部分完整版实现
  10. linux中grep命令返回值,grep命令详解