File: frameencoder.h

package info (click to toggle)
x265 4.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 15,408 kB
  • sloc: asm: 187,063; cpp: 118,996; ansic: 741; makefile: 146; sh: 91; python: 11
file content (320 lines) | stat: -rw-r--r-- 11,540 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
/*****************************************************************************
 * Copyright (C) 2013-2020 MulticoreWare, Inc
 *
 * Authors: Shin Yee <shinyee@multicorewareinc.com>
 *          Min Chen <chenm003@163.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
 *
 * This program is also available under a commercial proprietary license.
 * For more information, contact us at license @ x265.com.
 *****************************************************************************/

#ifndef X265_FRAMEENCODER_H
#define X265_FRAMEENCODER_H

#include "common.h"
#include "wavefront.h"
#include "bitstream.h"
#include "frame.h"
#include "picyuv.h"
#include "md5.h"

#include "analysis.h"
#include "sao.h"

#include "entropy.h"
#include "framefilter.h"
#include "ratecontrol.h"
#include "reference.h"
#include "nal.h"
#include "temporalfilter.h"

namespace X265_NS {
// private x265 namespace

class ThreadPool;
class Encoder;

#define ANGULAR_MODE_ID 2
#define AMP_ID 3

struct StatisticLog
{
    uint64_t cntInter[4];
    uint64_t cntIntra[4];
    uint64_t cuInterDistribution[4][INTER_MODES];
    uint64_t cuIntraDistribution[4][INTRA_MODES];
    uint64_t cntIntraNxN;
    uint64_t cntSkipCu[4];
    uint64_t cntTotalCu[4];
    uint64_t totalCu;

    StatisticLog()
    {
        memset(this, 0, sizeof(StatisticLog));
    }
};

/* manages the state of encoding one row of CTU blocks.  When
 * WPP is active, several rows will be simultaneously encoded. */
struct CTURow
{
    Entropy           bufferedEntropy;  /* store CTU2 context for next row CTU0 */
    Entropy           rowGoOnCoder;     /* store context between CTUs, code bitstream if !SAO */
    unsigned int      sliceId;          /* store current row slice id */

    FrameStats        rowStats;

    /* Threading variables */

    /* This lock must be acquired when reading or writing m_active or m_busy */
    Lock              lock;

    /* row is ready to run, has no neighbor dependencies. The row may have
     * external dependencies (reference frame pixels) that prevent it from being
     * processed, so it may stay with m_active=true for some time before it is
     * encoded by a worker thread. */
    volatile bool     active;

    /* row is being processed by a worker thread.  This flag is only true when a
     * worker thread is within the context of FrameEncoder::processRow(). This
     * flag is used to detect multiple possible wavefront problems. */
    volatile bool     busy;

    /* count of completed CUs in this row */
    volatile uint32_t completed;
    volatile uint32_t avgQPComputed;

    volatile int      reEncode;

