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
|