1 /***************************************************************************** 2 * Copyright (C) 2013-2020 MulticoreWare, Inc 3 * 4 * Authors: Deepthi Nandakumar <deepthi@multicorewareinc.com> 5 * Steve Borho <steve@borho.org> 6 * Min Chen <chenm003@163.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. 21 * 22 * This program is also available under a commercial proprietary license. 23 * For more information, contact us at license @ x265.com. 24 *****************************************************************************/ 25 26 #ifndef X265_ANALYSIS_H 27 #define X265_ANALYSIS_H 28 29 #include "common.h" 30 #include "predict.h" 31 #include "quant.h" 32 #include "yuv.h" 33 #include "shortyuv.h" 34 #include "cudata.h" 35 36 #include "entropy.h" 37 #include "search.h" 38 39 namespace X265_NS { 40 // private namespace 41 42 class Entropy; 43 44 struct SplitData 45 { 46 uint32_t splitRefs; 47 uint32_t mvCost[2]; 48 uint64_t sa8dCost; 49 initSplitCUDataSplitData50 void initSplitCUData() 51 { 52 splitRefs = 0; 53 mvCost[0] = 0; // L0 54 mvCost[1] = 0; // L1 55 sa8dCost = 0; 56 } 57 }; 58 59 class Analysis : public Search 60 { 61 public: 62 63 enum { 64 PRED_MERGE, 65 PRED_SKIP, 66 PRED_INTRA, 67 PRED_2Nx2N, 68 PRED_BIDIR, 69 PRED_Nx2N, 70 PRED_2NxN, 71 PRED_SPLIT, 72 PRED_2NxnU, 73 PRED_2NxnD, 74 PRED_nLx2N, 75 PRED_nRx2N, 76 PRED_INTRA_NxN, /* 4x4 intra PU blocks for 8x8 CU */ 77 PRED_LOSSLESS, /* lossless encode of best mode */ 78 MAX_PRED_TYPES 79 }; 80 81 struct ModeDepth 82 { 83 Mode pred[MAX_PRED_TYPES]; 84 Mode* bestMode; 85 Yuv fencYuv; 86 CUDataMemPool cuMemPool; 87 }; 88 89 class PMODE : public BondedTaskGroup 90 { 91 public: 92 93 Analysis& master; 94 const CUGeom& cuGeom; 95 int modes[MAX_PRED_TYPES]; 96 PMODE(Analysis & m,const CUGeom & g)97 PMODE(Analysis& m, const CUGeom& g) : master(m), cuGeom(g) {} 98 99 void processTasks(int workerThreadId); 100 101 protected: 102 103 PMODE operator=(const PMODE&); 104 }; 105 106 void processPmode(PMODE& pmode, Analysis& slave); 107 108 ModeDepth m_modeDepth[NUM_CU_DEPTH]; 109 bool m_bTryLossless; 110 bool m_bChromaSa8d; 111 bool m_bHD; 112 113 bool m_modeFlag[2]; 114 bool m_checkMergeAndSkipOnly[2]; 115 116 Analysis(); 117 118 bool create(ThreadLocalData* tld); 119 void destroy(); 120 121 Mode& compressCTU(CUData& ctu, Frame& frame, const CUGeom& cuGeom, const Entropy& initialContext); 122 int32_t loadTUDepth(CUGeom cuGeom, CUData parentCTU); 123 protected: 124 /* Analysis data for save/load mode, writes/reads data based on absPartIdx */ 125 x265_analysis_inter_data* m_reuseInterDataCTU; 126 int32_t* m_reuseRef; 127 uint8_t* m_reuseDepth; 128 uint8_t* m_reuseModes; 129 uint8_t* m_reusePartSize; 130 uint8_t* m_reuseMergeFlag; 131 x265_analysis_MV* m_reuseMv[2]; 132 uint8_t* m_reuseMvpIdx[2]; 133 134 uint32_t m_splitRefIdx[4]; 135 uint64_t* cacheCost; 136 137 uint8_t m_evaluateInter; 138 int32_t m_refineLevel; 139 140 uint8_t* m_additionalCtuInfo; 141 int* m_prevCtuInfoChange; 142 143 struct TrainingData 144 { 145 uint32_t cuVariance; 146 uint8_t predMode; 147 uint8_t partSize; 148 uint8_t mergeFlag; 149 int split; 150 initTrainingData151 void init(const CUData& parentCTU, const CUGeom& cuGeom) 152 { 153 cuVariance = 0; 154 predMode = parentCTU.m_predMode[cuGeom.absPartIdx]; 155 partSize = parentCTU.m_partSize[cuGeom.absPartIdx]; 156 mergeFlag = parentCTU.m_mergeFlag[cuGeom.absPartIdx]; 157 split = 0; 158 } 159 }; 160 161 /* refine RD based on QP for rd-levels 5 and 6 */ 162 void qprdRefine(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp, int32_t lqp); 163 164 /* full analysis for an I-slice CU */ 165 uint64_t compressIntraCU(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp); 166 167 /* full analysis for a P or B slice CU */ 168 uint32_t compressInterCU_dist(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp); 169 SplitData compressInterCU_rd0_4(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp); 170 SplitData compressInterCU_rd5_6(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp); 171 172 void recodeCU(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp, int32_t origqp = -1); 173 174 /* measure merge and skip */ 175 void checkMerge2Nx2N_rd0_4(Mode& skip, Mode& merge, const CUGeom& cuGeom); 176 void checkMerge2Nx2N_rd5_6(Mode& skip, Mode& merge, const CUGeom& cuGeom); 177 178 /* measure inter options */ 179 void checkInter_rd0_4(Mode& interMode, const CUGeom& cuGeom, PartSize partSize, uint32_t refmask[2]); 180 void checkInter_rd5_6(Mode& interMode, const CUGeom& cuGeom, PartSize partSize, uint32_t refmask[2]); 181 182 void checkBidir2Nx2N(Mode& inter2Nx2N, Mode& bidir2Nx2N, const CUGeom& cuGeom); 183 184 /* encode current bestMode losslessly, pick best RD cost */ 185 void tryLossless(const CUGeom& cuGeom); 186 187 /* add the RD cost of coding a split flag (0 or 1) to the given mode */ 188 void addSplitFlagCost(Mode& mode, uint32_t depth); 189 190 /* work-avoidance heuristics for RD levels < 5 */ 191 uint32_t topSkipMinDepth(const CUData& parentCTU, const CUGeom& cuGeom); 192 bool recursionDepthCheck(const CUData& parentCTU, const CUGeom& cuGeom, const Mode& bestMode); 193 bool complexityCheckCU(const Mode& bestMode); 194 195 /* generate residual and recon pixels for an entire CTU recursively (RD0) */ 196 void encodeResidue(const CUData& parentCTU, const CUGeom& cuGeom); 197 198 int calculateQpforCuSize(const CUData& ctu, const CUGeom& cuGeom, int32_t complexCheck = 0, double baseQP = -1); 199 uint32_t calculateCUVariance(const CUData& ctu, const CUGeom& cuGeom); 200 201 void classifyCU(const CUData& ctu, const CUGeom& cuGeom, const Mode& bestMode, TrainingData& trainData); 202 void trainCU(const CUData& ctu, const CUGeom& cuGeom, const Mode& bestMode, TrainingData& trainData); 203 double aqQPOffset(const CUData& ctu, const CUGeom& cuGeom); 204 double cuTreeQPOffset(const CUData& ctu, const CUGeom& cuGeom); 205 void calculateNormFactor(CUData& ctu, int qp); 206 void normFactor(const pixel* src, uint32_t blockSize, CUData& ctu, int qp, TextType ttype); 207 208 void collectPUStatistics(const CUData& ctu, const CUGeom& cuGeom); 209 210 /* check whether current mode is the new best */ checkBestMode(Mode & mode,uint32_t depth)211 inline void checkBestMode(Mode& mode, uint32_t depth) 212 { 213 ModeDepth& md = m_modeDepth[depth]; 214 if (md.bestMode) 215 { 216 if (mode.rdCost < md.bestMode->rdCost) 217 md.bestMode = &mode; 218 } 219 else 220 md.bestMode = &mode; 221 } 222 int findSameContentRefCount(const CUData& parentCTU, const CUGeom& cuGeom); 223 }; 224 225 struct ThreadLocalData 226 { 227 Analysis analysis; 228 destroyThreadLocalData229 void destroy() { analysis.destroy(); } 230 }; 231 232 } 233 234 #endif // ifndef X265_ANALYSIS_H 235