0
|
1 /*****************************************************************************
|
|
2 * Copyright (C) 2013 x265 project
|
|
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 #define ANGULAR_MODE_ID 2
|
|
51 #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 {
|
|
66 memset(this, 0, sizeof(StatisticLog));
|
|
67 }
|
|
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
|
|
77 FrameStats rowStats;
|
|
78
|
|
79 /* Threading variables */
|
|
80
|
|
81 /* This lock must be acquired when reading or writing m_active or m_busy */
|
|
82 Lock lock;
|
|
83
|
|
84 /* row is ready to run, has no neighbor dependencies. The row may have
|
|
85 * external dependencies (reference frame pixels) that prevent it from being
|
|
86 * processed, so it may stay with m_active=true for some time before it is
|
|
87 * encoded by a worker thread. */
|
|
88 volatile bool active;
|
|
89
|
|
90 /* row is being processed by a worker thread. This flag is only true when a
|
|
91 * worker thread is within the context of FrameEncoder::processRow(). This
|
|
92 * flag is used to detect multiple possible wavefront problems. */
|
|
93 volatile bool busy;
|
|
94
|
|
95 /* count of completed CUs in this row */
|
|
96 volatile uint32_t completed;
|
|
97
|
|
98 /* called at the start of each frame to initialize state */
|
|
99 void init(Entropy& initContext)
|
|
100 {
|
|
101 active = false;
|
|
102 busy = false;
|
|
103 completed = 0;
|
|
104 memset(&rowStats, 0, sizeof(rowStats));
|
|
105 rowGoOnCoder.load(initContext);
|
|
106 }
|
|
107 };
|
|
108
|
|
109 // Manages the wave-front processing of a single encoding frame
|
|
110 class FrameEncoder : public WaveFront, public Thread
|
|
111 {
|
|
112 public:
|
|
113
|
|
114 FrameEncoder();
|
|
115
|
|
116 virtual ~FrameEncoder() {}
|
|
117
|
|
118 virtual bool init(Encoder *top, int numRows, int numCols);
|
|
119
|
|
120 void destroy();
|
|
121
|
|
122 /* triggers encode of a new frame by the worker thread */
|
|
123 bool startCompressFrame(Frame* curFrame);
|
|
124
|
|
125 /* blocks until worker thread is done, returns access unit */
|
|
126 Frame *getEncodedPicture(NALList& list);
|
|
127
|
|
128 Event m_enable;
|
|
129 Event m_done;
|
|
130 Event m_completionEvent;
|
|
131 int m_localTldIdx;
|
|
132
|
|
133 volatile bool m_threadActive;
|
|
134 volatile bool m_bAllRowsStop;
|
|
135 volatile int m_completionCount;
|
|
136 volatile int m_vbvResetTriggerRow;
|
|
137
|
|
138 uint32_t m_numRows;
|
|
139 uint32_t m_numCols;
|
|
140 uint32_t m_filterRowDelay;
|
|
141 uint32_t m_filterRowDelayCus;
|
|
142 uint32_t m_refLagRows;
|
|
143
|
|
144 CTURow* m_rows;
|
|
145 RateControlEntry m_rce;
|
|
146 SEIDecodedPictureHash m_seiReconPictureDigest;
|
|
147
|
|
148 uint64_t m_SSDY;
|
|
149 uint64_t m_SSDU;
|
|
150 uint64_t m_SSDV;
|
|
151 double m_ssim;
|
|
152 uint64_t m_accessUnitBits;
|
|
153 uint32_t m_ssimCnt;
|
|
154 MD5Context m_state[3];
|
|
155 uint32_t m_crc[3];
|
|
156 uint32_t m_checksum[3];
|
|
157
|
|
158 volatile int m_activeWorkerCount; // count of workers currently encoding or filtering CTUs
|
|
159 volatile int m_totalActiveWorkerCount; // sum of m_activeWorkerCount sampled at end of each CTU
|
|
160 volatile int m_activeWorkerCountSamples; // count of times m_activeWorkerCount was sampled (think vbv restarts)
|
|
161 volatile int m_countRowBlocks; // count of workers forced to abandon a row because of top dependency
|
|
162 int64_t m_startCompressTime; // timestamp when frame encoder is given a frame
|
|
163 int64_t m_row0WaitTime; // timestamp when row 0 is allowed to start
|
|
164 int64_t m_allRowsAvailableTime; // timestamp when all reference dependencies are resolved
|
|
165 int64_t m_endCompressTime; // timestamp after all CTUs are compressed
|
|
166 int64_t m_endFrameTime; // timestamp after RCEnd, NR updates, etc
|
|
167 int64_t m_stallStartTime; // timestamp when worker count becomes 0
|
|
168 int64_t m_prevOutputTime; // timestamp when prev frame was retrieved by API thread
|
|
169 int64_t m_slicetypeWaitTime; // total elapsed time waiting for decided frame
|
|
170 int64_t m_totalWorkerElapsedTime; // total elapsed time spent by worker threads processing CTUs
|
|
171 int64_t m_totalNoWorkerTime; // total elapsed time without any active worker threads
|
|
172 #if DETAILED_CU_STATS
|
|
173 CUStats m_cuStats;
|
|
174 #endif
|
|
175
|
|
176 Encoder* m_top;
|
|
177 x265_param* m_param;
|
|
178 Frame* m_frame;
|
|
179 NoiseReduction* m_nr;
|
|
180 ThreadLocalData* m_tld; /* for --no-wpp */
|
|
181 Bitstream* m_outStreams;
|
|
182 uint32_t* m_substreamSizes;
|
|
183
|
|
184 CUGeom* m_cuGeoms;
|
|
185 uint32_t* m_ctuGeomMap;
|
|
186
|
|
187 Bitstream m_bs;
|
|
188 MotionReference m_mref[2][MAX_NUM_REF + 1];
|
|
189 Entropy m_entropyCoder;
|
|
190 Entropy m_initSliceContext;
|
|
191 FrameFilter m_frameFilter;
|
|
192 NALList m_nalList;
|
|
193
|
|
194 class WeightAnalysis : public BondedTaskGroup
|
|
195 {
|
|
196 public:
|
|
197
|
|
198 FrameEncoder& master;
|
|
199
|
|
200 WeightAnalysis(FrameEncoder& fe) : master(fe) {}
|
|
201
|
|
202 void processTasks(int workerThreadId);
|
|
203
|
|
204 protected:
|
|
205
|
|
206 WeightAnalysis operator=(const WeightAnalysis&);
|
|
207 };
|
|
208
|
|
209 protected:
|
|
210
|
|
211 bool initializeGeoms();
|
|
212
|
|
213 /* analyze / compress frame, can be run in parallel within reference constraints */
|
|
214 void compressFrame();
|
|
215
|
|
216 /* called by compressFrame to generate final per-row bitstreams */
|
|
217 void encodeSlice();
|
|
218
|
|
219 void threadMain();
|
|
220 int collectCTUStatistics(const CUData& ctu, FrameStats* frameLog);
|
|
221 void noiseReductionUpdate();
|
|
222
|
|
223 /* Called by WaveFront::findJob() */
|
|
224 virtual void processRow(int row, int threadId);
|
|
225 virtual void processRowEncoder(int row, ThreadLocalData& tld);
|
|
226
|
|
227 void enqueueRowEncoder(int row) { WaveFront::enqueueRow(row * 2 + 0); }
|
|
228 void enqueueRowFilter(int row) { WaveFront::enqueueRow(row * 2 + 1); }
|
|
229 void enableRowEncoder(int row) { WaveFront::enableRow(row * 2 + 0); }
|
|
230 void enableRowFilter(int row) { WaveFront::enableRow(row * 2 + 1); }
|
|
231 };
|
|
232 }
|
|
233
|
|
234 #endif // ifndef X265_FRAMEENCODER_H
|