AVS3编码学习过程中,很重要的一部分是捋清码流结构。通过学习AVS3-P2(FCD 2.0)-20200403_N2805.pdf,博主整理了AVS3的码流结构思维导图,并将编码树、编码单元、变换单元三个重要的结构抽取出来,以C语言的形式进行注释分析。本文中的图片、源码可以到https://download.csdn.net/download/leelitian3/14102746中免费下载。

码流结构导图:uAVS3e_structure

编码树:coding_unit_tree

/* LCU的起始像素,划分次数,划分模式,LCU的大小,是否支持QT划分,划分模式 */
coding_unit_tree(x0, y0, split, width, height, qt, mode)
{// 判定边界isBoundary = ((x0 + width) > PicWidthInLuma) || ((y0 + height) > PicHeightInLuma);rightBoundary = ((x0 + width) > PicWidthInLuma) && ((y0 + height) <= PicHeightInLuma);bottomBoundary = ((x0 + width) <= PicWidthInLuma) && ((y0 + height) > PicHeightInLuma);// 允许的划分标志allowNoSplit = 0;allowSplitQt = 0;allowSplitBtVer = 0;allowSplitBtHor = 0;allowSplitEqtVer = 0;allowSplitEqtHor = 0;// 如果是边界if (isBoundary){allowNoSplit = 0;// I帧:128x128if ((PictureType == 0) && (width > 64) && (height > 64)){allowSplitQt = 1;   // QTallowNoSplit = 1;   // NO_SPLIT}// 64x128,128x64else if ((width == 64 && height > 64) || (height == 64 && width > 64)){allowSplitBtHor = 1;    // BT_HORallowSplitBtVer = 1;    // BT_VER}// 右下角的那一块else if (!rightBoundary && !bottomBoundary){allowSplitQt = 1;       // QT}// 右边界else if (rightBoundary){allowSplitBtVer = 1;    // BT_VER}// 下边界else if (bottomBoundary){allowSplitBtHor = 1;    // BT_HOR}}// 不是边界的情况else{// 64x128,128x64if (((width == 64) && (height > 64)) || ((height == 64) && (width > 64))){allowSplitBtHor = 1;    // BT_HORallowSplitBtVer = 1;    // BT_VERallowNoSplit = 1;       // NO_SPLIT}// 如果划分次数太高了else if (split >= MaxSplitTimes){allowNoSplit = 1;       // NO_SPLIT}// I帧:128x128else if ((PictureType == 0) && (width == 128) && (height == 128)){allowSplitQt = 1;       // QTallowNoSplit = 1;       // NO_SPLIT}else{// 当前CU在宽高比8:1的划分范围内if ((width <= height * MaxPartRatio) && (height <= width * MaxPartRatio))allowNoSplit = 1;   // NO_SPLIT// 符合QT划分最小尺寸if ((width > MinQtSize) && qt)allowSplitQt = 1;   // QT// 在BT划分大小范围内,且划分后宽高比符合要求if ((width <= MaxBtSize) && (height <= MaxBtSize) && (width > MinBtSize) && (height < MaxPartRatio * width))allowSplitBtVer = 1;    // BT_VERif ((width <= MaxBtSize) && (height <= MaxBtSize) && (height > MinBtSize) && (width < MaxPartRatio * height))allowSplitBtHor = 1;    // BT_HOR// 在EQT划分大小范围内,且划分后宽高比符合要求if ((width <= MaxEqtSize) && (height <= MaxEqtSize) && (height >= MinEqtSize * 2) && (width >= MinEqtSize * 4) && (height * 4 <= MaxPartRatio * width))allowSplitEqtVer = 1;   // EQT_VERif ((width <= MaxEqtSize) && (height <= MaxEqtSize) && (width >= MinEqtSize * 2) && (height >= MinEqtSize * 4) && (width * 4 <= MaxPartRatio * height))allowSplitEqtHor = 1;   // EQT_HOR}}allowSplitBt = allowSplitBtVer || allowSplitBtHor;allowSplitEqt = allowSplitEqtVer || allowSplitEqtHor;// QT && ( NO_SPLIT || BT || EQT )if (allowSplitQt && (allowNoSplit || allowSplitBt || allowSplitEqt)){qt_split_flag;  // 是否使用QT划分}if (!QtSplitFlag){// NO_SPLIT && ( BT || EQT )if (allowNoSplit && (allowSplitBt || allowSplitEqt)){bet_split_flag;     // 是否使用BT/EQT划分}if (BetSplitFlag){// BT && EQTif (allowSplitBt && allowSplitEqt)bet_split_type_flag;    // 0:BT   1:EQTif ((!BetSplitTypeFlag && allowSplitBtHor && allowSplitBtVer) || (BetSplitTypeFlag && allowSplitEqtHor && allowSplitEqtVer))bet_split_dir_flag;     // 0:HOR  1:VER}}// B/P帧 && [ ( EQT / QT 64pixel ) || ( BT 128pixel ) ]if ((PictureType != 0) && ((((BetSplitFlag && !BetSplitTypeFlag) || QtSplitFlag) && (width * height == 64)) || (BetSplitTypeFlag && (width * height == 128)))){root_cu_mode;        //  0: PRED_Intra_Only  1: PRED_Inter_OnlymodeChild = root_cu_mode ? 'PRED_Intra_Only' : 'PRED_Inter_Only';}else{modeChild = mode;   // 子编码单元的pred_mode继承父编码单元}if (ChildSizeOccur4)    // 划分后CU的宽或高为4 ( 详见 AVS3-FCD2.0 P80 ){if (Component == 0){LumaWidth = width;LumaHeight = height;Component = 1;  // 设置为仅编码亮度分量}}// QT划分模式if (BlockSplitMode == 'SPLIT_QT'){// 子CU的大小QtWidth = width / 2;QtHeight = height / 2;// 中间点的像素坐标x1 = x0 + QtWidth;y1 = y0 + QtHeight;// coding_unit_tree:左上角块coding_unit_tree(x0, y0, split + 1, QtWidth, QtHeight, 1, modeChild);// 右上角块if (x1 < PicWidthInLuma)coding_unit_tree(x1, y0, split + 1, QtWidth, QtHeight, 1, modeChild);// 左下角块if (y1 < PicHeightInLuma)coding_unit_tree(x0, y1, split + 1, QtWidth, QtHeight, 1, modeChild);// 右下角块if ((x1 < PicWidthInLuma) && (y1 < PicHeightInLuma))coding_unit_tree(x1, y1, split + 1, QtWidth, QtHeight, 1, modeChild);// 若ChildSizeOccur4,则为色度CU编码if ((LumaWidth == width) && (LumaHeight = height) && ChildSizeOccur4){coding_unit(x0, y0, width, height, 'PRED_No_Constraint', 'COMPONENT_Chroma');   // 以上4块仅编码luma(line134),本块仅编码chromaComponent = 0;   // 恢复为编码luma_chroma}}// BT_VER划分模式else if (BlockSplitMode == 'SPLIT_BT_VER'){x1 = x0 + width / 2;// 左边块coding_unit_tree(x0, y0, split + 1, width / 2, height, 0, modeChild);// 右边块if (x1 < PicWidthInLuma)coding_unit_tree(x1, y0, split + 1, width / 2, height, 0, modeChild);// 色度块if ((LumaWidth == width) && (LumaHeight = height) && ChildSizeOccur4){coding_unit(x0, y0, width, height, 'PRED_No_Constraint', 'COMPONENT_Chroma');Component = 0;}}// BT_HOR划分模式else if (BlockSplitMode == 'SPLIT_BT_HOR'){y1 = y0 + height / 2;coding_unit_tree(x0, y0, split + 1, width, height / 2, 0, modeChild);if (y1 < PicHeightInLuma)coding_unit_tree(x0, y1, split + 1, width, height / 2, 0, modeChild);if ((LumaWidth == width) && (LumaHeight = height) && ChildSizeOccur4){coding_unit(x0, y0, width, height, 'PRED_No_Constraint', 'COMPONENT_Chroma');Component = 0;}}// EQT_VER划分模式else if (BlockSplitMode == 'SPLIT_EQT_VER'){x1 = x0 + width / 4;x2 = x0 + (3 * width / 4);y1 = y0 + height / 2;coding_unit_tree(x0, y0, split + 1, width / 4, height, 0, modeChild);coding_unit_tree(x1, y0, split + 1, width / 2, height / 2, 0, modeChild);coding_unit_tree(x1, y1, split + 1, width / 2, height / 2, 0, modeChild);coding_unit_tree(x2, y0, split + 1, width / 4, height, 0, modeChild);if ((LumaWidth == width) && (LumaHeight = height) && ChildSizeOccur4){coding_unit(x0, y0, width, height, 'PRED_No_Constraint', 'COMPONENT_Chroma');Component = 0;}}// EQT_HOR划分模式else if (BlockSplitMode == 'SPLIT_EQT_HOR'){x1 = x0 + width / 2;y1 = y0 + height / 4;y2 = y0 + (3 * height / 4);coding_unit_tree(x0, y0, split + 1, width, height / 4, 0, modeChild);coding_unit_tree(x0, y1, split + 1, width / 2, height / 2, 0, modeChild);coding_unit_tree(x1, y1, split + 1, width / 2, height / 2, 0, modeChild);coding_unit_tree(x0, y2, split + 1, width, height / 4, 0, modeChild);if ((LumaWidth == width) && (LumaHeight = height) && ChildSizeOccur4){coding_unit(x0, y0, width, height, 'PRED_No_Constraint', 'COMPONENT_Chroma');Component = 0;}}// NO_SPLIT划分模式else{// 可包含亮度分量和色度分量if (Component == 0){coding_unit(x0, y0, width, height, mode, 'COMPONENT_LUMACHROMA');}// 仅有亮度分量else if (Component == 1){coding_unit(x0, y0, width, height, mode, 'COMPONENT_LUMA');}}
}

