/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 | | |
44 | | namespace X265_NS { |
45 | | // private x265 namespace |
46 | | |
47 | | class ThreadPool; |
48 | | class Encoder; |
49 | | |
50 | 0 | #define ANGULAR_MODE_ID 2 |
51 | 0 | #define AMP_ID 3 |
52 | | |
53 | | struct StatisticLog |
54 | | { |
55 | | uint64_t cntInter[4]; |
56 | | uint64_t cntIntra[4]; |
57 | | uint64_t cuInterDistribution[4][INTER_MODES]; |
58 | | uint64_t cuIntraDistribution[4][INTRA_MODES]; |
59 | | uint64_t cntIntraNxN; |
60 | | uint64_t cntSkipCu[4]; |
61 | | uint64_t cntTotalCu[4]; |
62 | | uint64_t totalCu; |
63 | | |
64 | | StatisticLog() |
65 | 0 | { |
66 | 0 | memset(this, 0, sizeof(StatisticLog)); |
67 | 0 | } |
68 | | }; |
69 | | |
70 | | /* manages the state of encoding one row of CTU blocks. When |
71 | | * WPP is active, several rows will be simultaneously encoded. */ |
72 | | struct CTURow |
73 | | { |
74 | | Entropy bufferedEntropy; /* store CTU2 context for next row CTU0 */ |
75 | | Entropy rowGoOnCoder; /* store context between CTUs, code bitstream if !SAO */ |
76 | | unsigned int sliceId; /* store current row slice id */ |
77 | | |
78 | | FrameStats rowStats; |
79 | | |
80 | | /* Threading variables */ |
81 | | |
82 | | /* This lock must be acquired when reading or writing m_active or m_busy */ |
83 | | Lock lock; |
84 | | |
85 | | /* row is ready to run, has no neighbor dependencies. The row may have |
86 | | * external dependencies (reference frame pixels) that prevent it from being |
87 | | * processed, so it may stay with m_active=true for some time before it is |
88 | | * encoded by a worker thread. */ |
89 | | volatile bool active; |
90 | | |
91 | | /* row is being processed by a worker thread. This flag is only true when a |
92 | | * worker thread is within the context of FrameEncoder::processRow(). This |
93 | | * flag is used to detect multiple possible wavefront problems. */ |
94 | | volatile bool busy; |
95 | | |
96 | | /* count of completed CUs in this row */ |
97 | | volatile uint32_t completed; |
98 | | volatile uint32_t avgQPComputed; |
99 | | |
100 | | volatile int reEncode; |
101 | | |
102 | | /* called at the start of each frame to initialize state */ |
103 | | void init(Entropy& initContext, unsigned int sid) |
104 | 0 | { |
105 | 0 | active = false; |
106 | 0 | busy = false; |
107 | 0 | completed = 0; |
108 | 0 | avgQPComputed = 0; |
109 | 0 | sliceId = sid; |
110 | 0 | reEncode = 0; |
111 | 0 | memset(&rowStats, 0, sizeof(rowStats)); |
112 | 0 | rowGoOnCoder.load(initContext); |
113 | 0 | } |
114 | | }; |
115 | | |
116 | | // Manages the wave-front processing of a single encoding frame |
117 | | class FrameEncoder : public WaveFront, public Thread |
118 | | { |
119 | | public: |
120 | | |
121 | | FrameEncoder(); |
122 | | |
123 | 0 | virtual ~FrameEncoder() {} |
124 | | |
125 | | virtual bool init(Encoder *top, int numRows, int numCols); |
126 | | |
127 | | void destroy(); |
128 | | |
129 | | /* triggers encode of a new frame by the worker thread */ |
130 | | bool startCompressFrame(Frame* curFrame); |
131 | | |
132 | | /* blocks until worker thread is done, returns access unit */ |
133 | | Frame *getEncodedPicture(NALList& list); |
134 | | |
135 | | void initDecodedPictureHashSEI(int row, int cuAddr, int height); |
136 | | |
137 | | Event m_enable; |
138 | | Event m_done; |
139 | | Event m_completionEvent; |
140 | | int m_localTldIdx; |
141 | | bool m_reconfigure; /* reconfigure in progress */ |
142 | | volatile bool m_threadActive; |
143 | | volatile bool m_bAllRowsStop; |
144 | | volatile int m_completionCount; |
145 | | volatile int m_vbvResetTriggerRow; |
146 | | volatile int m_sliceCnt; |
147 | | |
148 | | uint32_t m_numRows; |
149 | | uint32_t m_numCols; |
150 | | uint32_t m_filterRowDelay; |
151 | | uint32_t m_filterRowDelayCus; |
152 | | uint32_t m_refLagRows; |
153 | | bool m_bUseSao; |
154 | | |
155 | | CTURow* m_rows; |
156 | | uint16_t m_sliceAddrBits; |
157 | | uint32_t m_sliceGroupSize; |
158 | | uint32_t* m_sliceBaseRow; |
159 | | uint32_t* m_sliceMaxBlockRow; |
160 | | int64_t m_rowSliceTotalBits[2]; |
161 | | RateControlEntry m_rce; |
162 | | SEIDecodedPictureHash m_seiReconPictureDigest; |
163 | | |
164 | | uint64_t m_SSDY; |
165 | | uint64_t m_SSDU; |
166 | | uint64_t m_SSDV; |
167 | | double m_ssim; |
168 | | uint64_t m_accessUnitBits; |
169 | | uint32_t m_ssimCnt; |
170 | | |
171 | | volatile int m_activeWorkerCount; // count of workers currently encoding or filtering CTUs |
172 | | volatile int m_totalActiveWorkerCount; // sum of m_activeWorkerCount sampled at end of each CTU |
173 | | volatile int m_activeWorkerCountSamples; // count of times m_activeWorkerCount was sampled (think vbv restarts) |
174 | | volatile int m_countRowBlocks; // count of workers forced to abandon a row because of top dependency |
175 | | int64_t m_startCompressTime; // timestamp when frame encoder is given a frame |
176 | | int64_t m_row0WaitTime; // timestamp when row 0 is allowed to start |
177 | | int64_t m_allRowsAvailableTime; // timestamp when all reference dependencies are resolved |
178 | | int64_t m_endCompressTime; // timestamp after all CTUs are compressed |
179 | | int64_t m_endFrameTime; // timestamp after RCEnd, NR updates, etc |
180 | | int64_t m_stallStartTime; // timestamp when worker count becomes 0 |
181 | | int64_t m_prevOutputTime; // timestamp when prev frame was retrieved by API thread |
182 | | int64_t m_slicetypeWaitTime; // total elapsed time waiting for decided frame |
183 | | int64_t m_totalWorkerElapsedTime; // total elapsed time spent by worker threads processing CTUs |
184 | | int64_t m_totalNoWorkerTime; // total elapsed time without any active worker threads |
185 | | #if DETAILED_CU_STATS |
186 | | CUStats m_cuStats; |
187 | | #endif |
188 | | |
189 | | Encoder* m_top; |
190 | | x265_param* m_param; |
191 | | Frame* m_frame; |
192 | | NoiseReduction* m_nr; |
193 | | ThreadLocalData* m_tld; /* for --no-wpp */ |
194 | | Bitstream* m_outStreams; |
195 | | Bitstream* m_backupStreams; |
196 | | uint32_t* m_substreamSizes; |
197 | | |
198 | | CUGeom* m_cuGeoms; |
199 | | uint32_t* m_ctuGeomMap; |
200 | | |
201 | | Bitstream m_bs; |
202 | | MotionReference m_mref[2][MAX_NUM_REF + 1]; |
203 | | Entropy m_entropyCoder; |
204 | | Entropy m_initSliceContext; |
205 | | FrameFilter m_frameFilter; |
206 | | NALList m_nalList; |
207 | | |
208 | | class WeightAnalysis : public BondedTaskGroup |
209 | | { |
210 | | public: |
211 | | |
212 | | FrameEncoder& master; |
213 | | |
214 | 0 | WeightAnalysis(FrameEncoder& fe) : master(fe) {} |
215 | | |
216 | | void processTasks(int workerThreadId); |
217 | | |
218 | | protected: |
219 | | |
220 | | WeightAnalysis operator=(const WeightAnalysis&); |
221 | | }; |
222 | | |
223 | | protected: |
224 | | |
225 | | bool initializeGeoms(); |
226 | | |
227 | | /* analyze / compress frame, can be run in parallel within reference constraints */ |
228 | | void compressFrame(); |
229 | | |
230 | | /* called by compressFrame to generate final per-row bitstreams */ |
231 | | void encodeSlice(uint32_t sliceAddr); |
232 | | |
233 | | void threadMain(); |
234 | | int collectCTUStatistics(const CUData& ctu, FrameStats* frameLog); |
235 | | void noiseReductionUpdate(); |
236 | | void writeTrailingSEIMessages(); |
237 | | bool writeToneMapInfo(x265_sei_payload *payload); |
238 | | |
239 | | /* Called by WaveFront::findJob() */ |
240 | | virtual void processRow(int row, int threadId); |
241 | | virtual void processRowEncoder(int row, ThreadLocalData& tld); |
242 | | |
243 | 0 | void enqueueRowEncoder(int row) { WaveFront::enqueueRow(row * 2 + 0); } |
244 | 0 | void enqueueRowFilter(int row) { WaveFront::enqueueRow(row * 2 + 1); } |
245 | 0 | void enableRowEncoder(int row) { WaveFront::enableRow(row * 2 + 0); } |
246 | 0 | void enableRowFilter(int row) { WaveFront::enableRow(row * 2 + 1); } |
247 | | #if ENABLE_LIBVMAF |
248 | | void vmafFrameLevelScore(); |
249 | | #endif |
250 | | void collectDynDataFrame(); |
251 | | void computeAvgTrainingData(); |
252 | | void collectDynDataRow(CUData& ctu, FrameStats* rowStats); |
253 | | }; |
254 | | } |
255 | | |
256 | | #endif // ifndef X265_FRAMEENCODER_H |