/src/vvenc/source/Lib/CommonLib/DepQuant.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 | | #pragma once |
43 | | |
44 | | #include "CommonDef.h" |
45 | | #include "Contexts.h" |
46 | | #include "Slice.h" |
47 | | #include "Unit.h" |
48 | | #include "UnitPartitioner.h" |
49 | | #include "QuantRDOQ2.h" |
50 | | |
51 | | //! \ingroup CommonLib |
52 | | //! \{ |
53 | | |
54 | | namespace vvenc { |
55 | | |
56 | | namespace DQIntern |
57 | | { |
58 | | /*================================================================================*/ |
59 | | /*===== =====*/ |
60 | | /*===== R A T E E S T I M A T O R =====*/ |
61 | | /*===== =====*/ |
62 | | /*================================================================================*/ |
63 | | |
64 | | struct NbInfoSbb |
65 | | { |
66 | | uint8_t numInv; |
67 | | uint8_t invInPos[5]; |
68 | | }; |
69 | | struct NbInfoOut |
70 | | { |
71 | | uint16_t maxDist; |
72 | | uint16_t num; |
73 | | uint16_t outPos[5]; |
74 | | }; |
75 | | struct CoeffFracBits |
76 | | { |
77 | | int32_t bits[6]; |
78 | | }; |
79 | | |
80 | | enum ScanPosType : int8_t { SCAN_ISCSBB = 0, SCAN_SOCSBB = 1, SCAN_EOCSBB = 2 }; |
81 | | |
82 | | struct ScanInfo |
83 | | { |
84 | 0 | ScanInfo() {} |
85 | | short numSbb; |
86 | | short scanIdx; |
87 | | short rasterPos; |
88 | | short sbbPos; // byte |
89 | | short nextSbbRight; |
90 | | short nextSbbBelow; |
91 | | int8_t sbbSize; |
92 | | int8_t insidePos; |
93 | | int8_t nextInsidePos; |
94 | | ScanPosType spt; |
95 | | int8_t posX; |
96 | | int8_t posY; |
97 | | int8_t sigCtxOffsetNext; |
98 | | int8_t gtxCtxOffsetNext; |
99 | | NbInfoSbb currNbInfoSbb; |
100 | | }; |
101 | | |
102 | | class Rom; |
103 | | struct TUParameters |
104 | | { |
105 | | TUParameters ( const Rom& rom, const unsigned width, const unsigned height, const ChannelType chType ); |
106 | | ~TUParameters() |
107 | 0 | { |
108 | 0 | delete [] m_scanInfo; |
109 | 0 | } |
110 | | |
111 | | ChannelType m_chType; |
112 | | unsigned m_width; |
113 | | unsigned m_height; |
114 | | unsigned m_numCoeff; |
115 | | unsigned m_numSbb; |
116 | | unsigned m_log2SbbWidth; |
117 | | unsigned m_log2SbbHeight; |
118 | | unsigned m_log2SbbSize; |
119 | | unsigned m_sbbSize; |
120 | | unsigned m_sbbMask; |
121 | | unsigned m_widthInSbb; |
122 | | unsigned m_heightInSbb; |
123 | | const ScanElement *m_scanSbbId2SbbPos; |
124 | | const ScanElement *m_scanId2BlkPos; |
125 | | const NbInfoSbb* m_scanId2NbInfoSbb; |
126 | | const NbInfoOut* m_scanId2NbInfoOut; |
127 | | ScanInfo* m_scanInfo; |
128 | | private: |
129 | | void xSetScanInfo( ScanInfo& scanInfo, int scanIdx ); |
130 | | }; |
131 | | |
132 | | class Rom |
133 | | { |
134 | | public: |
135 | 0 | Rom() : m_scansInitialized(false) {} |
136 | 0 | ~Rom() { xUninitScanArrays(); } |
137 | 0 | void init () { xInitScanArrays(); } |
138 | 0 | const NbInfoSbb* getNbInfoSbb( int hd, int vd ) const { return m_scanId2NbInfoSbbArray[hd][vd]; } |
139 | 0 | const NbInfoOut* getNbInfoOut( int hd, int vd ) const { return m_scanId2NbInfoOutArray[hd][vd]; } |
140 | | const TUParameters* getTUPars ( const CompArea& area, const ComponentID compID ) const |
141 | 0 | { |
142 | 0 | return m_tuParameters[Log2(area.width)][Log2(area.height)][toChannelType(compID)]; |
143 | 0 | } |
144 | | private: |
145 | | void xInitScanArrays (); |
146 | | void xUninitScanArrays (); |
147 | | private: |
148 | | bool m_scansInitialized; |
149 | | NbInfoSbb* m_scanId2NbInfoSbbArray[ MAX_TU_SIZE_IDX ][ MAX_TU_SIZE_IDX ]; |
150 | | NbInfoOut* m_scanId2NbInfoOutArray[ MAX_TU_SIZE_IDX ][ MAX_TU_SIZE_IDX ]; |
151 | | TUParameters* m_tuParameters [ MAX_TU_SIZE_IDX ][ MAX_TU_SIZE_IDX ][ MAX_NUM_CH ]; |
152 | | }; |
153 | | |
154 | | class RateEstimator |
155 | | { |
156 | | public: |
157 | 0 | RateEstimator () {} |
158 | 0 | ~RateEstimator() {} |
159 | | void initCtx ( const TUParameters& tuPars, const TransformUnit& tu, const ComponentID compID, const FracBitsAccess& fracBitsAccess ); |
160 | | |
161 | 0 | inline const BinFracBits *sigSbbFracBits() const { return m_sigSbbFracBits; } |
162 | | inline const BinFracBits *sigFlagBits(unsigned stateId) const |
163 | 0 | { |
164 | 0 | return m_sigFracBits[std::max(((int) stateId) - 1, 0)]; |
165 | 0 | } |
166 | 0 | inline const CoeffFracBits *gtxFracBits() const { return m_gtxFracBits; } |
167 | | inline int32_t lastOffset(unsigned scanIdx) const |
168 | 0 | { |
169 | 0 | return m_lastBitsX[m_scanId2Pos[scanIdx].x] + m_lastBitsY[m_scanId2Pos[scanIdx].y]; |
170 | 0 | } |
171 | | |
172 | | private: |
173 | | void xSetLastCoeffOffset ( const FracBitsAccess& fracBitsAccess, const TUParameters& tuPars, const TransformUnit& tu, const ComponentID compID ); |
174 | | void xSetSigSbbFracBits ( const FracBitsAccess& fracBitsAccess, ChannelType chType ); |
175 | | void xSetSigFlagBits ( const FracBitsAccess& fracBitsAccess, ChannelType chType ); |
176 | | void xSetGtxFlagBits ( const FracBitsAccess& fracBitsAccess, ChannelType chType ); |
177 | | |
178 | | public: |
179 | | static const unsigned sm_numCtxSetsSig = 3; |
180 | | static const unsigned sm_numCtxSetsGtx = 2; |
181 | | static const unsigned sm_maxNumSigSbbCtx = 2; |
182 | | static const unsigned sm_maxNumSigCtx = 12; |
183 | | static const unsigned sm_maxNumGtxCtx = 21; |
184 | | |
185 | | private: |
186 | | const ScanElement * m_scanId2Pos; |
187 | | int32_t m_lastBitsX [ MAX_TB_SIZEY ]; |
188 | | int32_t m_lastBitsY [ MAX_TB_SIZEY ]; |
189 | | BinFracBits m_sigSbbFracBits [ sm_maxNumSigSbbCtx ]; |
190 | | BinFracBits m_sigFracBits [ sm_numCtxSetsSig ][ sm_maxNumSigCtx ]; |
191 | | CoeffFracBits m_gtxFracBits [ sm_maxNumGtxCtx ]; |
192 | | }; |
193 | | |
194 | | /*================================================================================*/ |
195 | | /*===== =====*/ |
196 | | /*===== P R E - Q U A N T I Z E R =====*/ |
197 | | /*===== =====*/ |
198 | | /*================================================================================*/ |
199 | | |
200 | | struct PQData |
201 | | { |
202 | | TCoeff absLevel; |
203 | | int64_t deltaDist; |
204 | | }; |
205 | | |
206 | | class Quantizer |
207 | | { |
208 | | public: |
209 | 0 | Quantizer() {} |
210 | 0 | void init ( int dqThrVal ) { m_DqThrVal = dqThrVal; } |
211 | | void dequantBlock ( const TransformUnit& tu, const ComponentID compID, const QpParam& cQP, CoeffBuf& recCoeff, bool enableScalingLists, int* piDequantCoef ) const; |
212 | | void initQuantBlock ( const TransformUnit& tu, const ComponentID compID, const QpParam& cQP, const double lambda, int gValue = -1 ); |
213 | | bool preQuantCoeff ( const TCoeff absCoeff, PQData *pqData, int quanCoeff ) const; |
214 | 0 | TCoeff getLastThreshold() const { return m_thresLast; } |
215 | 0 | TCoeff getSSbbThreshold() const { return m_thresSSbb; } |
216 | | |
217 | 0 | int64_t getQScale () const { return m_QScale; } |
218 | | |
219 | | // quantization |
220 | | int m_DqThrVal; |
221 | | int m_QShift; |
222 | | int64_t m_QAdd; |
223 | | int64_t m_QScale; |
224 | | TCoeff m_maxQIdx; |
225 | | TCoeff m_thresLast; |
226 | | TCoeff m_thresSSbb; |
227 | | // distortion normalization |
228 | | int m_DistShift; |
229 | | int64_t m_DistAdd; |
230 | | int64_t m_DistStepAdd; |
231 | | int64_t m_DistOrgFact; |
232 | | }; |
233 | | |
234 | 0 | #define RICEMAX 32 |
235 | | extern const int32_t g_goRiceBits[4][RICEMAX]; |
236 | | |
237 | | /*================================================================================*/ |
238 | | /*===== =====*/ |
239 | | /*===== T C Q S T A T E =====*/ |
240 | | /*===== =====*/ |
241 | | /*================================================================================*/ |
242 | | |
243 | | struct StateMem; |
244 | | |
245 | | struct SbbCtx |
246 | | { |
247 | | uint8_t* sbbFlags; |
248 | | uint8_t* levels; |
249 | | }; |
250 | | |
251 | | class CommonCtx |
252 | | { |
253 | | friend class DepQuant; |
254 | | |
255 | | public: |
256 | 0 | CommonCtx() : m_currSbbCtx( m_allSbbCtx ), m_prevSbbCtx( m_currSbbCtx + 4 ) {} |
257 | | |
258 | 0 | inline void swap() { std::swap( m_currSbbCtx, m_prevSbbCtx ); } |
259 | | |
260 | | inline void reset( const TUParameters& tuPars, const RateEstimator& rateEst ) |
261 | 0 | { |
262 | 0 | m_nbInfo = tuPars.m_scanId2NbInfoOut; |
263 | 0 | ::memcpy( m_sbbFlagBits, rateEst.sigSbbFracBits(), 2 * sizeof( BinFracBits ) ); |
264 | 0 | const int numSbb = tuPars.m_numSbb; |
265 | 0 | const int chunkSize = numSbb + tuPars.m_numCoeff; |
266 | 0 | uint8_t* nextMem = m_memory; |
267 | 0 | for( int k = 0; k < 8; k++, nextMem += chunkSize ) |
268 | 0 | { |
269 | 0 | m_allSbbCtx[k].sbbFlags = nextMem; |
270 | 0 | m_allSbbCtx[k].levels = nextMem + numSbb; |
271 | 0 | } |
272 | 0 | } |
273 | | |
274 | | void update( const ScanInfo& scanInfo, const int prevId, int stateId, StateMem& curr ); |
275 | | |
276 | | void getLevelPtrs( const ScanInfo& scanInfo, uint8_t*& levels0, uint8_t*& levels1, uint8_t*& levels2, uint8_t*& levels3 ) |
277 | 0 | { |
278 | 0 | levels0 = m_currSbbCtx[0].levels + scanInfo.scanIdx; |
279 | 0 | levels1 = m_currSbbCtx[1].levels + scanInfo.scanIdx; |
280 | 0 | levels2 = m_currSbbCtx[2].levels + scanInfo.scanIdx; |
281 | 0 | levels3 = m_currSbbCtx[3].levels + scanInfo.scanIdx; |
282 | 0 | } |
283 | | |
284 | | private: |
285 | | const NbInfoOut* m_nbInfo; |
286 | | BinFracBits m_sbbFlagBits[2]; |
287 | | SbbCtx m_allSbbCtx[8]; |
288 | | SbbCtx* m_currSbbCtx; |
289 | | SbbCtx* m_prevSbbCtx; |
290 | | uint8_t m_memory[8 * ( MAX_TB_SIZEY * MAX_TB_SIZEY + MLS_GRP_NUM )]; |
291 | | }; |
292 | | |
293 | | static constexpr int64_t rdCostInit = std::numeric_limits<int64_t>::max() >> 1; |
294 | | |
295 | | struct Decisions |
296 | | { |
297 | | int64_t rdCost[4]; |
298 | | TCoeffSig absLevel[4]; |
299 | | int8_t prevId[4]; |
300 | | }; |
301 | | |
302 | | struct StateMem |
303 | | { |
304 | | int64_t rdCost[4]; |
305 | | int16_t remRegBins[4]; |
306 | | int32_t sbbBits0[4]; |
307 | | int32_t sbbBits1[4]; |
308 | | |
309 | | uint8_t tplAcc[16][4]; |
310 | | uint8_t sum1st[16][4]; |
311 | | uint8_t absVal[16][4]; |
312 | | |
313 | | struct |
314 | | { |
315 | | uint8_t sig[4]; |
316 | | uint8_t cff[4]; |
317 | | } ctx; |
318 | | |
319 | | uint8_t numSig[4]; |
320 | | int8_t refSbbCtxId[4]; |
321 | | |
322 | | int32_t cffBits1[RateEstimator::sm_maxNumGtxCtx + 3]; |
323 | | |
324 | | int8_t m_goRicePar[4]; |
325 | | int8_t m_goRiceZero[4]; |
326 | | const BinFracBits* m_sigFracBitsArray[4]; |
327 | | const CoeffFracBits* m_gtxFracBitsArray; |
328 | | |
329 | | int cffBitsCtxOffset; |
330 | | bool anyRemRegBinsLt4; |
331 | | int initRemRegBins; |
332 | | }; |
333 | | |
334 | | static constexpr size_t StateMemSkipCpySize = offsetof( StateMem, sbbBits1 ); |
335 | | } |
336 | | |
337 | | class DepQuant : public QuantRDOQ2, DQIntern::RateEstimator |
338 | | { |
339 | | public: |
340 | | DepQuant( const Quant* other, bool enc, bool useScalingLists ); |
341 | | virtual ~DepQuant(); |
342 | | |
343 | | virtual void quant ( TransformUnit& tu, const ComponentID compID, const CCoeffBuf& pSrc, TCoeff &uiAbsSum, const QpParam& cQP, const Ctx& ctx ); |
344 | | virtual void dequant( const TransformUnit& tu, CoeffBuf& dstCoeff, const ComponentID compID, const QpParam& cQP ); |
345 | | |
346 | | virtual void init ( int rdoq = 0, bool useRDOQTS = false, int dqThrVal = 8 ); |
347 | | |
348 | | private: |
349 | | void xQuantDQ ( TransformUnit& tu, const CCoeffBuf& srcCoeff, const ComponentID compID, const QpParam& cQP, const double lambda, const Ctx& ctx, TCoeff& absSum, bool enableScalingLists, int* quantCoeff ); |
350 | | void xDequantDQ ( const TransformUnit& tu, CoeffBuf& recCoeff, const ComponentID compID, const QpParam& cQP, bool enableScalingLists, int* quantCoeff ); |
351 | | void xDecideAndUpdate ( const TCoeff absCoeff, const DQIntern::ScanInfo& scanInfo, bool zeroOut, int quantCoeff); |
352 | | void xDecide ( const DQIntern::ScanInfo &scanInfo, const TCoeff absCoeff, const int lastOffset, DQIntern::Decisions &decisions, bool zeroOut, int quantCoeff ); |
353 | | |
354 | | DQIntern::CommonCtx m_commonCtx; |
355 | | std::shared_ptr<DQIntern::Rom> |
356 | | m_scansRom; |
357 | | DQIntern::Quantizer m_quant; |
358 | | |
359 | | DQIntern::Decisions m_trellis[MAX_TB_SIZEY * MAX_TB_SIZEY][2]; |
360 | | DQIntern::StateMem m_state_curr; |
361 | | DQIntern::StateMem m_state_skip; |
362 | | |
363 | | // has to be called as a first check, assumes no decision has been made yet!!! |
364 | | void( *m_checkAllRdCosts )( const DQIntern::ScanPosType spt, const DQIntern::PQData* pqData, DQIntern::Decisions& decisions, const DQIntern::StateMem& state ); |
365 | | // has to be called as a first check, assumes no decision has been made yet!!! |
366 | | void( *m_checkAllRdCostsOdd1 )( const DQIntern::ScanPosType spt, const int64_t pq_a_dist, const int64_t pq_b_dist, DQIntern::Decisions& decisions, const DQIntern::StateMem& state ); |
367 | | void( *m_updateStatesEOS )( const DQIntern::ScanInfo& scanInfo, const DQIntern::Decisions& decisions, const DQIntern::StateMem& skip, DQIntern::StateMem& curr, DQIntern::CommonCtx& commonCtx ); |
368 | | void( *m_updateStates )( const DQIntern::ScanInfo& scanInfo, const DQIntern::Decisions& decisions, DQIntern::StateMem& curr ); |
369 | | void( *m_findFirstPos )( int& firstTestPos, const TCoeff* tCoeff, const DQIntern::TUParameters& tuPars, int defaultTh, bool zeroOutForThres, int zeroOutWidth, int zeroOutHeight ); |
370 | | |
371 | | #if defined(TARGET_SIMD_X86) && ENABLE_SIMD_OPT_QUANT |
372 | | void initDepQuantX86(); |
373 | | template <X86_VEXT vext> |
374 | | void _initDepQuantX86(); |
375 | | #endif |
376 | | }; |
377 | | |
378 | | } // namespace vvenc |
379 | | |
380 | | //! \} |
381 | | |