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