编码单元:coding_unit

/* CU的像素坐标,CU大小,预测模式,分量 */
coding_unit(x0, y0, width, height, mode, component)
{// 色度分量if (component == 'COMPONENT_Chroma'){// priorCuMode:当前色度块对应的亮度块右下角4x4的子块为帧内模式if ((priorCuMode == 1) && (chroma_format != '00'))intra_chroma_pred_mode;      // 帧内色度预测模式NumOfTransBlocks = 3;ctp_y[0] = 0;CuCtp += ctp_y[0];// 若色度预测模式不是PCMif (IntraChromaPredMode != 'Intra_Chroma_PCM'){ctp_u;CuCtp += (ctp_u << 1);ctp_v;CuCtp += (ctp_v << 2);}// 编码U、V变换块for (i = NumOfTransBlocks - 2; i < NumOfTransBlocks; i++){IsPcmMode[i] = (IntraChromaPredMode == 'Intra_Chroma_PCM');IsChroma = 0;if (i == NumOfTransBlocks - 1 || i == NumOfTransBlocks - 2){IsChroma = 1;}// 变换块block(i, width, height, CuCtp, IsChroma, IsPcmMode[i], component);}}// LUMA或LUMACHROMAelse{// 若不是I帧if (PictureType != 0){if (mode != 'PRED_Intra_Only'){skip_flag;       // Skip模式标志}// Skip模式下:编码umve和affine模式if (SkipFlag){if (UmveEnableFlag)umve_flag;// affine与umve不能共存,且需要宽高都大于16if (AffineEnableFlag && !UmveFlag && (width >= 16) && (height >= 16))affine_flag;}// 非Skip模式下if (!SkipFlag){if (mode != 'PRED_Intra_Only'){direct_flag;  // direct模式标志}// Direct模式下:编码umve和affine模式if (DirectFlag){if (UmveEnableFlag)umve_flag;if (AffineEnableFlag && !UmveFlag && (width >= 16) && (height >= 16))affine_flag;}// 非Direct模式下:if (!DirectFlag && (mode == 'PRED_No_Constraint'))intra_cu_flag;   // 0:帧间模式    1:帧内模式}}PartSize = 'SIZE_2Mx2N';// 若衍生模式和帧内模式if (DtEnableFlag && IntraCuFlag){// CU符合DT划分的要求( 其中DtMinSize的值等于16 )allowDtHorSplit = (height >= DtMinSize) && (height <= DtMaxSize) && (width / height < 4) && (width <= DtMaxSize);allowDtVerSplit = (width >= DtMinSize) && (width <= DtMaxSize) && (height / width < 4) && (height <= DtMaxSize);if (allowDtHorSplit || allowDtVerSplit){dt_split_flag;        // 是否进行衍生划分if (DtSplitFlag){if (allowDtHorSplit && allowDtVerSplit){dt_split_dir;   // 0:垂直划分  1:水平划分}else if (allowDtHorSplit){DtSplitDir = 1;}else{DtSplitDir = 0;}if (DtSplitDir){dt_split_hqt_flag;     // 水平四叉划分:0表示不进行,1表示进行if (!DtSplitHqtFlag){dt_split_hadt_flag;    // 水平非对称划分:0表示up,1表示down}}else{dt_split_vqt_flag;if (!DtSplitVqtFlag){dt_split_vadt_flag;}}}}}// umve标识if (UmveFlag){umve_mv_idx;umve_step_idx;umve_dir_idx;}// skip/direct前提下的affineelse if ((SkipFlag || DirectFlag) && AffineFlag){cu_affine_cand_idx;}// skip/directelse if (SkipFlag || DirectFlag){cu_subtype_index;    // CU子类型索引}// 非Skip,非Directif (!SkipFlag && !DirectFlag){// 普通inter模式if (!IntraCuFlag){// affineif (AffineEnableFlag && (width >= 16) && (height >= 16))affine_flag;// amvrif (AmvrEnableFlag){if (EmvrEnableFlag && !AffineFlag){extend_mvr_flag;   // emvr}if (AffineFlag)affine_amvr_index;elseamvr_index;}// B帧预测参考模式:list 0/1/01if (PictureType == 2){inter_pred_ref_mode;}// smvdif (SmvdEnableFlag && SmvdApplyFlag && !AffineFlag && (InterPredRefMode == 2) && !ExtendMvrFlag){smvd_flag;}// MvExistL0:这部分暂时不懂if (MvExistL0){if (!SmvdFlag && NumRefActive[0] > 1)pu_reference_index_l0;mv_diff_x_abs_l0;if (MvDiffXAbsL0)mv_diff_x_sign_l0;mv_diff_y_abs_l0;if (MvDiffYAbsL0)mv_diff_y_sign_l0;if (AffineFlag){mv_diff_x_abs_l0_affine;if (MvDiffXAbsL0Affine)mv_diff_x_sign_l0_affine;mv_diff_y_abs_l0_affine;if (MvDiffYAbsL0Affine)mv_diff_y_sign_l0_affine;}}if (MvExistL1 && !SmvdFlag){if (NumRefActive[1] > 1)pu_reference_index_l1;mv_diff_x_abs_l1;if (MvDiffXAbsL1)mv_diff_x_sign_l1;mv_diff_y_abs_l1;if (MvDiffYAbsL1)mv_diff_y_sign_l1;if (AffineFlag){mv_diff_x_abs_l1_affine;if (MvDiffXAbsL1Affine)mv_diff_x_sign_l1_affine;mv_diff_y_abs_l1_affine;if (MvDiffYAbsL1Affine)mv_diff_y_sign_l1_affine;}}}// 帧内模式else{TuOrder = 0;// NumOfIntraPredBlock由衍生模式确定for (i = 0; i < NumOfIntraPredBlock; i++){intra_luma_pred_mode;  // 每个亮度PU的预测模式}if (PartSize == 'SIZE_2Mx2N'){IsPcmMode[TuOrder] = (IntraLumaPredMode == 'Intra_Luma_PCM');TuOrder++;}else{IsPcmMode[0] = 0;IsPcmMode[1] = 0;IsPcmMode[2] = 0;IsPcmMode[3] = 0;TuOrder = 3;}// 若为COMPONENT_LUMACHROMAif (IntraCuFlag && (chroma_format != '00') && (component == 'COMPONENT_LUMACHROMA')){intra_chroma_pred_mode;     // 色度PU的预测模式IsPcmMode[TuOrder + 1] = (IntraChromaPredMode == 'Intra_Chroma_PCM');IsPcmMode[TuOrder + 2] = (IntraChromaPredMode == 'Intra_Chroma_PCM');}if (IpfEnableFlag && (PartSize == 'SIZE_2Mx2N') && (!IsPcmMode[0])){ipf_flag;        // IPF滤波标志}}}// 非帧内,非Skip if (!IntraCuFlag && !SkipFlag){if (!DirectFlag && component == 'COMPONENT_LUMACHROMA')ctp_zero_flag;   // 1:变换块系数全为0CuCtp = 0;if (!CtpZeroFlag){// 宽高在8~32,宽高比小于4if (PbtEnableFlag && (width / height < 4) && (height / width < 4) && (width >= 8) && (width <= 32) && (height >= 8) && (height <= 32)){pbt_cu_flag;  // 基于位置的变换标志}// 不使用pbt变换,NumOfTransBlocks = 3if (!PbtCuFlag){if (component == 'COMPONENT_LUMACHROMA'){ctp_u;ctp_v;}CuCtp = ctp_u << (NumOfTransBlocks - 2);CuCtp += (ctp_v << (NumOfTransBlocks - 1));if (((ctp_u != 0) || (ctp_v != 0)) || (component != 'COMPONENT_LUMACHROMA')){ctp_y[0];CuCtp += ctp_y[0];}else{CuCtp += ctp_y[0];}}// 使用pbt变换,NumOfTransBlocks = 6else{if (component == 'COMPONENT_LUMACHROMA'){ctp_u;ctp_v;}CuCtp = ctp_u << (NumOfTransBlocks - 2);CuCtp += (ctp_v << (NumOfTransBlocks - 1));for (i = 0; i < NumOfTransBlocks - 2; i++){ctp_y[i];CuCtp += (ctp_y[i] << i);}// 此时CuCtp为 YYYYUV}}}// 帧内模式else if (!SkipFlag){CuCtp = 0;if (!IsPcmMode[0]){for (i = 0; i < NumOfTransBlocks - 2; i++){ctp_y[i];CuCtp += (ctp_y[i] << i);}}if ((component == 'COMPONENT_LUMACHROMA') && (IntraChromaPredMode != 'Intra_Chroma_PCM')){ctp_u;ctp_v;}CuCtp += (ctp_u << (NumOfTransBlocks - 2));CuCtp += (ctp_v << (NumOfTransBlocks - 1));}// 变换块for (i = 0; i < NumOfTransBlocks; i++){if (i < NumOfTransBlocks){// TransformSplitDirection:0不划分,1pbt,2水平,3垂直blockWidth = ((TransformSplitDirection == 0) || (TransformSplitDirection == 2)) ? width : (TransformSplitDirection == 1 ? width >> 1 : width >> 2);blockHeight = ((TransformSplitDirection == 0) || (TransformSplitDirection == 3)) ? height : (TransformSplitDirection == 1 ? height >> 1 : height >> 2);blockX = x0 + (((TransformSplitDirection == 0) || (TransformSplitDirection == 2)) ? 0 : (TransformSplitDirection == 1 ? ((blockWidth >> 1) * (i % 2)) : ((blockWidth >> 2) * i)));blockY = y0 + (((TransformSplitDirection == 0) || (TransformSplitDirection == 3)) ? 0 : (TransformSplitDirection == 1 ? ((blockHeight >> 1) * (i / 2)) : ((blockHeight >> 2) * i)))}IsChroma = 0;if (i == NumOfTransBlocks - 1 || i == NumOfTransBlocks - 2){IsChroma = 1;}block(i, blockWidth, blockHeight, CuCtp, IsChroma, IsPcmMode[i], component);}}
}

 变换单元:block

