openh264 帧内预测编码原理:WelsMdI4x4Fast 函数

介绍

  • 说明:该函数内部原理类似WelsMdI4x4函数,具体可以参考:openh264 帧内预测编码原理:WelsMdI4x4 函数。
  1. 功能:针对4x4像素块的帧内模式决策的快速实现逻辑
  2. 原型
int32_t WelsMdI4x4Fast (sWelsEncCtx* pEncCtx, SWelsMD* pWelsMd, SMB* pCurMb, SMbCache* pMbCache)
  1. 参数
  • pEncCtx: 指向编码上下文的指针。
  • pWelsMd: 指向模式决策结构的指针。
  • pCurMb: 指向当前宏块的指针。
  • pMbCache: 指向宏块缓存的指针。

函数关系图

在这里插入图片描述

原理

  1. 过程
  • 初始化变量;
  • for 循环每个 4x4 块,进行预测分析;
    • 计算当前4x4块在编码宏块pEncMb和解码宏块pDecMb中的位置。这是通过iCoordinateX和iCoordinateY(4x4块在宏块中的相对位置)以及宏块的行大小kiLineSizeEnc和kiLineSizeDec来实现的;
    • PredIntra4x4Mode函数根据当前块的扫描顺序索引kpCache48CountScan4[i]和缓存的内插值模式pMbCache->iIntraPredMode来预测当前块的模式;
    • 根据kiOffset(当前块的邻居关系)确定有多少可用的预测模式(iAvailCount),并获取这些模式的数组kpAvailMode;
    • 如果iAvailCount等于 9 或者等于 7,
      • 初始化最佳模式iBestMode为 DC;
      • pfGetLumaI4x4Pred计算 DC 模式下的预测块,pfMdCost函数计算出最佳模式iBestMode和最佳代价iBestCost;
      • 初始化当前模式iCurMode为 水平 H,
        • pfGetLumaI4x4Pred计算 H 模式下的预测块,pfMdCost函数计算出当前模式下当前代价iCurCost和水平代价iCostH;
        • 比较当前代价iCurCost和最佳代价iBestCost,更新最佳代价iBestCost和最佳模式iBestMode;
      • 初始化当前模式iCurMode为 垂直 V,
        • pfGetLumaI4x4Pred计算 V 模式下的预测块,pfMdCost函数计算出当前模式下当前代价iCurCost和垂直代价iCostV;
        • 比较当前代价iCurCost和最佳代价iBestCost,更新最佳代价iBestCost和最佳模式iBestMode;
      • 如果垂直代价iCostV 小于 水平代价iCostH,
        • 如果可预测模式数量iAvailCount等于 9,
          • 分别计算I4_PRED_VR、I4_PRED_VL、I4_PRED_DDR、I4_PRED_DDL模式下的代价,选择最佳模式iBestMode和最佳代价iBestCost;
        • 如果可预测模式数量iAvailCount等于 7,
          • 分别计算I4_PRED_DDR、I4_PRED_VR模式下的代价,选择最佳模式iBestMode和最佳代价iBestCost;
      • 否则,
        • 有条件的计算I4_PRED_HD、I4_PRED_HU、I4_PRED_DDR、I4_PRED_DDL模式下的代价,选择最佳模式iBestMode和最佳代价iBestCost;
    • 否则,
      • for 循环遍历每种可能模式;
        • 根据索引从可用模式中指向当前模式iCurMode;
        • 根据 iBestPredBufferNum 的当前值,更新 pDst 指向另一个缓冲区,以便为下一个模式生成预测;
        • fGetLumaI4x4Pred[iCurMode] 函数根据当前模式生成预测块;
        • 使用 pfSampleSatd 函数计算预测块和原始编码块之间的绝对变换差分和(SATD)作为当前预测模式的代价iCurCost;
        • 比较iCurCost和iBestCost,更新iBestMode、iBestCost,并切换 iBestPredBufferNum 以指向当前最佳的预测块;
    • pBestPredI4x4Blk4 被设置为指向当前最佳预测块的内存地址;
    • 将当前最佳模式的成本 iBestCost 加到总成本 iCosti4x4 上;
    • 如果到目前为止累积的成本 iCosti4x4 大于或等于之前计算的亮度成本 iBestCostLuma,则break退出循环。这是因为继续计算其他模式不太可能找到更低的成本,从而节省计算资源;
    • 更新预测模式和样本可用性缓存;
      • iFinalMode 是将 iBestMode 通过一个映射表 g_kiMapModeI4x4 转换后的模式值;
      • 根据当前预测模式 iPredMode 和最终模式 iFinalMode 的比较结果,更新 pPrevIntra4x4PredModeFlag 缓存。如果它们相等,则设置为 true,否则设置为 false,同时更新
        pRemIntra4x4PredModeFlag;
      • pRemIntra4x4PredModeFlag 指针递增,为下一个模式的更新做准备;
      • 将 iFinalMode 更新到 pMbCache->iIntraPredMode 中,这是当前4x4块的内插值预测模式缓存。这个缓存用于后续的编码过程;
    • 调用 WelsEncRecI4x4Y 函数对确定最佳预测模式的当前4x4块进行编码。这个函数会进行实际的变换、量化和重建操作;
  • 调用宏ST32、LD32函数将 pMbCache->iIntraPredMode 数组中从索引33开始的32位值复制到 pCurMb->pIntra4x4PredMode 的起始位置;常是将计算得到的内插值预测模式复制到宏块的正式存储区域;
  • 将缓存pMbCache中特定位置赋值给当前宏块pCurMb中预测模式,由于在宏块中的特定位置需要特定的预测模式值;
  • iCosti4x4 变量增加了一个基于量化参数 iLambda 的值;
  • 返回总成本iCosti4x4。
  1. 原理图
    在这里插入图片描述