    /* called at the start of each frame to initialize state */
    void init(Entropy& initContext, unsigned int sid)
    {
        active = false;
        busy = false;
        completed = 0;
        avgQPComputed = 0;
        sliceId = sid;
        reEncode = 0;
        memset(&rowStats, 0, sizeof(rowStats));
        rowGoOnCoder.load(initContext);
    }
};

/*Film grain characteristics*/
struct FilmGrain
{
    bool    m_filmGrainCharacteristicsCancelFlag;
    bool    m_filmGrainCharacteristicsPersistenceFlag;
    bool    m_separateColourDescriptionPresentFlag;
    uint8_t m_filmGrainModelId;
    uint8_t m_blendingModeId;
    uint8_t m_log2ScaleFactor;
};

struct ColourDescription
{
    bool        m_filmGrainFullRangeFlag;
    uint8_t     m_filmGrainBitDepthLumaMinus8;
    uint8_t     m_filmGrainBitDepthChromaMinus8;
    uint8_t     m_filmGrainColourPrimaries;
    uint8_t     m_filmGrainTransferCharacteristics;
    uint8_t     m_filmGrainMatrixCoeffs;
};

struct FGPresent
{
    uint8_t     m_blendingModeId;
    uint8_t     m_log2ScaleFactor;
    bool        m_presentFlag[3];
};

struct AomFilmGrain
{
    int32_t     m_apply_grain;
    int32_t     m_update_grain;
    int32_t     m_scaling_points_y[14][2];
    int32_t     m_num_y_points;
    int32_t     m_scaling_points_cb[10][2];
    int32_t     m_num_cb_points;
    int32_t     m_scaling_points_cr[10][2];
    int32_t     m_num_cr_points;
    int32_t     m_scaling_shift;
    int32_t     m_ar_coeff_lag;
    int32_t     m_ar_coeffs_y[24];
    int32_t     m_ar_coeffs_cb[25];
    int32_t     m_ar_coeffs_cr[25];
    int32_t     m_ar_coeff_shift;
    int32_t     m_cb_mult;
    int32_t     m_cb_luma_mult;
    int32_t     m_cb_offset;
    int32_t     m_cr_mult;
    int32_t     m_cr_luma_mult;
    int32_t     m_cr_offset;
    int32_t     m_overlap_flag;
    int32_t     m_clip_to_restricted_range;
    int32_t     m_bitDepth;
    int32_t     m_chroma_scaling_from_luma;
    int32_t     m_grain_scale_shift;
    uint16_t    m_grain_seed;
};

// Manages the wave-front processing of a single encoding frame
class FrameEncoder : public WaveFront, public Thread
{
public:

    FrameEncoder();

    virtual ~FrameEncoder() {}

    virtual bool init(Encoder *top, int numRows, int numCols);

    void destroy();

    /* triggers encode of a new frame by the worker thread */
    bool startCompressFrame(Frame* curFrame[MAX_LAYERS]);

    /* blocks until worker thread is done, returns access unit */
    Frame **getEncodedPicture(NALList& list);

    void initDecodedPictureHashSEI(int row, int cuAddr, int height, int layer);

    Event                    m_enable;
    Event                    m_done;
    Event                    m_completionEvent;
    int                      m_localTldIdx;
    bool                     m_reconfigure; /* reconfigure in progress */
    volatile bool            m_threadActive;
    volatile bool            *m_bAllRowsStop;
    volatile int             m_completionCount;
    volatile int             *m_vbvResetTriggerRow;
    volatile int             m_sliceCnt;

    uint32_t                 m_numRows;
    uint32_t                 m_numCols;
    uint32_t                 m_filterRowDelay;
    uint32_t                 m_filterRowDelayCus;
    uint32_t                 m_refLagRows;
    bool                     m_bUseSao;

    CTURow*                  m_rows;
    uint16_t                 m_sliceAddrBits;
    uint32_t                 m_sliceGroupSize;
    uint32_t*                m_sliceBaseRow;    
    uint32_t*                m_sliceMaxBlockRow;
    int64_t                  m_rowSliceTotalBits[2];
    RateControlEntry         m_rce;
    SEIDecodedPictureHash    m_seiReconPictureDigest;

    uint64_t                 m_SSDY[MAX_LAYERS];
    uint64_t                 m_SSDU[MAX_LAYERS];
    uint64_t                 m_SSDV[MAX_LAYERS];
    double                   m_ssim[MAX_LAYERS];
    uint64_t                 m_accessUnitBits[MAX_LAYERS];
    uint32_t                 m_ssimCnt[MAX_LAYERS];