/* 块编号,块大小,该块是否含有编码数据,是否为色度分量,是否使用PCM,分量信息 */
block(i, blockWidth, blockHeight, CuCtp, isChroma, isPcm, component)
{M1 = blockWidth;M2 = blockHeight;// 初始化量化系数矩阵为0for (x = 0; x < M1; x++){for (y = 0; y < M2; y++)QuantCoeffMatrix[x][y] = 0;}// 非PCM模式if (!isPcm){// i号块有编码数据if (CuCtp & (1 << i)){blockWidth = isChroma ? blockWidth / 2 : blockWidth;blockHeight = isChroma ? blockHeight / 2 : blockHeight;idxW = Log(blockWidth) – 1;idxH = Log(blockHeight) – 1;NumOfCoeff = blockWidth * blockHeight;ScanPosOffset = 0;do{coeff_run;              // runcoeff_level_minus1;     // levelcoeff_sign;             // level_signAbsLevel = coeff_level_minus1 + 1;ScanPosOffset = ScanPosOffset + coeff_run;PosxInBlk = InvScanCoeffInBlk[idxW][idxH][ScanPosOffset][0];PosyInBlk = InvScanCoeffInBlk[idxW][idxH][ScanPosOffset][1];QuantCoeffMatrix[PosxInBlk][PosyInBlk] = coeff_sign ? –AbsLevel : AbsLevel;if (ScanPosOffset >= NumOf Coeff – 1){break;}coeff_last;             // coeff_lastScanPosOffset = ScanPosOffset + 1;} while (!coeff_last)}}// PCM模式else{// 填充位if ((component != 'COMPONENT_CHROMA' && i == 0) || (component == 'COMPONENT_CHROMA' && i == 1)){aec_ipcm_stuffing_bit;while (!byte_aligned()){aec_byte_alignment_bit0;}}// 色度TU大小为一半M1 = isChroma ? blockWidth / 2 : blockWidth;M2 = isChroma ? blockHeight / 2 : blockHeight;xMin = Min(32, M1);yMin = Min(32, M2);// 分为32x32的块依次编码for (yStep = 0; yStep < M2 / yMin; yStep++){for (xStep = 0; xStep < M1 / xMin; xStep++){for (y = 0; y < yMin; y++){for (x = 0; x < xMin; x++){pcm_coeff;QuantCoeffMatrix[x + xStep * xMin][y + yStep * yMin] = pcm_coeff;}}}}}
}

