Coverage Report

Created: 2025-07-23 08:18

/src/x265/source/encoder/analysis.h
Line
Count
Source (jump to first uncovered line)
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
50
    void initSplitCUData()
51
0
    {
52
0
        splitRefs = 0;
53
0
        mvCost[0] = 0; // L0
54
0
        mvCost[1] = 0; // L1
55
0
        sa8dCost  = 0;
56
0
    }
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
#if ENABLE_SCC_EXT
79
        PRED_IBC_2Nx2N,
80
        PRED_IBC_Nx2N,
81
        PRED_IBC_2NxN,
82
        PRED_MIXED_IBC_NX2N,
83
        PRED_MIXED_IBC_2NXN,
84
        PRED_MERGE_IBC,
85
#endif
86
        MAX_PRED_TYPES
87
    };
88
89
    struct ModeDepth
90
    {
91
        Mode           pred[MAX_PRED_TYPES];
92
        Mode*          bestMode;
93
        Yuv            fencYuv;
94
        CUDataMemPool  cuMemPool;
95
    };
96
97
    class PMODE : public BondedTaskGroup
98
    {
99
    public:
100
101
        Analysis&     master;
102
        const CUGeom& cuGeom;
103
        int           modes[MAX_PRED_TYPES];
104
105
0
        PMODE(Analysis& m, const CUGeom& g) : master(m), cuGeom(g) {}
106
107
        void processTasks(int workerThreadId);
108
109
    protected:
110
111
        PMODE operator=(const PMODE&);
112
    };
113
114
    void processPmode(PMODE& pmode, Analysis& slave);
115
116
    ModeDepth m_modeDepth[NUM_CU_DEPTH];
117
    bool      m_bTryLossless;
118
    bool      m_bChromaSa8d;
119
    bool      m_bHD;
120
121
    bool      m_modeFlag[2];
122
    bool      m_checkMergeAndSkipOnly[2];
123
124
    IBC       m_ibc;
125
    Analysis();
126
127
    bool create(ThreadLocalData* tld);
128
    void destroy();
129
130
    Mode& compressCTU(CUData& ctu, Frame& frame, const CUGeom& cuGeom, const Entropy& initialContext);
131
    int32_t loadTUDepth(CUGeom cuGeom, CUData parentCTU);
132
133
protected:
134
    /* Analysis data for save/load mode, writes/reads data based on absPartIdx */
135
    x265_analysis_inter_data*  m_reuseInterDataCTU;
136
    int32_t*                   m_reuseRef;
137
    uint8_t*                   m_reuseDepth;
138
    uint8_t*                   m_reuseModes;
139
    uint8_t*                   m_reusePartSize;
140
    uint8_t*                   m_reuseMergeFlag;
141
    x265_analysis_MV*          m_reuseMv[2];
142
    uint8_t*             m_reuseMvpIdx[2];
143
144
    uint32_t             m_splitRefIdx[4];
145
    uint64_t*            cacheCost;
146
147
    uint8_t                 m_evaluateInter;
148
    int32_t                 m_refineLevel;
149
150
    uint8_t*                m_additionalCtuInfo;
151
    int*                    m_prevCtuInfoChange;
152
153
    struct TrainingData
154
    {
155
        uint32_t cuVariance;
156
        uint8_t predMode;
157
        uint8_t partSize;
158
        uint8_t mergeFlag;
159
        int split;
160
161
        void init(const CUData& parentCTU, const CUGeom& cuGeom)
162
0
        {
163
0
            cuVariance = 0;
164
0
            predMode = parentCTU.m_predMode[cuGeom.absPartIdx];
165
0
            partSize = parentCTU.m_partSize[cuGeom.absPartIdx];
166
0
            mergeFlag = parentCTU.m_mergeFlag[cuGeom.absPartIdx];
167
0
            split = 0;
168
0
        }
169
    };
170
171
    /* refine RD based on QP for rd-levels 5 and 6 */
172
    void qprdRefine(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp, int32_t lqp);
173
174
    /* full analysis for an I-slice CU */
175
#if ENABLE_SCC_EXT
176
    uint64_t compressIntraCU(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp, IBC* ibc = NULL);
177
#else
178
    uint64_t compressIntraCU(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp);
179
#endif
180
181
    /* full analysis for a P or B slice CU */
182
    uint32_t compressInterCU_dist(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp);
183
    SplitData compressInterCU_rd0_4(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp);