源码

int32_t WelsMdI4x4Fast (sWelsEncCtx* pEncCtx, SWelsMD* pWelsMd, SMB* pCurMb, SMbCache* pMbCache) {SWelsFuncPtrList* pFunc       = pEncCtx->pFuncList;SDqLayer* pCurDqLayer         = pEncCtx->pCurDqLayer;int32_t iLambda               = pWelsMd->iLambda;int32_t iBestCostLuma         = pWelsMd->iCostLuma;uint8_t* pEncMb               = pMbCache->SPicData.pEncMb[0];uint8_t* pDecMb               = pMbCache->SPicData.pCsMb[0];const int32_t kiLineSizeEnc   = pCurDqLayer->iEncStride[0];const int32_t kiLineSizeDec   = pCurDqLayer->iCsStride[0];uint8_t* pCurEnc, *pCurDec, *pDst;int8_t iPredMode, iCurMode, iBestMode, iFinalMode;int32_t iCurCost, iBestCost;int32_t iAvailCount;const uint8_t* kpAvailMode;int32_t i, j, iCoordinateX, iCoordinateY, iIdxStrideEnc, iIdxStrideDec;int32_t iCostH, iCostV, iCostVR, iCostHD, iCostVL, iCostHU, iBestModeFake;int32_t lambda[2] = {iLambda << 2, iLambda};bool* pPrevIntra4x4PredModeFlag       = pMbCache->pPrevIntra4x4PredModeFlag;int8_t* pRemIntra4x4PredModeFlag      = pMbCache->pRemIntra4x4PredModeFlag;const uint8_t* kpIntra4x4AvailCount   = &g_kiIntra4AvailCount[0];const uint8_t* kpCache48CountScan4    = &g_kuiCache48CountScan4Idx[0];const int8_t* kpNeighborIntraToI4x4   = g_kiNeighborIntraToI4x4[pMbCache->uiNeighborIntra];const int8_t* kpCoordinateIdxX        = &g_kiCoordinateIdx4x4X[0];const int8_t* kpCoordinateIdxY        = &g_kiCoordinateIdx4x4Y[0];int32_t iBestPredBufferNum            = 0;int32_t iCosti4x4                     = 0;
#if defined(X86_ASM)WelsPrefetchZero_mmx (g_kiMapModeI4x4);WelsPrefetchZero_mmx ((int8_t*)&pFunc->pfGetLumaI4x4Pred);
#endif//X86_ASMfor (i = 0; i < 16; i++) {const int32_t kiOffset = kpNeighborIntraToI4x4[i];
//    const int32_t i_next = (1+i) & 15; // next loop
//    const uint8_t dummy_byte= pIntra4x4AvailCount[pNeighborIntraToI4x4[i_next]]; // prefetch pIntra4x4AvailCount of next loop to avoid cache missed//step 1: locating current 4x4 block position in pEnc and pDecMbiCoordinateX = kpCoordinateIdxX[i];iCoordinateY = kpCoordinateIdxY[i];iIdxStrideEnc = (iCoordinateY * kiLineSizeEnc) + iCoordinateX;pCurEnc = pEncMb + iIdxStrideEnc;iIdxStrideDec = (iCoordinateY * kiLineSizeDec) + iCoordinateX;pCurDec = pDecMb + iIdxStrideDec;//step 2: get predicted mode from neighboriPredMode = PredIntra4x4Mode (pMbCache->iIntraPredMode, kpCache48CountScan4[i]);//step 3: collect candidates of iPredModeiAvailCount = kpIntra4x4AvailCount[kiOffset];kpAvailMode = g_kiIntra4AvailMode[kiOffset];if (iAvailCount == 9 || iAvailCount == 7) {//I4_PRED_DC(2)iBestMode = I4_PRED_DC;pDst = &pMbCache->pMemPredBlk4[iBestPredBufferNum << 4];pFunc->pfGetLumaI4x4Pred[I4_PRED_DC] (pDst, pCurDec, kiLineSizeDec);iBestCost = pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_4x4] (pDst, 4, pCurEnc, kiLineSizeEnc) +lambda[iPredMode == g_kiMapModeI4x4[iBestMode]];//I4_PRED_H(1)iCurMode = I4_PRED_H;pDst = &pMbCache->pMemPredBlk4[ (1 - iBestPredBufferNum) << 4];pFunc->pfGetLumaI4x4Pred[iCurMode] (pDst, pCurDec, kiLineSizeDec);iCostH = iCurCost = pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_4x4] (pDst, 4, pCurEnc, kiLineSizeEnc) +lambda[iPredMode == g_kiMapModeI4x4[iCurMode]];if (iCurCost < iBestCost) {iBestMode = iCurMode;iBestCost = iCurCost;iBestPredBufferNum = 1 - iBestPredBufferNum;}//I4_PRED_V(0)iCurMode = I4_PRED_V;pDst = &pMbCache->pMemPredBlk4[ (1 - iBestPredBufferNum) << 4];pFunc->pfGetLumaI4x4Pred[iCurMode] (pDst, pCurDec, kiLineSizeDec);iCostV = iCurCost = pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_4x4] (pDst, 4, pCurEnc, kiLineSizeEnc) +lambda[iPredMode == g_kiMapModeI4x4[iCurMode]];if (iCurCost < iBestCost) {iBestMode = iCurMode;iBestCost = iCurCost;iBestPredBufferNum = 1 - iBestPredBufferNum;}if (iCostV < iCostH) {if (iAvailCount == 9) {iBestModeFake = true; //indicating whether V is the best fake mode//I4_PRED_VR(5) and I4_PRED_VL(7)iCurMode = I4_PRED_VR;pDst = &pMbCache->pMemPredBlk4[ (1 - iBestPredBufferNum) << 4];pFunc->pfGetLumaI4x4Pred[iCurMode] (pDst, pCurDec, kiLineSizeDec);iCostVR = iCurCost = pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_4x4] (pDst, 4, pCurEnc, kiLineSizeEnc) +lambda[iPredMode == g_kiMapModeI4x4[iCurMode]];if (iCurCost < iBestCost) {iBestMode = iCurMode;iBestCost = iCurCost;iBestPredBufferNum = 1 - iBestPredBufferNum;}if (iCurCost < iCostV)iBestModeFake = false;iCurMode = I4_PRED_VL;pDst = &pMbCache->pMemPredBlk4[ (1 - iBestPredBufferNum) << 4];pFunc->pfGetLumaI4x4Pred[iCurMode] (pDst, pCurDec, kiLineSizeDec);iCostVL = iCurCost = pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_4x4] (pDst, 4, pCurEnc, kiLineSizeEnc) +lambda[iPredMode == g_kiMapModeI4x4[iCurMode]];if (iCurCost < iBestCost) {iBestMode = iCurMode;iBestCost = iCurCost;iBestPredBufferNum = 1 - iBestPredBufferNum;}if (iCurCost < iCostV)iBestModeFake = false;//Vertical Early Determinationif (!iBestModeFake) { //Vertical is not the best, go on checking...//select the best one from VL and VRif (iCostVR < iCostVL) {//I4_PRED_DDR(4)iCurMode = I4_PRED_DDR;pDst = &pMbCache->pMemPredBlk4[ (1 - iBestPredBufferNum) << 4];pFunc->pfGetLumaI4x4Pred[iCurMode] (pDst, pCurDec, kiLineSizeDec);iCurCost = pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_4x4] (pDst, 4, pCurEnc, kiLineSizeEnc) +lambda[iPredMode == g_kiMapModeI4x4[iCurMode]];if (iCurCost < iBestCost) {iBestMode = iCurMode;iBestCost = iCurCost;iBestPredBufferNum = 1 - iBestPredBufferNum;}} else {//I4_PRED_DDL(3)iCurMode = I4_PRED_DDL;pDst = &pMbCache->pMemPredBlk4[ (1 - iBestPredBufferNum) << 4];pFunc->pfGetLumaI4x4Pred[iCurMode] (pDst, pCurDec, kiLineSizeDec);iCurCost = pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_4x4] (pDst, 4, pCurEnc, kiLineSizeEnc) +lambda[iPredMode == g_kiMapModeI4x4[iCurMode]];if (iCurCost < iBestCost) {iBestMode = iCurMode;iBestCost = iCurCost;iBestPredBufferNum = 1 - iBestPredBufferNum;}}}} else if (iAvailCount == 7) {iCurMode = I4_PRED_DDR;pDst = &pMbCache->pMemPredBlk4[ (1 - iBestPredBufferNum) << 4];pFunc->pfGetLumaI4x4Pred[iCurMode] (pDst, pCurDec, kiLineSizeDec);iCurCost = pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_4x4] (pDst, 4, pCurEnc, kiLineSizeEnc) +lambda[iPredMode == g_kiMapModeI4x4[iCurMode]];if (iCurCost < iBestCost) {iBestMode = iCurMode;iBestCost = iCurCost;iBestPredBufferNum = 1 - iBestPredBufferNum;}iCurMode = I4_PRED_VR;pDst = &pMbCache->pMemPredBlk4[ (1 - iBestPredBufferNum) << 4];pFunc->pfGetLumaI4x4Pred[iCurMode] (pDst, pCurDec, kiLineSizeDec);iCurCost = pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_4x4] (pDst, 4, pCurEnc, kiLineSizeEnc) +lambda[iPredMode == g_kiMapModeI4x4[iCurMode]];if (iCurCost < iBestCost) {iBestMode = iCurMode;iBestCost = iCurCost;iBestPredBufferNum = 1 - iBestPredBufferNum;}}} else {iBestModeFake = true; //indicating whether H is the best fake mode//I4_PRED_HD(6) and I4_PRED_HU(8)iCurMode = I4_PRED_HD;pDst = &pMbCache->pMemPredBlk4[ (1 - iBestPredBufferNum) << 4];pFunc->pfGetLumaI4x4Pred[iCurMode] (pDst, pCurDec, kiLineSizeDec);iCostHD = iCurCost = pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_4x4] (pDst, 4, pCurEnc, kiLineSizeEnc) +lambda[iPredMode == g_kiMapModeI4x4[iCurMode]];if (iCurCost < iBestCost) {iBestMode = iCurMode;iBestCost = iCurCost;iBestPredBufferNum = 1 - iBestPredBufferNum;}if (iCurCost < iCostH)iBestModeFake = false;iCurMode = I4_PRED_HU;pDst = &pMbCache->pMemPredBlk4[ (1 - iBestPredBufferNum) << 4];pFunc->pfGetLumaI4x4Pred[iCurMode] (pDst, pCurDec, kiLineSizeDec);iCostHU = iCurCost = pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_4x4] (pDst, 4, pCurEnc, kiLineSizeEnc) +lambda[iPredMode == g_kiMapModeI4x4[iCurMode]];if (iCurCost < iBestCost) {iBestMode = iCurMode;iBestCost = iCurCost;iBestPredBufferNum = 1 - iBestPredBufferNum;}if (iCurCost < iCostH)iBestModeFake = false;if (!iBestModeFake) { //Horizontal is not the best, go on checking...//select the best one from VL and VRif (iCostHD < iCostHU) {//I4_PRED_DDR(4)iCurMode = I4_PRED_DDR;pDst = &pMbCache->pMemPredBlk4[ (1 - iBestPredBufferNum) << 4];pFunc->pfGetLumaI4x4Pred[iCurMode] (pDst, pCurDec, kiLineSizeDec);iCurCost = pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_4x4] (pDst, 4, pCurEnc, kiLineSizeEnc) +lambda[iPredMode == g_kiMapModeI4x4[iCurMode]];if (iCurCost < iBestCost) {iBestMode = iCurMode;iBestCost = iCurCost;iBestPredBufferNum = 1 - iBestPredBufferNum;}} else if (iAvailCount == 9) {//I4_PRED_DDL(3)iCurMode = I4_PRED_DDL;pDst = &pMbCache->pMemPredBlk4[ (1 - iBestPredBufferNum) << 4];pFunc->pfGetLumaI4x4Pred[iCurMode] (pDst, pCurDec, kiLineSizeDec);iCurCost = pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_4x4] (pDst, 4, pCurEnc, kiLineSizeEnc) +lambda[iPredMode == g_kiMapModeI4x4[iCurMode]];if (iCurCost < iBestCost) {iBestMode = iCurMode;iBestCost = iCurCost;iBestPredBufferNum = 1 - iBestPredBufferNum;}}}}} else {iBestCost = INT_MAX;iBestMode = I4_PRED_INVALID;for (j = 0; j < iAvailCount; j++) {// I4x4_MODE_CHECK(pAvailMode[j], iCurCost);iCurMode = kpAvailMode[j];pDst = &pMbCache->pMemPredBlk4[ (1 - iBestPredBufferNum) << 4];pFunc->pfGetLumaI4x4Pred[iCurMode] (pDst, pCurDec, kiLineSizeDec);iCurCost = pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_4x4] (pDst, 4, pCurEnc, kiLineSizeEnc) +lambda[iPredMode == g_kiMapModeI4x4[iCurMode]];if (iCurCost < iBestCost) {iBestMode = iCurMode;iBestCost = iCurCost;iBestPredBufferNum = 1 - iBestPredBufferNum;}}}pMbCache->pBestPredI4x4Blk4 = &pMbCache->pMemPredBlk4[iBestPredBufferNum << 4];iCosti4x4 += iBestCost;if (iCosti4x4 >= iBestCostLuma) {break;}//step 5: update pred mode and sample avail cacheiFinalMode = g_kiMapModeI4x4[iBestMode];if (iPredMode == iFinalMode) {*pPrevIntra4x4PredModeFlag++ = true;} else {*pPrevIntra4x4PredModeFlag++ = false;*pRemIntra4x4PredModeFlag  = (iFinalMode < iPredMode ? iFinalMode : (iFinalMode - 1));}pRemIntra4x4PredModeFlag++;// pCurMb->pIntra4x4PredMode[scan4[i]] = iFinalMode;pMbCache->iIntraPredMode[kpCache48CountScan4[i]] = iFinalMode;//step 6: encoding I_4x4WelsEncRecI4x4Y (pEncCtx, pCurMb, pMbCache, i);}ST32 (pCurMb->pIntra4x4PredMode, LD32 (&pMbCache->iIntraPredMode[33]));pCurMb->pIntra4x4PredMode[4] = pMbCache->iIntraPredMode[12];pCurMb->pIntra4x4PredMode[5] = pMbCache->iIntraPredMode[20];pCurMb->pIntra4x4PredMode[6] = pMbCache->iIntraPredMode[28];iCosti4x4 += (iLambda << 4) + (iLambda << 3); //4*6*lambda from JVT SATD0return iCosti4x4;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/852664.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

react的自定义组件

// 自定义组件(首字母必须大写) function Button() {return <button>click me</button>; } const Button1()>{return <button>click me1</button>; }// 使用组件 function App() {return (<div className"App">{/* // 自闭和引用自…

React Redux

React Redux是Redux的官方React UI绑定层。它允许您的React组件从Redux存储读取数据&#xff0c;并将操作分派到存储以更新状态。redux是一个管理状态数据state的容器。提供了可预测的状态管理。 React Redux 8.x需要React 16.8.3或更高版本/Rect Native 0.59或更高&#xff0c…

在AMD GPU上加速大型语言模型的Flash Attention

Accelerating Large Language Models with Flash Attention on AMD GPUs — ROCm Blogs 引言 在这篇博客文章中&#xff0c;我们将指导您如何在AMD GPU上安装Flash Attention&#xff0c;并提供与在PyTorch中标准SDPA比较其性能的基准测试。我们还将测量Hugging Face中多个大型…

【Java】解决Java报错:FileNotFoundException

文章目录 引言1. 错误详解2. 常见的出错场景2.1 文件路径错误2.2 文件名拼写错误2.3 文件权限问题2.4 文件路径未正确拼接 3. 解决方案3.1 检查文件路径3.2 使用相对路径和类路径3.3 检查文件权限3.4 使用文件选择器 4. 预防措施4.1 使用配置文件4.2 使用日志记录4.3 使用单元测…

上网行为管理的作用是什么?有哪些上网行为管理软件?

上网行为管理在现代企业及家庭环境中扮演着至关重要的角色&#xff0c;其作用不仅限于提升网络安全性&#xff0c;还涉及保护企业信息安全、提高员工工作效率等多个方面。以下将详细阐述上网行为管理的作用&#xff0c;并介绍几款主流的上网行为管理软件。 一、上网行为管理的作…

Neo4j 桌面版打不开踩坑贴

真的踩坑。。。没有人告诉我为啥桌面版和社区版不能一起下啊&#xff01;&#xff01; 我是先下载了社区版之后再下载的桌面版&#xff0c;结果桌面版界面一直打不开。 尝试了网上多种办法都没效果&#xff0c;好多都是说jdk不兼容导致无法打开&#xff0c;让我从JDK 17 ->…

AUTOSAR平台中的信息安全标准模块

面向MCU端的AUTOSAR CP平台加密组件——Crypto ECU中所有的软件单元都遭受到信息安全攻击的可能。AUTOSAR为保障ECU信息和数据安全&#xff0c;定义了CRYPTO 组件,包含 SecOC、KeyM、IdsM、Csm、CryIf 和Crypto Driver 等标准模块。CRYPTO组件提供各种加解密算法以及密钥管理功…

物联网对智慧驾考应用的价值

随着物联网技术的快速发展&#xff0c;传统行业正经历着前所未有的变革。在智慧驾考领域&#xff0c;4G DTU&#xff08;数据传输单元&#xff09;和工业路由器的应用&#xff0c;不仅提升了考试的规范性和效率&#xff0c;更为驾考行业带来了深远影响。作为工业物联网的资深工…

JVM 类加载器的工作原理

JVM 类加载器的工作原理 类加载器&#xff08;ClassLoader&#xff09;是一个用于加载类文件的子系统&#xff0c;负责将字节码文件&#xff08;.class 文件&#xff09;加载到 JVM 中。Java 类加载器允许 Java 应用程序在运行时动态地加载、链接和初始化类。 2. 类加载器的工…

今年的就业环境不容乐观,你想好怎么应对了吗

今年的就业环境不容乐观&#xff0c;你想好怎么应对了吗 毕业生进入职场的历程往往充满挑战和未知&#xff0c;尤其是在当前经济环境下&#xff0c;失业问题愈发凸显。本文通过分享几位年轻人的真实经历&#xff0c;剖析大学生及职场人士面临的困境&#xff0c;并提供应对策略…

手把手带你搭建一个语音对话机器人,5分钟定制个人AI小助手(新手入门篇)

写在前面 如果你的身边有一个随时待命、聪明绝顶的AI小助手&#xff0c;能够听懂你的话&#xff0c;理解你的需求&#xff0c;用温暖的声音回应你&#xff0c;会是一种什么体验&#xff1f; 今天&#xff0c;带大家一起搭建一个语音对话机器人&#xff0c;拥有一个专属的个人…

games101作业7光线追踪 含多线程和微表面提高

对于光线追踪进行综合运用。 光线与三角形求交 其它的emit那些&#xff0c;现在先不用管&#xff0c;后面看看作用是什么。 inline Intersection Triangle::getIntersection(Ray ray) {Intersection inter;if (dotProduct(ray.direction, normal) > 0)//光线从里面打&…

[Shell编程学习路线]——深入理解Shell编程中的变量(理论与实例)

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f6e0;️Shell编程专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年6月12日11点40分 &#x1f004;️文章质量&#xff1a;95分 文章目录 ————前言———— 1 自定义变量 &#x1fae0;…

Zynq学习笔记--AXI4-Stream到视频输出IP是如何工作的?

目录 1. 简介 2. 原理详解 2.1 示例工程 2.2 AXI4-Stream to Video Out 3. Master/Slave Timing Mode 3.1 Slave Timing Mode 3.2 Master Timing Mode 4. 总结 1. 简介 本文主要介绍了 AXI4-Stream 到视频输出 的内容。其中&#xff0c;示例工程展示了一个具体的设计&…

GitLab教程(五):高效的工作模式——Feature Branching

文章目录 1.什么是Feature Branching2.Feature Branching的Git实践 1.什么是Feature Branching 特性分支&#xff08;Feature Branching&#xff09;是一种软件开发工作流&#xff0c;尤其在使用Git或其他版本控制系统时被广泛采用。这种策略鼓励开发者为每一个新功能、改进或…

推荐一款好用的读论文软件操作方法

步骤&#xff1a; 1. 使用一译 —— 文档和论文翻译、对照阅读、讨论和社区 2.上传自己想要翻译的论文即可。 示例 Planing论文双语翻译 1.1 Parting with Misconceptions about Learning-based Vehicle Motion Planning 中英文对照阅读 1.2 Rethinking Imitation-based Pl…

SCT82A32 是一款 100V 电压模式控制同步降压控制器

主要特征 ◦ 5.5V-100V 宽输入范围 ◦ 0.8V-60V 可调输出电压 ◦ 0.8V1% 参考电压 ◦ 最低占空比下的40ns 最小 tON ◦ 最高占空比下的150ns 最小 tOFF • 100 KHz 到 1.2 MHz 开关频率 ◦ 时钟同步输入/输出功能 ◦ 可选择二极管仿真或 FPWM • 7.5V 门极驱动器 ◦ 2.3A …

Spring Cloud Gateway 详解:构建高效的API网关解决方案

Spring Cloud Gateway 详解&#xff1a;构建高效的API网关解决方案 Spring Cloud Gateway 是 Spring Cloud 生态系统中用于构建 API 网关的核心组件。它基于 Spring WebFlux 构建&#xff0c;旨在提供简单且有效的方式来路由和增强 API 请求。以下是 Spring Cloud Gateway 的详…

【iOS】YYModel源码阅读笔记

文章目录 前言一、JSON转换库对比二、YYModel性能优化三、YYModel的使用四、架构分析YYClassInfo 剖析 五、流程剖析转换前准备工作 – 将JSON统一成NSDictionary将NSDictionary 转换为Model对象提取Model信息使用NSDictionary的数据填充Model 总结 前言 先前写了JSONModel的源…

如何计算可截素数

什么是可截素数&#xff1f; 它本身是一个素数&#xff0c;如果从左往右逐一截去数字&#xff0c;剩下的仍然都是素数&#xff0c;如果从右往左逐一截去数字&#xff0c;剩下的也仍然都是素数。 例如&#xff1a;3797就是一个可截素数。 从左往右截去数字&#xff1a;797&a…