如果文章对您有帮助,记得点个赞哦 o(* ̄▽ ̄*)ブ

AVS3码流结构解析相关推荐

  1. H.264码流结构解析

    大概前五六年之前写过的一个大体分析H.264格式,不是很详细,可以大致看看有哪些格式.  H.264码流结构解析 那个时候上传的百度文库,以前记得有多积分,现在都不能下载了,还要充钱才可以.真是~~~ ...

  2. 【AV1 spec学习一】OBU类型及码流结构

    [AV1 spec学习一]OBU类型及码流结构 基本概念 基本语法表示形式 OBU类型 码流结构 基本概念 刚开始看AV1 spec,对一些初见的名词在此做些记录,随见随添. 缩写 全称 含义 OBU ...

  3. H.264码流结构及JM8.6中码流的产生步骤

    整理自:http://www.cnblogs.com/xkfz007/archive/2012/08/12/2612931.html H.264中的码流结构 H.264码流结构示意图: NALU第一字 ...

  4. JavaCV音视频开发宝典:使用JavaCV读取海康平台或海康网络摄像头sdk回调视频TS码流并解析预览图像

    <JavaCV音视频开发宝典>专栏目录导航 <JavaCV音视频开发宝典>专栏介绍和目录 ​ 前言 两年前博主写了如何利用JavaCV解析各种h264裸流,<JavaCV ...

  5. 【mpeg】mpeg1、mpeg2与mpeg4码流结构区别分析

    Date: 2018.10.25 1.参考 http://www.cnblogs.com/CoderTian/p/9246225.html 2.前言     最近在学习和研究MPEG-2标准的过程中, ...

  6. JavaCV音视频开发宝典:使用JavaCV读取海康平台或海康网络摄像头sdk回调录像回放视频PS码流并解析预览图像

    <JavaCV音视频开发宝典>专栏目录导航 <JavaCV音视频开发宝典>专栏介绍和目录 ​ 前言 上一章中<JavaCV音视频开发宝典:使用JavaCV读取海康平台或海 ...

  7. H.264中NALU、RBSP、SODB的关系 (弄清码流结构)

    NALU:Coded H.264 data is stored or transmitted as a series of packets known as NetworkAbstraction La ...

  8. H264码流NALU解析

    包 package h264import ("sync"log "github.com/sirupsen/logrus" )const (DEFAULT_CAP ...

  9. 【音视频数据数据处理 12】【H.264篇】解析H.264原始码流中的I帧 / P帧 / B帧数据(暂未解决,本文先放着,来日更新)

    [音视频数据数据处理 12][H.264篇]解析H.264原始码流中的I帧 / P帧 / B帧数据 一.如何判断是 I帧 / P帧 / B帧 1.1 slice_type 1.2 slice_head ...

最新文章

  1. windows ssh secure shell设置初始窗口大小
  2. 大闸蟹谋定功能性养殖-丰收节交易会·李喜贵: 科技示范基地
  3. 【推导】【NTT】hdu6061 RXD and functions(NTT)
  4. [转].NET 数字格式化:忽略末尾零
  5. 光环大数据spark文档_推荐大数据Spark必读书目
  6. 从单亲家庭内向小男生到哈佛耶鲁全奖,百万年薪的“男神学长”活出了一部励志偶像剧!
  7. [JavaWeb基础] 015.Struts2 表单验证框架
  8. 16 年前,Google 为何花 5000 万美元买下 Android?
  9. 调查问卷Html5发展综述
  10. 随身WiFi刷OPENWRT作为旁路由
  11. 用SAI的时候笔会自动取色,画个草稿都画不下去怎么办
  12. spss java vm_如何解决spss无法创建java虚拟机的问题
  13. win7 win10 配置共享文件夹
  14. 最新 行政区划 省市区 历史版 2022 年
  15. IT部门绩效考核管理思考
  16. 语雀可以导出html吗,工具 - Confluence 迁移到语雀 - 《语雀使用文档》 - 书栈网 · BookStack...
  17. 【PM杂谈】我理解的项目管理
  18. 微信小程序 slot插槽基本使用
  19. java verify_java – 什么时候使用Mockito.verify()?
  20. win10系统警告unknown hard error开不了机怎么办

热门文章

  1. 关于在13个球中寻找不同的问题解答
  2. 如何实现电脑通过手机上网?1分钟搞定!
  3. 计算机的职业形象,计算机专业科开展学生干部职业形象塑造专题培训
  4. Kermit文件传输协议
  5. 小程序性能优化之页面预加载方案——让你的小程序运行如飞 进阶篇
  6. windows10计算机里输入法,win10电脑上输入法不见了怎么办
  7. IPv6连接类型Native Static、Native DHCPv6、Tunnel 6in4、Tunnel 6to4、Tunnel 6rd的区别
  8. vs2010没有新建项目的解决方法
  9. VUE-CLI/VUE-ROUTER
  10. 1.27 Daisy Chains(花瓣)