184
#if ENABLE_SCC_EXT
185
    SplitData compressInterCU_rd5_6(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp, IBC* ibc = NULL);
186
#else
187
    SplitData compressInterCU_rd5_6(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp);
188
#endif
189
190
    void recodeCU(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp, int32_t origqp = -1);
191
192
    /* measure merge and skip */
193
    void checkMerge2Nx2N_rd0_4(Mode& skip, Mode& merge, const CUGeom& cuGeom);
194
    void checkMerge2Nx2N_rd5_6(Mode& skip, Mode& merge, const CUGeom& cuGeom);
195
196
    /* measure inter options */
197
    void checkInter_rd0_4(Mode& interMode, const CUGeom& cuGeom, PartSize partSize, uint32_t refmask[2]);
198
#if !ENABLE_SCC_EXT
199
    void checkInter_rd5_6(Mode& interMode, const CUGeom& cuGeom, PartSize partSize, uint32_t refmask[2]);
200
#endif
201
    void checkBidir2Nx2N(Mode& inter2Nx2N, Mode& bidir2Nx2N, const CUGeom& cuGeom);
202
203
#if ENABLE_SCC_EXT
204
    void checkInter_rd5_6(Mode& interMode, const CUGeom& cuGeom, PartSize partSize, uint32_t refmask[2], MV* iMVCandList = NULL);
205
206
    void checkRDCostIntraBCMerge2Nx2N(Mode& merge, const CUGeom& cuGeom);
207
    void checkIntraBC_rd5_6(Mode& intraBCMode, const CUGeom& cuGeom, PartSize ePartSize, bool testOnlyPred, bool bUse1DSearchFor8x8, IBC& ibc, MV* iMVCandList = NULL);
208
#endif
209
210
    /* encode current bestMode losslessly, pick best RD cost */
211
    void tryLossless(const CUGeom& cuGeom);
212
213
    /* add the RD cost of coding a split flag (0 or 1) to the given mode */
214
    void addSplitFlagCost(Mode& mode, uint32_t depth);
215
216
    /* work-avoidance heuristics for RD levels < 5 */
217
    uint32_t topSkipMinDepth(const CUData& parentCTU, const CUGeom& cuGeom);
218
    bool recursionDepthCheck(const CUData& parentCTU, const CUGeom& cuGeom, const Mode& bestMode);
219
    bool complexityCheckCU(const Mode& bestMode);
220
221
    /* generate residual and recon pixels for an entire CTU recursively (RD0) */
222
    void encodeResidue(const CUData& parentCTU, const CUGeom& cuGeom);
223
224
    int calculateQpforCuSize(const CUData& ctu, const CUGeom& cuGeom, int32_t complexCheck = 0, double baseQP = -1);
225
    uint32_t calculateCUVariance(const CUData& ctu, const CUGeom& cuGeom);
226
227
    void classifyCU(const CUData& ctu, const CUGeom& cuGeom, const Mode& bestMode, TrainingData& trainData);
228
    void trainCU(const CUData& ctu, const CUGeom& cuGeom, const Mode& bestMode, TrainingData& trainData);
229
    double aqQPOffset(const CUData& ctu, const CUGeom& cuGeom);
230
    double cuTreeQPOffset(const CUData& ctu, const CUGeom& cuGeom);
231
    void calculateNormFactor(CUData& ctu, int qp);
232
    void normFactor(const pixel* src, uint32_t blockSize, CUData& ctu, int qp, TextType ttype);
233
234
    void collectPUStatistics(const CUData& ctu, const CUGeom& cuGeom);
235
236
    /* check whether current mode is the new best */
237
    inline void checkBestMode(Mode& mode, uint32_t depth)
238
0
    {
239
0
        ModeDepth& md = m_modeDepth[depth];
240
0
        if (md.bestMode)
241
0
        {
242
0
            if (mode.rdCost < md.bestMode->rdCost)
243
0
                md.bestMode = &mode;
244
0
        }
245
0
        else
246
0
            md.bestMode = &mode;
247
0
    }
248
    int findSameContentRefCount(const CUData& parentCTU, const CUGeom& cuGeom);
249
};
250
251
struct ThreadLocalData
252
{
253
    Analysis analysis;
254
255
0
    void destroy() { analysis.destroy(); }
256
};
257
258
}
259
260
#endif // ifndef X265_ANALYSIS_H