/src/vvenc/source/Lib/EncoderLib/EncCu.h
Line | Count | Source |
1 | | /* ----------------------------------------------------------------------------- |
2 | | The copyright in this software is being made available under the Clear BSD |
3 | | License, included below. No patent rights, trademark rights and/or |
4 | | other Intellectual Property Rights other than the copyrights concerning |
5 | | the Software are granted under this license. |
6 | | |
7 | | The Clear BSD License |
8 | | |
9 | | Copyright (c) 2019-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVenC Authors. |
10 | | All rights reserved. |
11 | | |
12 | | Redistribution and use in source and binary forms, with or without modification, |
13 | | are permitted (subject to the limitations in the disclaimer below) provided that |
14 | | the following conditions are met: |
15 | | |
16 | | * Redistributions of source code must retain the above copyright notice, |
17 | | this list of conditions and the following disclaimer. |
18 | | |
19 | | * Redistributions in binary form must reproduce the above copyright |
20 | | notice, this list of conditions and the following disclaimer in the |
21 | | documentation and/or other materials provided with the distribution. |
22 | | |
23 | | * Neither the name of the copyright holder nor the names of its |
24 | | contributors may be used to endorse or promote products derived from this |
25 | | software without specific prior written permission. |
26 | | |
27 | | NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY |
28 | | THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
29 | | CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
30 | | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
31 | | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
32 | | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
33 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
34 | | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
35 | | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER |
36 | | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
37 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
38 | | POSSIBILITY OF SUCH DAMAGE. |
39 | | |
40 | | |
41 | | ------------------------------------------------------------------------------------------- */ |
42 | | /** \file EncCu.h |
43 | | \brief Coding Unit (CU) encoder class (header) |
44 | | */ |
45 | | |
46 | | #pragma once |
47 | | |
48 | | #include "vvenc/vvencCfg.h" |
49 | | #include "CABACWriter.h" |
50 | | #include "IntraSearch.h" |
51 | | #include "InterSearch.h" |
52 | | #include "EncModeCtrl.h" |
53 | | #include "RateCtrl.h" |
54 | | #include "CommonLib/CommonDef.h" |
55 | | #include "CommonLib/Unit.h" |
56 | | #include "CommonLib/UnitPartitioner.h" |
57 | | #include "CommonLib/LoopFilter.h" |
58 | | #include "DecoderLib/DecCu.h" |
59 | | |
60 | | //! \ingroup EncoderLib |
61 | | //! \{ |
62 | | |
63 | | namespace vvenc { |
64 | | |
65 | | class EncModeCtrl; |
66 | | struct EncTestMode; |
67 | | class EncPicture; |
68 | | |
69 | | // ==================================================================================================================== |
70 | | // Class definition |
71 | | // ==================================================================================================================== |
72 | | struct GeoMergeCombo |
73 | | { |
74 | | int splitDir = 0; |
75 | | int8_t mergeIdx0 = -1; |
76 | | int8_t mergeIdx1 = -1; |
77 | | double cost = 0.0; |
78 | | }; |
79 | | |
80 | | struct SmallerThanComboCost |
81 | | { |
82 | | inline bool operator()(const GeoMergeCombo &first, const GeoMergeCombo &second) |
83 | 0 | { |
84 | 0 | return (first.cost < second.cost); |
85 | 0 | } |
86 | | }; |
87 | | |
88 | | struct GeoComboCostList |
89 | | { |
90 | | std::vector<GeoMergeCombo> list; |
91 | 0 | void sortByCost() { std::stable_sort(list.begin(), list.end(), SmallerThanComboCost()); }; |
92 | | }; |
93 | | |
94 | | class FastGeoCostList |
95 | | { |
96 | | using CostArray = double[GEO_NUM_PARTITION_MODE][2]; |
97 | | |
98 | | int m_maxNumGeoCand{ 0 }; |
99 | | CostArray *m_singleDistList{ nullptr }; |
100 | | |
101 | | public: |
102 | | |
103 | 0 | FastGeoCostList() {} |
104 | | ~FastGeoCostList() |
105 | 0 | { |
106 | 0 | delete[] m_singleDistList; |
107 | 0 | m_singleDistList = nullptr; |
108 | 0 | } |
109 | | |
110 | | void init( int maxNumGeoCand ) |
111 | 0 | { |
112 | 0 | if( m_maxNumGeoCand != maxNumGeoCand ) |
113 | 0 | { |
114 | 0 | delete[] m_singleDistList; |
115 | 0 | m_singleDistList = nullptr; |
116 | |
|
117 | 0 | CHECK( maxNumGeoCand > MRG_MAX_NUM_CANDS, "Too many candidates" ); |
118 | 0 | m_singleDistList = new CostArray[maxNumGeoCand]; |
119 | 0 | m_maxNumGeoCand = maxNumGeoCand; |
120 | 0 | } |
121 | 0 | } |
122 | | |
123 | | void insert( int splitDir, int partIdx, int mergeIdx, double cost ) |
124 | 0 | { |
125 | 0 | CHECKD( splitDir >= GEO_NUM_PARTITION_MODE, "geoIdx is too large" ); |
126 | 0 | CHECKD( mergeIdx >= m_maxNumGeoCand, "mergeIdx is too large" ); |
127 | 0 | CHECKD( partIdx >= 2, "partIdx is too large" ); |
128 | |
|
129 | 0 | m_singleDistList[mergeIdx][splitDir][partIdx] = cost; |
130 | 0 | } |
131 | | |
132 | | double getCost( const int splitDir, const int mergeCand0, const int mergeCand1 ) |
133 | 0 | { |
134 | 0 | return m_singleDistList[mergeCand0][splitDir][0] + m_singleDistList[mergeCand1][splitDir][1]; |
135 | 0 | } |
136 | | }; |
137 | | |
138 | | |
139 | | |
140 | | class MergeItem |
141 | | { |
142 | | private: |
143 | | PelStorage m_pelStorage; |
144 | | std::vector<MotionInfo> m_mvStorage; |
145 | | |
146 | | public: |
147 | | |
148 | | enum class MergeItemType |
149 | | { |
150 | | REGULAR, |
151 | | SBTMVP, |
152 | | AFFINE, |
153 | | MMVD, |
154 | | CIIP, |
155 | | GPM, |
156 | | IBC, |
157 | | NUM, |
158 | | }; |
159 | | |
160 | | double cost; |
161 | | std::array<MvField[3], 2> |
162 | | mvField; |
163 | | int mergeIdx; |
164 | | uint8_t bcwIdx; |
165 | | uint8_t interDir; |
166 | | bool useAltHpelIf; |
167 | | int8_t affineType; |
168 | | int8_t numCiipIntra; |
169 | | |
170 | | bool noResidual; |
171 | | bool noBdofRefine; |
172 | | |
173 | | bool lumaPredReady; |
174 | | bool chromaPredReady; |
175 | | |
176 | | MergeItemType mergeItemType; |
177 | | |
178 | | MergeItem(); |
179 | | ~MergeItem(); |
180 | | |
181 | | void create (ChromaFormat chromaFormat, const Area& area); |
182 | | void init (); |
183 | | void importMergeInfo (const MergeCtx& mergeCtx, int _mergeIdx, MergeItemType _mergeItemType, CodingUnit& cu); |
184 | | void importMergeInfo (const AffineMergeCtx& mergeCtx, int _mergeIdx, MergeItemType _mergeItemType, CodingUnit& cu); |
185 | | bool exportMergeInfo (CodingUnit& cu, bool forceNoResidual) const; |
186 | 0 | PelUnitBuf getPredBuf (const UnitArea& unitArea) { return m_pelStorage.getCompactBuf( unitArea ); } |
187 | 0 | CMotionBuf getMvBuf (const UnitArea &unitArea) const { return CMotionBuf( m_mvStorage.data(), g_miScaling.scale( unitArea.lumaSize() ) ); } |
188 | 0 | MotionBuf getMvBuf (const UnitArea &unitArea) { return MotionBuf( m_mvStorage.data(), g_miScaling.scale( unitArea.lumaSize() ) ); } |
189 | | |
190 | | static int getGpmUnfiedIndex( int splitDir, const MergeIdxPair &geoMergeIdx ) |
191 | 0 | { |
192 | 0 | return ( splitDir << 8 ) | ( geoMergeIdx[ 0 ] << 4 ) | geoMergeIdx[ 1 ]; |
193 | 0 | } |
194 | | |
195 | | static void updateGpmIdx( int mergeIdx, uint8_t &splitDir, MergeIdxPair &geoMergeIdx ) |
196 | 0 | { |
197 | 0 | splitDir = ( mergeIdx >> 8 ) & 0xFF; |
198 | 0 | geoMergeIdx[0] = ( mergeIdx >> 4 ) & 0xF; |
199 | 0 | geoMergeIdx[1] = mergeIdx & 0xF; |
200 | 0 | } |
201 | | }; |
202 | | |
203 | | class MergeItemList |
204 | | { |
205 | | private: |
206 | | std::vector<MergeItem*> m_mergeItems; |
207 | | std::vector<MergeItem*> m_list; |
208 | | size_t m_maxTrackingNum = 0; |
209 | | size_t m_maxSize; |
210 | | size_t m_maxExtSize; |
211 | | size_t m_numExt; |
212 | | |
213 | | public: |
214 | | MergeItemList(); |
215 | | ~MergeItemList(); |
216 | | |
217 | | void init (size_t maxListSize, size_t maxExtSize, ChromaFormat chromaFormat, SizeType ctuWidth, SizeType ctuHeight); |
218 | | MergeItem* allocateNewMergeItem (); |
219 | | bool insertMergeItemToList (MergeItem* p); |
220 | | void giveBackMergeItem (MergeItem* p); |
221 | | void resetList (size_t maxTrackingNum); |
222 | | void shrinkList (size_t reduceTo); |
223 | | MergeItem* getMergeItemInList (size_t index); |
224 | 0 | size_t size () const { return m_list.size(); } |
225 | 0 | size_t capacity () const { return m_maxTrackingNum; } |
226 | | }; |
227 | | |
228 | | using MergeBufVector = static_vector<PelUnitBuf, MRG_MAX_NUM_CANDS>; |
229 | | |
230 | | /// CU encoder class |
231 | | class EncCu |
232 | | : DecCu |
233 | | { |
234 | | private: |
235 | | struct CtxPair |
236 | | { |
237 | | Ctx start; |
238 | | Ctx best; |
239 | | }; |
240 | | |
241 | | std::vector<CtxPair> m_CtxBuffer; |
242 | | CtxPair* m_CurrCtx; |
243 | | CtxCache* m_CtxCache; |
244 | | |
245 | | // Data : encoder control |
246 | | |
247 | | static const int maxCuDepth = ( MAX_CU_SIZE_IDX - MIN_CU_LOG2 ) << 1; |
248 | | |
249 | | int m_cuChromaQpOffsetIdxPlus1; |
250 | | int m_tempQpDiff; |
251 | | std::vector<int>* m_globalCtuQpVector; |
252 | | XUCache m_unitCache; |
253 | | std::mutex* m_wppMutex; |
254 | | CodingStructure* m_pTempCS[maxCuDepth]; |
255 | | CodingStructure* m_pBestCS[maxCuDepth]; |
256 | | CodingStructure* m_pTempCS2; |
257 | | CodingStructure* m_pBestCS2; |
258 | | PelStorage m_pOrgBuffer[maxCuDepth]; |
259 | | PelStorage m_pRspBuffer[maxCuDepth]; |
260 | | |
261 | | // Access channel |
262 | | const VVEncCfg* m_pcEncCfg; |
263 | | IntraSearch m_cIntraSearch; |
264 | | InterSearch m_cInterSearch; |
265 | | RdCost m_cRdCost; |
266 | | LoopFilter m_cLoopFilter; |
267 | | |
268 | | CABACWriter* m_CABACEstimator; |
269 | | EncModeCtrl m_modeCtrl; |
270 | | TrQuant m_cTrQuant; ///< transform & quantization |
271 | | RateCtrl* m_pcRateCtrl; |
272 | | |
273 | | PelStorage m_aTmpStorageLCU [MAX_TMP_BUFS]; ///< used with CIIP, EDO, GEO |
274 | | PelStorage m_acMergeTmpBuffer[MRG_MAX_NUM_CANDS]; |
275 | | |
276 | | SortedPelUnitBufs<SORTED_BUFS> |
277 | | m_SortedPelUnitBufs; |
278 | | FastGeoCostList m_GeoCostList; |
279 | | static const MergeIdxPair |
280 | | m_GeoModeTest[GEO_MAX_NUM_CANDS]; |
281 | | double m_mergeBestSATDCost; |
282 | | |
283 | | MotionInfo m_subPuMiBuf[(MAX_CU_SIZE * MAX_CU_SIZE) >> (MIN_CU_LOG2 << 1)]; |
284 | | |
285 | | Mv m_refinedMvdL0[MRG_MAX_NUM_CANDS][MAX_NUM_SUBCU_DMVR]; |
286 | | |
287 | | double m_sbtCostSave[2]; |
288 | | // thread stuff |
289 | | Ctx* m_syncPicCtx; ///< context storage for state of contexts at the wavefront/WPP/entropy-coding-sync second CTU of tile-row used for estimation |
290 | | PelStorage m_dbBuffer; |
291 | | |
292 | | Partitioner m_partitioner; |
293 | | |
294 | | int m_bestBcwIdx[2]; |
295 | | double m_bestBcwCost[2]; |
296 | | |
297 | | int m_MergeSimpleFlag; |
298 | | int m_tileIdx; |
299 | | int m_EDO; |
300 | | |
301 | | GeoComboCostList m_comboList; |
302 | | MergeItemList m_mergeItemList; |
303 | | std::array<Mv, MAX_NUM_SUBCU_DMVR> |
304 | | m_subPuMvOffset[MRG_MAX_NUM_CANDS]; |
305 | | Distortion m_uiSadBestForQPA; |
306 | | |
307 | | static const double coefSquareCUsFasterFastMedium[2][5][2][2][2]; |
308 | | static const double coefSquareCUsSlowSlower[2][5][2][5][2][2][2]; |
309 | | |
310 | | public: |
311 | | EncCu(); |
312 | | virtual ~EncCu(); |
313 | | |
314 | | void init ( const VVEncCfg& encCfg, const SPS& sps, std::vector<int>* const globalCtuQpVector, Ctx* syncPicCtx, RateCtrl* pRateCtrl ); |
315 | | void setCtuEncRsrc ( CABACWriter* cabacEstimator, CtxCache* ctxCache, ReuseUniMv* pReuseUniMv, BlkUniMvInfoBuffer* pBlkUniMvInfoBuffer, AffineProfList* pAffineProfList, IbcBvCand* pCachedBvs ); |
316 | | void destroy (); |
317 | | |
318 | 0 | std::vector<int>* getQpPtr () const { return m_globalCtuQpVector; } |
319 | | |
320 | | void initPic ( Picture* pic ); |
321 | | void initSlice ( const Slice* slice ); |
322 | | void setUpLambda ( Slice& slice, const double dLambda, const int iQP, const bool setSliceLambda, const bool saveUnadjusted); |
323 | | void updateLambda ( const Slice& slice, const double ctuLambda, const int ctuQP, const int newQP, const bool saveUnadjusted); |
324 | | |
325 | | void encodeCtu ( Picture* pic, int (&prevQP)[MAX_NUM_CH], uint32_t ctuXPosInCtus, uint32_t ctuYPosInCtus ); |
326 | | |
327 | | private: |
328 | | void xCompressCtu ( CodingStructure& cs, const UnitArea& area, const unsigned ctuRsAddr, const int prevQP[] ); |
329 | | |
330 | | void xCalDebCost ( CodingStructure& cs, Partitioner& partitioner ); |
331 | | Distortion xGetDistortionDb ( CodingStructure& cs, CPelBuf& org, CPelBuf& reco, const CompArea& compArea, bool beforeDb ); |
332 | | |
333 | | void xCompressCU ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm ); |
334 | | bool xCheckBestMode ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm, const EncTestMode& encTestmode, const bool useEDO = false ); |
335 | | |
336 | | void xCheckRDCostIntra ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm, const EncTestMode& encTestMode ); |
337 | | void xCheckRDCostInter ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm, const EncTestMode& encTestMode ); |
338 | | void xCheckRDCostInterIMV ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm, const EncTestMode& encTestMode ); |
339 | | void xCheckRDCostUnifiedMerge |
340 | | ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, EncTestMode& encTestMode ); |
341 | | void xCheckModeSplit ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm, const EncTestMode& encTestMode ); |
342 | | void xCheckModeSplitInternal( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm, const EncTestMode& encTestMode, const ModeType modeTypeParent, bool& skipInterPass ); |
343 | | void xReuseCachedResult ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm ); |
344 | | |
345 | | void xCheckDQP ( CodingStructure& cs, Partitioner& partitioner, bool bKeepCtx = false); |
346 | | void xEncodeDontSplit ( CodingStructure& cs, Partitioner& partitioner); |
347 | | |
348 | | void xEncodeInterResidual ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm, const EncTestMode& encTestMode, |
349 | | int residualPass = 0, bool* bestHasNonResi = NULL, double* equBcwCost = NULL ); |
350 | | |
351 | | bool xIsBcwSkip( const CodingUnit& cu ) |
352 | 0 | { |
353 | 0 | if( cu.slice->sliceType != VVENC_B_SLICE ) |
354 | 0 | { |
355 | 0 | return true; |
356 | 0 | } |
357 | 0 | return( (m_pcEncCfg->m_QP > 32) && ((cu.slice->TLayer >= 4) |
358 | 0 | || ((cu.refIdx[0] >= 0 && cu.refIdx[1] >= 0) |
359 | 0 | && ( abs(cu.slice->poc - cu.slice->getRefPOC(REF_PIC_LIST_0, cu.refIdx[0])) == 1 |
360 | 0 | || abs(cu.slice->poc - cu.slice->getRefPOC(REF_PIC_LIST_1, cu.refIdx[1])) == 1 |
361 | 0 | ) ) )); |
362 | 0 | } |
363 | | |
364 | | uint64_t xCalcPuMeBits ( const CodingUnit& cu); |
365 | | double xCalcDistortion ( CodingStructure *&cur_CS, ChannelType chType, int BitDepth, int imv); |
366 | | int xCheckMMVDCand ( MmvdIdx& mmvdMergeCand, int& bestDir, int tempNum, double& bestCostOffset, double& bestCostMerge, double bestCostList ); |
367 | | void xCheckRDCostIBCMode ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm, const EncTestMode& encTestMode ); |
368 | | void xCheckRDCostIBCModeMerge2Nx2N ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& partitioner, const EncTestMode& encTestMode ); |
369 | | |
370 | | |
371 | | CodingUnit* getCuForInterPrediction ( CodingStructure* cs, const EncTestMode& encTestMode ); |
372 | | unsigned int updateRdCheckingNum ( MergeItemList&, double threshold, unsigned int numMergeSatdCand ); |
373 | | |
374 | | void generateMergePrediction ( const UnitArea& unitArea, MergeItem* mergeItem, CodingUnit& cu, bool luma, bool chroma, |
375 | | PelUnitBuf& dstBuf, bool finalRd, bool forceNoResidual, PelUnitBuf* predBuf1, PelUnitBuf* predBuf2 ); |
376 | | double calcLumaCost4MergePrediction( const TempCtx& ctxStart, const PelUnitBuf& predBuf, double lambda, CodingUnit& pu, DistParam& distParam ); |
377 | | void addRegularCandsToPruningList( const MergeCtx& mergeCtx, const UnitArea& localUnitArea, double sqrtLambdaForFirstPassIntra, |
378 | | const TempCtx& ctxStart, DistParam& distParam, CodingUnit& cu, bool* sameMv, MergeBufVector& regularPred ); |
379 | | void addCiipCandsToPruningList ( const MergeCtx& mergeCtx, const UnitArea& localUnitArea, double sqrtLambdaForFirstPassIntra, |
380 | | const TempCtx& ctxStart, DistParam& distParam, CodingUnit& cu, bool* sameMv ); |
381 | | void addMmvdCandsToPruningList ( const MergeCtx& mergeCtx, const UnitArea& localUnitArea, double sqrtLambdaForFirstPassIntra, |
382 | | const TempCtx& ctxStart, DistParam& distParam, CodingUnit& cu ); |
383 | | void addAffineCandsToPruningList ( AffineMergeCtx& affineMergeCtx, const UnitArea& localUnitArea, double sqrtLambdaForFirstPass, |
384 | | const TempCtx& ctxStart, DistParam& distParam, CodingUnit& cu ); |
385 | | void addGpmCandsToPruningList ( const MergeCtx& mergeCtx, const UnitArea& localUnitArea, double sqrtLambdaForFirstPass, |
386 | | const TempCtx& ctxStart, const GeoComboCostList& comboList, MergeBufVector& geoBuffer, DistParam& distParam, CodingUnit& cu ); |
387 | | |
388 | | bool prepareGpmComboList ( const MergeCtx& mergeCtx, const UnitArea& localUnitArea, double sqrtLambdaForFirstPass, |
389 | | GeoComboCostList& comboList, MergeBufVector& geoBuffer, CodingUnit& cu ); |
390 | | // TODO: for now skip that |
391 | | //void checkEarlySkip ( const CodingStructure* bestCS, const Partitioner &partitioner ); |
392 | | }; |
393 | | |
394 | | } // namespace vvenc |
395 | | |
396 | | //! \} |
397 | | |