Coverage Report

Created: 2025-07-23 08:18

/src/x265/source/encoder/frameencoder.h
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************
2
 * Copyright (C) 2013-2020 MulticoreWare, Inc
3
 *
4
 * Authors: Shin Yee <shinyee@multicorewareinc.com>
5
 *          Min Chen <chenm003@163.com>
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
20
 *
21
 * This program is also available under a commercial proprietary license.
22
 * For more information, contact us at license @ x265.com.
23
 *****************************************************************************/
24
25
#ifndef X265_FRAMEENCODER_H
26
#define X265_FRAMEENCODER_H
27
28
#include "common.h"
29
#include "wavefront.h"
30
#include "bitstream.h"
31
#include "frame.h"
32
#include "picyuv.h"
33
#include "md5.h"
34
35
#include "analysis.h"
36
#include "sao.h"
37
38
#include "entropy.h"
39
#include "framefilter.h"
40
#include "ratecontrol.h"
41
#include "reference.h"
42
#include "nal.h"
43
#include "temporalfilter.h"
44
45
namespace X265_NS {
46
// private x265 namespace
47
48
class ThreadPool;
49
class Encoder;
50
51
0
#define ANGULAR_MODE_ID 2
52
0
#define AMP_ID 3
53
54
struct StatisticLog
55
{
56
    uint64_t cntInter[4];
57
    uint64_t cntIntra[4];
58
    uint64_t cuInterDistribution[4][INTER_MODES];
59
    uint64_t cuIntraDistribution[4][INTRA_MODES];
60
    uint64_t cntIntraNxN;
61
    uint64_t cntSkipCu[4];
62
    uint64_t cntTotalCu[4];
63
    uint64_t totalCu;
64
65
    StatisticLog()
66
0
    {
67
0
        memset(this, 0, sizeof(StatisticLog));
68
0
    }
69
};
70
71
/* manages the state of encoding one row of CTU blocks.  When
72
 * WPP is active, several rows will be simultaneously encoded. */
73
struct CTURow
74
{
75
    Entropy           bufferedEntropy;  /* store CTU2 context for next row CTU0 */
76
    Entropy           rowGoOnCoder;     /* store context between CTUs, code bitstream if !SAO */
77
    unsigned int      sliceId;          /* store current row slice id */
78
79
    FrameStats        rowStats;
80
81
    /* Threading variables */
82
83
    /* This lock must be acquired when reading or writing m_active or m_busy */
84
    Lock              lock;
85
86
    /* row is ready to run, has no neighbor dependencies. The row may have
87
     * external dependencies (reference frame pixels) that prevent it from being
88
     * processed, so it may stay with m_active=true for some time before it is
89
     * encoded by a worker thread. */
90
    volatile bool     active;
91
92
    /* row is being processed by a worker thread.  This flag is only true when a
93
     * worker thread is within the context of FrameEncoder::processRow(). This
94
     * flag is used to detect multiple possible wavefront problems. */
95
    volatile bool     busy;
96
97
    /* count of completed CUs in this row */
98
    volatile uint32_t completed;
99
    volatile uint32_t avgQPComputed;
100
101
    volatile int      reEncode;
102
103
    /* called at the start of each frame to initialize state */
104
    void init(Entropy& initContext, unsigned int sid)
105
0
    {
106
0
        active = false;
107
0
        busy = false;
108
0
        completed = 0;
109
0
        avgQPComputed = 0;
110
0
        sliceId = sid;
111
0
        reEncode = 0;
112
0
        memset(&rowStats, 0, sizeof(rowStats));
113
0
        rowGoOnCoder.load(initContext);
114
0
    }
115
};
116
117
/*Film grain characteristics*/
118
struct FilmGrain
119
{
120
    bool    m_filmGrainCharacteristicsCancelFlag;
121
    bool    m_filmGrainCharacteristicsPersistenceFlag;
122
    bool    m_separateColourDescriptionPresentFlag;
123
    uint8_t m_filmGrainModelId;
124
    uint8_t m_blendingModeId;
125
    uint8_t m_log2ScaleFactor;
126
};
127
128
struct ColourDescription
129
{
130
    bool        m_filmGrainFullRangeFlag;
131
    uint8_t     m_filmGrainBitDepthLumaMinus8;
132
    uint8_t     m_filmGrainBitDepthChromaMinus8;
133
    uint8_t     m_filmGrainColourPrimaries;
134
    uint8_t     m_filmGrainTransferCharacteristics;
135
    uint8_t     m_filmGrainMatrixCoeffs;
136
};
137
138
struct FGPresent
139
{
140
    uint8_t     m_blendingModeId;
141
    uint8_t     m_log2ScaleFactor;
142
    bool        m_presentFlag[3];
143
};
144
145
struct AomFilmGrain
146
{
147
    int32_t     m_apply_grain;
148
    int32_t     m_update_grain;
149
    int32_t     m_scaling_points_y[14][2];
150
    int32_t     m_num_y_points;
151
    int32_t     m_scaling_points_cb[10][2];
152
    int32_t     m_num_cb_points;
153
    int32_t     m_scaling_points_cr[10][2];
154
    int32_t     m_num_cr_points;
155
    int32_t     m_scaling_shift;
156
    int32_t     m_ar_coeff_lag;
157
    int32_t     m_ar_coeffs_y[24];
158
    int32_t     m_ar_coeffs_cb[25];
159
    int32_t     m_ar_coeffs_cr[25];
160
    int32_t     m_ar_coeff_shift;
161
    int32_t     m_cb_mult;
162
    int32_t     m_cb_luma_mult;
163
    int32_t     m_cb_offset;
164
    int32_t     m_cr_mult;
165
    int32_t     m_cr_luma_mult;
166
    int32_t     m_cr_offset;
167
    int32_t     m_overlap_flag;
168
    int32_t     m_clip_to_restricted_range;
169
    int32_t     m_bitDepth;
170
    int32_t     m_chroma_scaling_from_luma;
171
    int32_t     m_grain_scale_shift;
172
    uint16_t    m_grain_seed;
173
};
174
175
// Manages the wave-front processing of a single encoding frame
176
class FrameEncoder : public WaveFront, public Thread
177
{
178
public:
179
180
    FrameEncoder();
181
182
0
    virtual ~FrameEncoder() {}
183
184
    virtual bool init(Encoder *top, int numRows, int numCols);
185
186
    void destroy();
187
188
    /* triggers encode of a new frame by the worker thread */
189
    bool startCompressFrame(Frame* curFrame[MAX_LAYERS]);
190
191
    /* blocks until worker thread is done, returns access unit */
192
    Frame **getEncodedPicture(NALList& list);
193
194
    void initDecodedPictureHashSEI(int row, int cuAddr, int height, int layer);
195
196
    Event                    m_enable;
197
    Event                    m_done;
198
    Event                    m_completionEvent;
199
    int                      m_localTldIdx;
200
    bool                     m_reconfigure; /* reconfigure in progress */
201
    volatile bool            m_threadActive;
202
    volatile bool            *m_bAllRowsStop;
203
    volatile int             m_completionCount;
204
    volatile int             *m_vbvResetTriggerRow;
205
    volatile int             m_sliceCnt;
206
207
    uint32_t                 m_numRows;
208
    uint32_t                 m_numCols;
209
    uint32_t                 m_filterRowDelay;
210
    uint32_t                 m_filterRowDelayCus;
211
    uint32_t                 m_refLagRows;
212
    bool                     m_bUseSao;
213
214
    CTURow*                  m_rows;
215
    uint16_t                 m_sliceAddrBits;
216
    uint32_t                 m_sliceGroupSize;
217
    uint32_t*                m_sliceBaseRow;    
218
    uint32_t*                m_sliceMaxBlockRow;
219
    int64_t                  m_rowSliceTotalBits[2];
220
    RateControlEntry         m_rce;
221
    SEIDecodedPictureHash    m_seiReconPictureDigest;
222
223
    uint64_t                 m_SSDY[MAX_LAYERS];
224
    uint64_t                 m_SSDU[MAX_LAYERS];
225
    uint64_t                 m_SSDV[MAX_LAYERS];
226
    double                   m_ssim[MAX_LAYERS];
227
    uint64_t                 m_accessUnitBits[MAX_LAYERS];
228
    uint32_t                 m_ssimCnt[MAX_LAYERS];
229
230
    volatile int             m_activeWorkerCount;        // count of workers currently encoding or filtering CTUs
231
    volatile int             m_totalActiveWorkerCount;   // sum of m_activeWorkerCount sampled at end of each CTU
232
    volatile int             m_activeWorkerCountSamples; // count of times m_activeWorkerCount was sampled (think vbv restarts)
233
    volatile int             m_countRowBlocks;           // count of workers forced to abandon a row because of top dependency
234
    int64_t                  m_startCompressTime[MAX_LAYERS];        // timestamp when frame encoder is given a frame
235
    int64_t                  m_row0WaitTime[MAX_LAYERS];             // timestamp when row 0 is allowed to start
236
    int64_t                  m_allRowsAvailableTime[MAX_LAYERS];     // timestamp when all reference dependencies are resolved
237
    int64_t                  m_endCompressTime[MAX_LAYERS];          // timestamp after all CTUs are compressed
238
    int64_t                  m_endFrameTime[MAX_LAYERS];             // timestamp after RCEnd, NR updates, etc
239
    int64_t                  m_stallStartTime[MAX_LAYERS];           // timestamp when worker count becomes 0
240
    int64_t                  m_prevOutputTime[MAX_LAYERS];           // timestamp when prev frame was retrieved by API thread
241
    int64_t                  m_slicetypeWaitTime[MAX_LAYERS];        // total elapsed time waiting for decided frame
242
    int64_t                  m_totalWorkerElapsedTime[MAX_LAYERS];   // total elapsed time spent by worker threads processing CTUs
243
    int64_t                  m_totalNoWorkerTime[MAX_LAYERS];        // total elapsed time without any active worker threads
244
#if DETAILED_CU_STATS
245
    CUStats                  m_cuStats;
246
#endif
247
248
    Encoder*                 m_top;
249
    x265_param*              m_param;
250
    Frame*                   m_frame[MAX_LAYERS];
251
    Frame**                  m_retFrameBuffer;
252
    NoiseReduction*          m_nr;
253
    ThreadLocalData*         m_tld; /* for --no-wpp */
254
    Bitstream*               m_outStreams;
255
    Bitstream*               m_backupStreams;
256
    uint32_t*                m_substreamSizes;
257
258
    CUGeom*                  m_cuGeoms;
259
    uint32_t*                m_ctuGeomMap;
260
261
    Bitstream                m_bs;
262
    MotionReference          m_mref[2][MAX_NUM_REF + 1];
263
    Entropy                  m_entropyCoder;
264
    Entropy                  m_initSliceContext;
265
    FrameFilter              m_frameFilter;
266
    NALList                  m_nalList;
267
268
    int                      m_sLayerId;
269
270
    class WeightAnalysis : public BondedTaskGroup
271
    {
272
    public:
273
274
        FrameEncoder& master;
275
276
0
        WeightAnalysis(FrameEncoder& fe) : master(fe) {}
277
278
        void processTasks(int workerThreadId);
279
280
    protected:
281
282
        WeightAnalysis operator=(const WeightAnalysis&);
283
    };
284
285
protected:
286
287
    bool initializeGeoms();
288
289
    /* analyze / compress frame, can be run in parallel within reference constraints */
290
    void compressFrame(int layer);
291
292
    /* called by compressFrame to generate final per-row bitstreams */
293
    void encodeSlice(uint32_t sliceAddr, int layer);
294
295
    void threadMain();
296
    int  collectCTUStatistics(const CUData& ctu, FrameStats* frameLog);
297
    void noiseReductionUpdate();
298
    void writeTrailingSEIMessages(int layer);
299
    bool writeToneMapInfo(x265_sei_payload *payload);
300
301
    /* Called by WaveFront::findJob() */
302
    virtual void processRow(int row, int threadId, int layer);
303
    virtual void processRowEncoder(int row, ThreadLocalData& tld, int layer);
304
305
0
    void enqueueRowEncoder(int row) { WaveFront::enqueueRow(row * 2 + 0); }
306
0
    void enqueueRowFilter(int row)  { WaveFront::enqueueRow(row * 2 + 1); }
307
0
    void enableRowEncoder(int row)  { WaveFront::enableRow(row * 2 + 0); }
308
0
    void enableRowFilter(int row)   { WaveFront::enableRow(row * 2 + 1); }
309
#if ENABLE_LIBVMAF
310
    void vmafFrameLevelScore();
311
#endif
312
    void collectDynDataFrame(int layer);
313
    void computeAvgTrainingData(int layer);
314
    void collectDynDataRow(CUData& ctu, FrameStats* rowStats);    
315
    void readModel(FilmGrainCharacteristics* m_filmGrain, FILE* filmgrain);
316
    void readAomModel(AomFilmGrainCharacteristics* m_aomFilmGrain, FILE* Aomfilmgrain);
317
};
318
}
319
320
#endif // ifndef X265_FRAMEENCODER_H