Coverage Report

Created: 2026-03-08 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/x265/source/encoder/analysis.h
Line
Count
Source
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
    /**
134
     * @brief Build CTU-level and area-level MVP seeds used by threaded ME.
135
     *
136
     * Performs an initial 2Nx2N search on the full CTU (and first split depth
137
     * when available), propagates temporal/colocated medians, and then drives
138
     * per-PU motion estimation.
139
     */
140
    void deriveMVsForCTU(CUData& ctu, const CUGeom& cuGeom, Frame& frame);
141
142
    /**
143
     * @brief Recursively walk CU partitions and run ME for each enabled PU shape.
144
     *
145
     * Computes the PU index mapping (`finalIdx`) used by CTU MV storage and
146
     * submits each PU to puMotionEstimation() with neighbor indices for MVP
147
     * derivation.
148
     */
149
    void computeMVForPUs(CUData& ctu, const CUGeom& cuGeom, int qp, Frame& frame);
150
151
protected:
152
    /* Analysis data for save/load mode, writes/reads data based on absPartIdx */
153
    x265_analysis_inter_data*  m_reuseInterDataCTU;
154
    int32_t*                   m_reuseRef;
155
    uint8_t*                   m_reuseDepth;
156
    uint8_t*                   m_reuseModes;
157
    uint8_t*                   m_reusePartSize;
158
    uint8_t*                   m_reuseMergeFlag;
159
    x265_analysis_MV*          m_reuseMv[2];
160
    uint8_t*             m_reuseMvpIdx[2];
161
162
    uint32_t             m_splitRefIdx[4];
163
    uint64_t*            cacheCost;
164
165
    uint8_t                 m_evaluateInter;
166
    int32_t                 m_refineLevel;
167
168
    uint8_t*                m_additionalCtuInfo;
169
    int*                    m_prevCtuInfoChange;
170
171
    struct TrainingData
172
    {
173
        uint32_t cuVariance;
174
        uint8_t predMode;
175
        uint8_t partSize;
176
        uint8_t mergeFlag;
177
        int split;
178
179
        void init(const CUData& parentCTU, const CUGeom& cuGeom)
180
0
        {
181
0
            cuVariance = 0;
182
0
            predMode = parentCTU.m_predMode[cuGeom.absPartIdx];
183
0
            partSize = parentCTU.m_partSize[cuGeom.absPartIdx];
184
0
            mergeFlag = parentCTU.m_mergeFlag[cuGeom.absPartIdx];
185
0
            split = 0;
186
0
        }
187
    };
188
189
    /* refine RD based on QP for rd-levels 5 and 6 */
190
    void qprdRefine(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp, int32_t lqp);
191
192
    /* full analysis for an I-slice CU */
193
#if ENABLE_SCC_EXT
194
    uint64_t compressIntraCU(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp, IBC* ibc = NULL);
195
#else
196
    uint64_t compressIntraCU(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp);
197
#endif
198
199
    /* full analysis for a P or B slice CU */
200
    uint32_t compressInterCU_dist(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp);
201
    SplitData compressInterCU_rd0_4(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp);
202
#if ENABLE_SCC_EXT
203
    SplitData compressInterCU_rd5_6(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp, IBC* ibc = NULL);
204
#else
205
    SplitData compressInterCU_rd5_6(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp);
206
#endif
207
208
    void recodeCU(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp, int32_t origqp = -1);
209
210
    /* measure merge and skip */
211
    void checkMerge2Nx2N_rd0_4(Mode& skip, Mode& merge, const CUGeom& cuGeom);
212
    void checkMerge2Nx2N_rd5_6(Mode& skip, Mode& merge, const CUGeom& cuGeom);
213
214
    /* measure inter options */
215
    void checkInter_rd0_4(Mode& interMode, const CUGeom& cuGeom, PartSize partSize, uint32_t refmask[2]);
216
#if !ENABLE_SCC_EXT
217
    void checkInter_rd5_6(Mode& interMode, const CUGeom& cuGeom, PartSize partSize, uint32_t refmask[2]);
218
#endif
219
    void checkBidir2Nx2N(Mode& inter2Nx2N, Mode& bidir2Nx2N, const CUGeom& cuGeom);
220
221
#if ENABLE_SCC_EXT
222
    void checkInter_rd5_6(Mode& interMode, const CUGeom& cuGeom, PartSize partSize, uint32_t refmask[2], MV* iMVCandList = NULL);
223
224
    void checkRDCostIntraBCMerge2Nx2N(Mode& merge, const CUGeom& cuGeom);
225
    void checkIntraBC_rd5_6(Mode& intraBCMode, const CUGeom& cuGeom, PartSize ePartSize, bool testOnlyPred, bool bUse1DSearchFor8x8, IBC& ibc, MV* iMVCandList = NULL);
226
#endif
227
228
    /* encode current bestMode losslessly, pick best RD cost */
229
    void tryLossless(const CUGeom& cuGeom);
230
231
    /* add the RD cost of coding a split flag (0 or 1) to the given mode */
232
    void addSplitFlagCost(Mode& mode, uint32_t depth);
233
234
    /* work-avoidance heuristics for RD levels < 5 */
235
    uint32_t topSkipMinDepth(const CUData& parentCTU, const CUGeom& cuGeom);
236
    bool recursionDepthCheck(const CUData& parentCTU, const CUGeom& cuGeom, const Mode& bestMode);
237
    bool complexityCheckCU(const Mode& bestMode);
238
239
    /* generate residual and recon pixels for an entire CTU recursively (RD0) */
240
    void encodeResidue(const CUData& parentCTU, const CUGeom& cuGeom);
241
242
    int calculateQpforCuSize(const CUData& ctu, const CUGeom& cuGeom, int32_t complexCheck = 0, double baseQP = -1);
243
    uint32_t calculateCUVariance(const CUData& ctu, const CUGeom& cuGeom);
244
245
    void classifyCU(const CUData& ctu, const CUGeom& cuGeom, const Mode& bestMode, TrainingData& trainData);
246
    void trainCU(const CUData& ctu, const CUGeom& cuGeom, const Mode& bestMode, TrainingData& trainData);
247
    double aqQPOffset(const CUData& ctu, const CUGeom& cuGeom);
248
    double cuTreeQPOffset(const CUData& ctu, const CUGeom& cuGeom);
249
    void calculateNormFactor(CUData& ctu, int qp);
250
    void normFactor(const pixel* src, uint32_t blockSize, CUData& ctu, int qp, TextType ttype);
251
252
    void collectPUStatistics(const CUData& ctu, const CUGeom& cuGeom);
253
254
    /* check whether current mode is the new best */
255
    inline void checkBestMode(Mode& mode, uint32_t depth)
256
785k
    {
257
785k
        ModeDepth& md = m_modeDepth[depth];
258
785k
        if (md.bestMode)
259
385k
        {
260
385k
            if (mode.rdCost < md.bestMode->rdCost)
261
549
                md.bestMode = &mode;
262
385k
        }
263
400k
        else
264
400k
            md.bestMode = &mode;
265
785k
    }
266
    int findSameContentRefCount(const CUData& parentCTU, const CUGeom& cuGeom);
267
};
268
269
struct ThreadLocalData
270
{
271
    Analysis analysis;
272
273
21.2k
    void destroy() { analysis.destroy(); }
274
};
275
276
}
277
278
#endif // ifndef X265_ANALYSIS_H