    volatile int             m_activeWorkerCount;        // count of workers currently encoding or filtering CTUs
    volatile int             m_totalActiveWorkerCount;   // sum of m_activeWorkerCount sampled at end of each CTU
    volatile int             m_activeWorkerCountSamples; // count of times m_activeWorkerCount was sampled (think vbv restarts)
    volatile int             m_countRowBlocks;           // count of workers forced to abandon a row because of top dependency
    int64_t                  m_startCompressTime[MAX_LAYERS];        // timestamp when frame encoder is given a frame
    int64_t                  m_row0WaitTime[MAX_LAYERS];             // timestamp when row 0 is allowed to start
    int64_t                  m_allRowsAvailableTime[MAX_LAYERS];     // timestamp when all reference dependencies are resolved
    int64_t                  m_endCompressTime[MAX_LAYERS];          // timestamp after all CTUs are compressed
    int64_t                  m_endFrameTime[MAX_LAYERS];             // timestamp after RCEnd, NR updates, etc
    int64_t                  m_stallStartTime[MAX_LAYERS];           // timestamp when worker count becomes 0
    int64_t                  m_prevOutputTime[MAX_LAYERS];           // timestamp when prev frame was retrieved by API thread
    int64_t                  m_slicetypeWaitTime[MAX_LAYERS];        // total elapsed time waiting for decided frame
    int64_t                  m_totalWorkerElapsedTime[MAX_LAYERS];   // total elapsed time spent by worker threads processing CTUs
    int64_t                  m_totalNoWorkerTime[MAX_LAYERS];        // total elapsed time without any active worker threads
#if DETAILED_CU_STATS
    CUStats                  m_cuStats;
#endif

    Encoder*                 m_top;
    x265_param*              m_param;
    Frame*                   m_frame[MAX_LAYERS];
    Frame**                  m_retFrameBuffer;
    NoiseReduction*          m_nr;
    ThreadLocalData*         m_tld; /* for --no-wpp */
    Bitstream*               m_outStreams;
    Bitstream*               m_backupStreams;
    uint32_t*                m_substreamSizes;

    CUGeom*                  m_cuGeoms;
    uint32_t*                m_ctuGeomMap;

    Bitstream                m_bs;
    MotionReference          m_mref[2][MAX_NUM_REF + 1];
    Entropy                  m_entropyCoder;
    Entropy                  m_initSliceContext;
    FrameFilter              m_frameFilter;
    NALList                  m_nalList;

    int                      m_sLayerId;

    class WeightAnalysis : public BondedTaskGroup
    {
    public:

        FrameEncoder& master;

        WeightAnalysis(FrameEncoder& fe) : master(fe) {}

        void processTasks(int workerThreadId);

    protected:

        WeightAnalysis operator=(const WeightAnalysis&);
    };

protected:

    bool initializeGeoms();

    /* analyze / compress frame, can be run in parallel within reference constraints */
    void compressFrame(int layer);

    /* called by compressFrame to generate final per-row bitstreams */
    void encodeSlice(uint32_t sliceAddr, int layer);

    void threadMain();
    int  collectCTUStatistics(const CUData& ctu, FrameStats* frameLog);
    void noiseReductionUpdate();
    void writeTrailingSEIMessages(int layer);
    bool writeToneMapInfo(x265_sei_payload *payload);

    /* Called by WaveFront::findJob() */
    virtual void processRow(int row, int threadId, int layer);
    virtual void processRowEncoder(int row, ThreadLocalData& tld, int layer);

    void enqueueRowEncoder(int row) { WaveFront::enqueueRow(row * 2 + 0); }
    void enqueueRowFilter(int row)  { WaveFront::enqueueRow(row * 2 + 1); }
    void enableRowEncoder(int row)  { WaveFront::enableRow(row * 2 + 0); }
    void enableRowFilter(int row)   { WaveFront::enableRow(row * 2 + 1); }
#if ENABLE_LIBVMAF
    void vmafFrameLevelScore();
#endif
    void collectDynDataFrame(int layer);
    void computeAvgTrainingData(int layer);
    void collectDynDataRow(CUData& ctu, FrameStats* rowStats);    
    void readModel(FilmGrainCharacteristics* m_filmGrain, FILE* filmgrain);
    void readAomModel(AomFilmGrainCharacteristics* m_aomFilmGrain, FILE* Aomfilmgrain);
};
}

#endif // ifndef X265_FRAMEENCODER_H