1 /* -----------------------------------------------------------------------------
2 The copyright in this software is being made available under the 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 For any license concerning other Intellectual Property rights than the software,
8 especially patent licenses, a separate Agreement needs to be closed.
9 For more information please contact:
10 
11 Fraunhofer Heinrich Hertz Institute
12 Einsteinufer 37
13 10587 Berlin, Germany
14 www.hhi.fraunhofer.de/vvc
15 vvc@hhi.fraunhofer.de
16 
17 Copyright (c) 2018-2021, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
18 All rights reserved.
19 
20 Redistribution and use in source and binary forms, with or without
21 modification, are permitted provided that the following conditions are met:
22 
23  * Redistributions of source code must retain the above copyright notice,
24    this list of conditions and the following disclaimer.
25  * Redistributions in binary form must reproduce the above copyright notice,
26    this list of conditions and the following disclaimer in the documentation
27    and/or other materials provided with the distribution.
28  * Neither the name of Fraunhofer nor the names of its contributors may
29    be used to endorse or promote products derived from this software without
30    specific prior written permission.
31 
32 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
36 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
42 THE POSSIBILITY OF SUCH DAMAGE.
43 
44 
45 ------------------------------------------------------------------------------------------- */
46 
47 /** \file     DecCu.cpp
48     \brief    CU decoder class
49 */
50 
51 #include "DecCu.h"
52 
53 #include "CommonLib/InterPrediction.h"
54 #include "CommonLib/IntraPrediction.h"
55 #include "CommonLib/Picture.h"
56 #include "CommonLib/UnitTools.h"
57 #include "CommonLib/TimeProfiler.h"
58 
59 #include "CommonLib/dtrace_buffer.h"
60 
61 namespace vvdec
62 {
63 
64 //! \ingroup DecoderLib
65 //! \{
66 
TaskDeriveCtuMotionInfo(CodingStructure & cs,const UnitArea & ctuArea,MotionHist & hist)67 void DecCu::TaskDeriveCtuMotionInfo( CodingStructure &cs, const UnitArea &ctuArea, MotionHist& hist )
68 {
69   PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_CONTROL_PARSE_DERIVE_LL, cs, CH_L );
70 
71   const unsigned  ctuRsAddr      = getCtuAddr( Position( ctuArea.lumaPos().x, ctuArea.lumaPos().y ), *cs.pcv );
72   const unsigned  ctuXPosInCtus  = ctuRsAddr % cs.pcv->widthInCtus;
73   const unsigned  tileColIdx     = cs.pps->ctuToTileCol( ctuXPosInCtus );
74   const unsigned  tileXPosInCtus = cs.pps->getTileColumnBd( tileColIdx );
75 
76   if( ctuXPosInCtus == tileXPosInCtus )
77   {
78     hist.motionLut.   resize(0);
79     hist.motionLutIbc.resize(0);
80   }
81 
82   for( auto &currCU : cs.traverseCUs( ctuArea ) )
83   {
84     CHECK( !ctuArea.blocks[currCU.chType()].contains( currCU.blocks[currCU.chType()] ), "Should never happen!" );
85 
86 #if JVET_O1170_CHECK_BV_AT_DECODER
87     if( currCU.Y().valid() && currCU.sps->getIBCFlag() )
88     {
89       const int vSize = cs.sps->getMaxCUHeight() > 64 ? 64 : cs.sps->getMaxCUHeight();
90       if( ( currCU.Y().x % vSize ) == 0 && ( currCU.Y().y % vSize ) == 0 )
91       {
92         m_pcInterPred->resetVPDUforIBC( cs.pcv->chrFormat, cs.sps->getMaxCUHeight(), vSize, currCU.Y().x  + g_IBCBufferSize / cs.sps->getMaxCUHeight() / 2, currCU.Y().y );
93       }
94     }
95 #endif
96 
97     if( !CU::isIntra( currCU ) )
98     {
99       xDeriveCUMV( currCU, hist );
100     }
101   }
102 }
103 
TaskTrafoCtu(CodingStructure & cs,const UnitArea & ctuArea)104 void DecCu::TaskTrafoCtu( CodingStructure &cs, const UnitArea &ctuArea )
105 {
106   PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_ITRANS_REC, cs, CH_L );
107 
108   for( auto &currCU : cs.traverseCUs( ctuArea ) )
109   {
110     CHECK( !ctuArea.blocks[currCU.chType()].contains( currCU.blocks[currCU.chType()] ), "Should never happen!" );
111 
112     if( currCU.rootCbf() )
113     {
114       reconstructResi( currCU );
115     }
116   }
117 }
118 
TaskInterCtu(CodingStructure & cs,const UnitArea & ctuArea)119 void DecCu::TaskInterCtu( CodingStructure &cs, const UnitArea &ctuArea )
120 {
121   PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_CONTROL_PARSE_DERIVE_LL, cs, CH_L );
122 
123   for( auto &currCU: cs.traverseCUs( ctuArea ) )
124   {
125     CHECK( !ctuArea.blocks[currCU.chType()].contains( currCU.blocks[currCU.chType()] ), "Should never happen!" );
126 
127     if( !CU::isIntra( currCU ) && !CU::isIBC( currCU ) )
128     {
129       predAndReco( currCU, false );
130     }
131   }
132 }
133 
TaskCriticalIntraKernel(CodingStructure & cs,const UnitArea & ctuArea)134 void DecCu::TaskCriticalIntraKernel( CodingStructure &cs, const UnitArea &ctuArea )
135 {
136   PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_CONTROL_PARSE_DERIVE_LL, cs, CH_L );
137   for( auto &currCU : cs.traverseCUs( ctuArea ) )
138   {
139     CHECK( !ctuArea.blocks[currCU.chType()].contains( currCU.blocks[currCU.chType()] ), "Should never happen!" );
140 
141     if( CU::isIntra( currCU ) || currCU.ciipFlag() || CU::isIBC( currCU ) )
142     {
143       predAndReco( currCU, true );
144     }
145     else if( currCU.rootCbf() )
146     {
147       finishLMCSAndReco( currCU );
148     }
149 
150     if( cs.sps->getIBCFlag() )
151     {
152       cs.fillIBCbuffer( currCU, ctuArea.Y().y / cs.sps->getMaxCUHeight() );
153     }
154   }
155 }
156 
TaskDeriveDMVRMotionInfo(CodingStructure & cs,const UnitArea & ctuArea)157 void DecCu::TaskDeriveDMVRMotionInfo( CodingStructure& cs, const UnitArea& ctuArea )
158 {
159   PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_CONTROL_PARSE_DERIVE_LL, cs, CH_L );
160   MotionBuf   mb     = cs.getMotionBuf( ctuArea.Y() );
161   MotionInfo* orgPtr = mb.buf;
162 
163   for( CodingUnit &cu : cs.traverseCUs( ctuArea ) )
164   {
165     CHECKD( !ctuArea.blocks[cu.chType()].contains( cu.blocks[cu.chType()] ), "Should never happen!" );
166 
167     PredictionUnit &pu = cu;
168 
169     if( isLuma( pu.chType() ) && pu.dmvrCondition() )
170     {
171       const int dy = std::min<int>( pu.lumaSize().height, DMVR_SUBCU_HEIGHT );
172       const int dx = std::min<int>( pu.lumaSize().width,  DMVR_SUBCU_WIDTH );
173 
174       static constexpr unsigned scale = 4 * AMVP_DECIMATION_FACTOR;
175       static constexpr unsigned mask  = scale - 1;
176 
177       const Position puPos = pu.lumaPos();
178       const Mv mv0 = pu.mv[0][0];
179       const Mv mv1 = pu.mv[1][0];
180 
181       for( int y = puPos.y, num = 0; y < ( puPos.y + pu.lumaSize().height ); y = y + dy )
182       {
183         for( int x = puPos.x; x < ( puPos.x + pu.lumaSize().width ); x = x + dx, num++ )
184         {
185           const Mv subPuMv0 = mv0 + pu.mvdL0SubPu[num];
186           const Mv subPuMv1 = mv1 - pu.mvdL0SubPu[num];
187 
188           int y2 = ( ( y - 1 ) & ~mask ) + scale;
189 
190           for( ; y2 < y + dy; y2 += scale )
191           {
192             int x2 = ( ( x - 1 ) & ~mask ) + scale;
193 
194             for( ; x2 < x + dx; x2 += scale )
195             {
196               mb.buf = orgPtr + cs.inCtuPos( Position{ x2, y2 }, CH_L );
197 
198               MotionInfo& mi = *mb.buf;
199 
200               mi.mv[0] = subPuMv0;
201               mi.mv[1] = subPuMv1;
202             }
203           }
204         }
205       }
206     }
207   }
208 }
209 // ====================================================================================================================
210 // Constructor / destructor / create / destroy
211 // ====================================================================================================================
212 
DecCu()213 DecCu::DecCu()
214 {
215   create();
216 }
217 
~DecCu()218 DecCu::~DecCu()
219 {
220   destroy();
221 }
222 
init(IntraPrediction * pcIntra,InterPrediction * pcInter,Reshape * pcReshape,TrQuant * pcTrQuant)223 void DecCu::init( IntraPrediction* pcIntra, InterPrediction* pcInter, Reshape *pcReshape, TrQuant *pcTrQuant )
224 {
225   m_pcIntraPred  = pcIntra;
226   m_pcInterPred  = pcInter;
227   m_pcTrQuant    = pcTrQuant;
228   m_pcReshape    = pcReshape;
229 }
230 
create()231 void DecCu::create()
232 {
233 }
234 
destroy()235 void DecCu::destroy()
236 {
237 }
238 
239 // ====================================================================================================================
240 // Public member functions
241 // ====================================================================================================================
242 
predAndReco(CodingUnit & cu,bool doCiipIntra)243 void DecCu::predAndReco( CodingUnit& cu, bool doCiipIntra )
244 {
245   PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_ITRANS_REC, *cu.cs, CH_L );
246   CodingStructure &cs = *cu.cs;
247 
248   if( CU::isIntra( cu ) )
249   {
250     if( cu.colorTransform() )
251     {
252       xIntraRecACT( cu );
253       return;
254     }
255 
256     for( TransformUnit &tu : TUTraverser( &cu.firstTU, cu.lastTU->next ) )
257     {
258       for( const CompArea &area : tu.blocks )
259       {
260         if( !area.valid() )
261         {
262           continue;
263         }
264 
265         const ComponentID compID = area.compID();
266         const ChannelType chType = toChannelType( compID );
267 
268         PelBuf piPred;
269         {
270           PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_INTRAPRED, cs, compID );
271 
272           if( chType == CHANNEL_TYPE_LUMA )
273           {
274             Position pos = Position( tu.Y().x - cu.lumaPos().x, tu.Y().y - cu.lumaPos().y );
275             piPred = cs.getPredBuf( cu ).Y().subBuf( pos, tu.lumaSize() );
276           }
277           else
278           {
279             piPred = cs.getPredBuf( cu ).Cb().subBuf( Position( 0, 0 ), tu.chromaSize() );
280           }
281 
282           const PredictionUnit &pu      = cu;
283           const uint32_t uiChFinalMode  = PU::getFinalIntraMode( pu, chType );
284 
285           if( CU::isMIP( cu, chType ) )
286           {
287             m_pcIntraPred->initIntraPatternChType( tu, area );
288             m_pcIntraPred->initIntraMip( pu, area );
289             m_pcIntraPred->predIntraMip( compID, piPred, pu );
290           }
291           else if( compID != COMPONENT_Y && PU::isLMCMode( uiChFinalMode ) )
292           {
293             m_pcIntraPred->initIntraPatternChType( tu, area );
294             m_pcIntraPred->xGetLumaRecPixels( pu, area );
295             m_pcIntraPred->predIntraChromaLM( compID, piPred, pu, area, uiChFinalMode );
296           }
297           else
298           {
299             const bool predRegDiffFromTB = CU::isPredRegDiffFromTB( *tu.cu, compID );
300             const bool firstTBInPredReg  = CU::isFirstTBInPredReg( *tu.cu, compID, area );
301             CompArea areaPredReg( COMPONENT_Y, area );
302 
303             const bool bUseFilteredPredictions = isLuma( compID ) && cu.ispMode() == NOT_INTRA_SUBPARTITIONS && IntraPrediction::useFilteredIntraRefSamples( compID, pu, tu );
304 
305             if( tu.cu->ispMode() && isLuma( compID ) )
306             {
307               PelBuf piReco = cs.getRecoBuf( area );
308               if( predRegDiffFromTB )
309               {
310                 if( firstTBInPredReg )
311                 {
312                   CU::adjustPredArea( areaPredReg );
313                   m_pcIntraPred->initIntraPatternChTypeISP( *tu.cu, areaPredReg, piReco );
314                 }
315               }
316               else
317               {
318                 m_pcIntraPred->initIntraPatternChTypeISP( *tu.cu, area, piReco );
319               }
320             }
321             else
322             {
323               m_pcIntraPred->initIntraPatternChType( tu, area, bUseFilteredPredictions );
324             }
325 
326             if( predRegDiffFromTB )
327             {
328               if( firstTBInPredReg )
329               {
330                 Position pos( areaPredReg.x - cu.lumaPos().x, areaPredReg.y - cu.lumaPos().y );
331                 piPred      = cs.getPredBuf( cu ).Y().subBuf( pos, areaPredReg.size() );
332 
333                 m_pcIntraPred->predIntraAng( compID, piPred, pu, bUseFilteredPredictions );
334 
335                 piPred.width = area.width;
336               }
337             }
338             else
339               m_pcIntraPred->predIntraAng( compID, piPred, pu, bUseFilteredPredictions );
340           }
341         }
342 
343         //===== inverse transform =====
344         PelBuf piReco = cs.getRecoBuf( area );
345         PelBuf piResi = cs.getRecoBuf( area );
346 
347         const Slice &slice      = *cu.slice;
348         const bool   doChrScale = isChroma( compID )
349                                   && slice.getLmcsEnabledFlag()
350                                   && slice.getPicHeader()->getLmcsChromaResidualScaleFlag()
351                                   && tu.blocks[compID].area() > 4
352                                   && ( TU::getCbf( tu, compID ) || tu.jointCbCr )
353                                   ;
354 
355         if( doChrScale )
356         {
357           const Area area       = tu.Y().valid() ? tu.Y() : Area(recalcPosition(tu.chromaFormat, tu.chType(), CHANNEL_TYPE_LUMA, tu.blocks[tu.chType()].pos()), recalcSize(tu.chromaFormat, tu.chType(), CHANNEL_TYPE_LUMA, tu.blocks[tu.chType()].size()));
358           int chromaResScaleInv = m_pcReshape->calculateChromaAdjVpduNei( tu, area.pos() );
359           piReco.scaleSignal( chromaResScaleInv, slice.clpRng( compID ) );
360         }
361 
362         if( TU::getCbf( tu, compID ) || ( isChroma( compID ) && tu.jointCbCr ) )
363         {
364           piReco.reconstruct( piPred, piResi, slice.clpRng( compID ) );
365         }
366         else
367         {
368           piReco.copyFrom( piPred );
369         }
370       }
371     }
372   }
373   else
374   {
375     const UnitArea& cuArea = cu;
376 
377     PelUnitBuf predBuf = cu.rootCbf() ? cs.getPredBuf( cu ) : cs.getRecoBuf( cuArea );
378     PelUnitBuf recoBuf = cs.getRecoBuf( cuArea );
379 
380     // CBF in at least one channel, but no TU split
381     if( cu.rootCbf() )
382     {
383       for( const auto &blk : cu.blocks )
384       {
385         if( blk.valid() && !cu.planeCbf( blk.compID() ) )
386         {
387           predBuf.bufs[blk.compID()] = recoBuf.bufs[blk.compID()];
388         }
389       }
390     }
391 
392     if( cu.geoFlag() )
393     {
394       m_pcInterPred->motionCompensationGeo( cu, predBuf );
395     }
396     else
397     {
398       if( doCiipIntra )
399         m_pcIntraPred->geneIntrainterPred( cu );
400 
401       // inter prediction
402       CHECK( CU::isIBC( cu ) && cu.ciipFlag(),       "IBC and CIIP cannot be used together"   );
403       CHECK( CU::isIBC( cu ) && cu.affineFlag(),     "IBC and AFFINE cannot be used together" );
404       CHECK( CU::isIBC( cu ) && cu.geoFlag(),        "IBC and GEO cannot be used together"    );
405       CHECK(CU::isIBC(cu) && cu.mmvdFlag(),          "IBC and MMVD cannot be used together"     );
406 
407       if( !CU::isIBC( cu ) && !doCiipIntra )
408       {
409         m_pcInterPred->motionCompensation( cu, predBuf );
410       }
411       else if( CU::isIBC( cu ) )
412       {
413         const bool luma   = cu.Y ().valid();
414         const bool chroma = isChromaEnabled(cu.chromaFormat) && cu.Cb().valid();
415         m_pcInterPred->motionCompensation( cu, predBuf, luma, chroma );
416       }
417     }
418 
419     if( cu.ciipFlag() && doCiipIntra )
420     {
421       m_pcIntraPred->geneWeightedPred( COMPONENT_Y, predBuf.Y(), cu, m_pcIntraPred->getPredictorPtr2( COMPONENT_Y ) );
422 
423       if( isChromaEnabled( cu.chromaFormat ) && cu.chromaSize().width > 2 )
424       {
425         m_pcIntraPred->geneWeightedPred( COMPONENT_Cb, predBuf.Cb(), cu, m_pcIntraPred->getPredictorPtr2( COMPONENT_Cb ) );
426         m_pcIntraPred->geneWeightedPred( COMPONENT_Cr, predBuf.Cr(), cu, m_pcIntraPred->getPredictorPtr2( COMPONENT_Cr ) );
427       }
428     }
429 
430     DTRACE    ( g_trace_ctx, D_TMP, "pred " );
431     DTRACE_CRC( g_trace_ctx, D_TMP, *cu.cs, predBuf, &cu.Y() );
432 
433     if( cu.rootCbf() )
434     {
435       if( cu.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag( *cu.slice ) && !doCiipIntra )
436       {
437         predBuf.Y().rspSignal( m_pcReshape->getFwdLUT() );
438       }
439 
440       if( ( cu.ciipFlag() && doCiipIntra ) || CU::isIBC( cu ) )
441       {
442         finishLMCSAndReco( cu );
443       }
444     }
445     else
446     {
447       if( cu.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag( *cu.slice ) && !CU::isIBC( cu ) )
448       {
449         predBuf.Y().rspSignal( m_pcReshape->getFwdLUT() );
450       }
451     }
452 
453     DTRACE    ( g_trace_ctx, D_TMP, "reco " );
454     DTRACE_CRC( g_trace_ctx, D_TMP, *cu.cs, cu.cs->getRecoBuf( cuArea ), &cu.Y() );
455   }
456 }
457 
finishLMCSAndReco(CodingUnit & cu)458 void DecCu::finishLMCSAndReco( CodingUnit &cu )
459 {
460   PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_ITRANS_REC, *cu.cs, CH_L );
461   CodingStructure &cs = *cu.cs;
462 
463   const uint32_t uiNumVaildComp = getNumberValidComponents( cu.chromaFormat );
464   const bool     doCS           = cs.picHeader->getLmcsEnabledFlag() && cs.picHeader->getLmcsChromaResidualScaleFlag() && cu.slice->getLmcsEnabledFlag();
465   const PelUnitBuf predUnitBuf  = cs.getPredBuf( cu );
466 
467   for( auto& currTU : TUTraverser( &cu.firstTU, cu.lastTU->next ) )
468   {
469     int chromaResScaleInv = 0;
470 
471     for( uint32_t ch = 0; ch < uiNumVaildComp; ch++ )
472     {
473       const ComponentID compID = ComponentID( ch );
474 
475       if( doCS )
476       {
477         if( isLuma( compID ) )
478         {
479           chromaResScaleInv = m_pcReshape->calculateChromaAdjVpduNei( currTU, currTU.blocks[COMPONENT_Y] );
480         }
481         else if( ( TU::getCbf( currTU, compID ) || currTU.jointCbCr ) && currTU.blocks[compID].area() > 4 )
482         {
483           const CompArea &area = currTU.blocks[compID];
484           PelBuf resiBuf       = cs.getRecoBuf( area );
485           resiBuf.scaleSignal( chromaResScaleInv, cu.slice->clpRng( compID ) );
486         }
487       }
488 
489       if( currTU.blocks[compID].valid() )
490       {
491         CPelBuf predBuf = predUnitBuf.bufs[compID];
492         OFFSET( predBuf.buf, predBuf.stride, currTU.blocks[compID].x - cu.blocks[compID].x, currTU.blocks[compID].y - cu.blocks[compID].y );
493         //CPelBuf resiBuf = cs.getRecoBuf( currTU.blocks[compID] );
494          PelBuf recoBuf = cs.getRecoBuf( currTU.blocks[compID] );
495          predBuf.width  = recoBuf.width;
496          predBuf.height = recoBuf.height;
497 
498         if( TU::getCbf( currTU, compID ) || ( isChroma( compID ) && currTU.jointCbCr ) )
499         {
500           recoBuf.reconstruct( predBuf, recoBuf, cu.slice->clpRngs() );
501         }
502         else if( cu.planeCbf( compID ) )
503         {
504           recoBuf.copyFrom( predBuf );
505         }
506       }
507     }
508   }
509 }
510 
reconstructResi(CodingUnit & cu)511 void DecCu::reconstructResi( CodingUnit &cu )
512 {
513   CodingStructure &cs = *cu.cs;
514 
515   for( TransformUnit &tu : TUTraverser( &cu.firstTU, cu.lastTU->next ) )
516   {
517     for( const auto &area : tu.blocks )
518     {
519       if( !area.valid() )
520       {
521         continue;
522       }
523 
524       const ComponentID compID = area.compID();
525 
526       //===== inverse transform =====
527       PelBuf piResi = cs.getRecoBuf( area );
528 
529       if( tu.jointCbCr && isChroma( compID ) )
530       {
531         if( compID == COMPONENT_Cb )
532         {
533           PelBuf resiCr = cs.getRecoBuf( tu.blocks[ COMPONENT_Cr ] );
534           if( tu.jointCbCr >> 1 )
535           {
536             QpParam qpCb( tu, compID );
537             m_pcTrQuant->invTransformNxN( tu, COMPONENT_Cb, piResi, qpCb );
538           }
539           else
540           {
541             QpParam qpCr( tu, COMPONENT_Cr );
542             m_pcTrQuant->invTransformNxN( tu, COMPONENT_Cr, resiCr, qpCr );
543           }
544           m_pcTrQuant->invTransformICT( tu, piResi, resiCr );
545         }
546       }
547       else if( TU::getCbf( tu, compID ) )
548       {
549         QpParam cQP( tu, compID );
550         m_pcTrQuant->invTransformNxN( tu, compID, piResi, cQP );
551       }
552     }
553   }
554 }
555 
556 // ====================================================================================================================
557 // Protected member functions
558 // ====================================================================================================================
559 
560 /** Function for deriving reconstructed luma/chroma samples of a PCM mode CU.
561 * \param pcCU pointer to current CU
562 * \param uiPartIdx part index
563 * \param piPCM pointer to PCM code arrays
564 * \param piReco pointer to reconstructed sample arrays
565 * \param uiStride stride of reconstructed sample arrays
566 * \param uiWidth CU width
567 * \param uiHeight CU height
568 * \param compID colour component ID
569 * \returns void
570 */
571 
xIntraRecACT(CodingUnit & cu)572 void DecCu::xIntraRecACT( CodingUnit &cu )
573 {
574   CodingStructure &cs  = *cu.cs;
575   const Slice &slice   = *cu.slice;
576 
577   for( TransformUnit &tu : TUTraverser( &cu.firstTU, cu.lastTU->next ) )
578   {
579     cs.getRecoBuf( tu ).colorSpaceConvert( cs.getRecoBuf( tu ), slice.clpRng( COMPONENT_Y ) );
580 
581     for( const CompArea &area : tu.blocks )
582     {
583       const ComponentID compID = area.compID();
584 
585       if( compID == COMPONENT_Y )
586       {
587         continue;
588       }
589       //===== inverse transform =====
590       PelBuf piReco = cs.getRecoBuf( area );
591 
592       const bool   doChrScale = isChroma( compID )
593                                 && slice.getLmcsEnabledFlag()
594                                 && slice.getPicHeader()->getLmcsChromaResidualScaleFlag()
595                                 && tu.blocks[compID].area() > 4
596                                 && ( TU::getCbf( tu, compID ) || tu.jointCbCr )
597                                 ;
598 
599       if( doChrScale )
600       {
601         const Area area       = tu.Y().valid() ? tu.Y() : Area(recalcPosition(tu.chromaFormat, tu.chType(), CHANNEL_TYPE_LUMA, tu.blocks[tu.chType()].pos()), recalcSize(tu.chromaFormat, tu.chType(), CHANNEL_TYPE_LUMA, tu.blocks[tu.chType()].size()));
602         int chromaResScaleInv = m_pcReshape->calculateChromaAdjVpduNei( tu, area.pos() );
603         piReco.scaleSignal( chromaResScaleInv, slice.clpRng( compID ) );
604       }
605     }
606 
607     for( const CompArea &area : tu.blocks )
608     {
609       if( !area.valid() )
610       {
611         continue;
612       }
613 
614       const ComponentID compID = area.compID();
615       const ChannelType chType = toChannelType( compID );
616 
617       PelBuf piPred;
618       if( chType == CHANNEL_TYPE_LUMA )
619       {
620         Position pos = Position( tu.Y().x - cu.lumaPos().x, tu.Y().y - cu.lumaPos().y );
621         piPred = cs.getPredBuf( cu ).Y().subBuf( pos, tu.lumaSize() );
622       }
623       else
624       {
625         piPred = cs.getPredBuf( cu ).Cb().subBuf( Position( 0, 0 ), tu.chromaSize() );
626       }
627 
628       const PredictionUnit &pu      = cu;
629       const uint32_t uiChFinalMode  = PU::getFinalIntraMode( pu, chType );
630 
631       bool predRegDiffFromTB = CU::isPredRegDiffFromTB( *tu.cu, compID );
632       bool firstTBInPredReg  = CU::isFirstTBInPredReg( *tu.cu, compID, area );
633       CompArea areaPredReg   ( COMPONENT_Y, area );
634 
635       if( CU::isMIP( cu, chType ) )
636       {
637         m_pcIntraPred->initIntraPatternChType( tu, area );
638         m_pcIntraPred->initIntraMip( pu, area );
639         m_pcIntraPred->predIntraMip( compID, piPred, pu );
640       }
641       else
642       {
643         const bool bUseFilteredPredictions = isLuma( chType ) && cu.ispMode() == NOT_INTRA_SUBPARTITIONS && IntraPrediction::useFilteredIntraRefSamples( compID, pu, tu );
644 
645         if( tu.cu->ispMode() && isLuma( compID ) )
646         {
647           PelBuf piReco = cs.getRecoBuf( area );
648           if( predRegDiffFromTB )
649           {
650             if( firstTBInPredReg )
651             {
652               CU::adjustPredArea( areaPredReg );
653               m_pcIntraPred->initIntraPatternChTypeISP( *tu.cu, areaPredReg, piReco );
654             }
655           }
656           else
657           {
658             m_pcIntraPred->initIntraPatternChTypeISP( *tu.cu, area, piReco );
659           }
660         }
661         else
662         {
663           m_pcIntraPred->initIntraPatternChType( tu, area, bUseFilteredPredictions );
664         }
665 
666         if( compID != COMPONENT_Y && PU::isLMCMode( uiChFinalMode ) )
667         {
668           m_pcIntraPred->xGetLumaRecPixels( pu, area );
669           m_pcIntraPred->predIntraChromaLM( compID, piPred, pu, area, uiChFinalMode );
670         }
671         else
672         {
673           if( predRegDiffFromTB )
674           {
675             if( firstTBInPredReg )
676             {
677               Position pos( areaPredReg.x - cu.lumaPos().x, areaPredReg.y - cu.lumaPos().y );
678               piPred      = cs.getPredBuf( cu ).Y().subBuf( pos, areaPredReg.size() );
679 
680               m_pcIntraPred->predIntraAng( compID, piPred, pu, bUseFilteredPredictions );
681             }
682           }
683           else
684             m_pcIntraPred->predIntraAng( compID, piPred, pu, bUseFilteredPredictions );
685         }
686       }
687 
688       PelBuf piReco = cs.getRecoBuf( area );
689       PelBuf piResi = cs.getRecoBuf( area );
690 
691       piReco.reconstruct( piPred, piResi, slice.clpRng( compID ) );
692     }
693   }
694 }
695 
xDeriveCUMV(CodingUnit & cu,MotionHist & hist)696 void DecCu::xDeriveCUMV( CodingUnit &cu, MotionHist& hist )
697 {
698   PredictionUnit& pu = cu;
699   MergeCtx mrgCtx;
700 
701   if( pu.mergeFlag() )
702   {
703     if( pu.mmvdFlag() )
704     {
705       int fPosBaseIdx = pu.mmvdIdx / MMVD_MAX_REFINE_NUM;
706 
707       PU::getInterMergeCandidates     ( pu, mrgCtx, hist, fPosBaseIdx + 1 );
708       PU::getInterMMVDMergeCandidates ( pu, mrgCtx,       pu.mmvdIdx );
709       mrgCtx.setMmvdMergeCandiInfo    ( pu, pu.mmvdIdx );
710 
711       PU::spanMotionInfo              ( pu, mrgCtx );
712     }
713     else if( pu.geoFlag() )
714     {
715       PU::getGeoMergeCandidates( pu, m_geoMrgCtx, hist );
716 
717       const uint8_t splitDir = pu.geoSplitDir;
718       const uint8_t candIdx0 = pu.geoMergeIdx0();
719       const uint8_t candIdx1 = pu.geoMergeIdx1();
720 
721       PU::spanGeoMotionInfo( pu, m_geoMrgCtx, splitDir, candIdx0, candIdx1 );
722     }
723     else if( pu.affineFlag() )
724     {
725       AffineMergeCtx affineMergeCtx;
726 
727       if( pu.sps->getSBTMVPEnabledFlag() )
728       {
729         mrgCtx.subPuMvpMiBuf  = cu.getMotionBuf();
730         affineMergeCtx.mrgCtx = &mrgCtx;
731       }
732 
733       int mergeIdx = pu.mergeIdx();
734       PU::getAffineMergeCand( pu, affineMergeCtx, mergeIdx );
735 
736       pu.setInterDir        ( affineMergeCtx.interDirNeighbours[mergeIdx] );
737       pu.setAffineType      ( affineMergeCtx.affineType        [mergeIdx] );
738       pu.setBcwIdx          ( affineMergeCtx.BcwIdx            [mergeIdx] );
739       pu.setMergeType       ( affineMergeCtx.mergeType         [mergeIdx] );
740 
741       if( pu.mergeType() == MRG_TYPE_SUBPU_ATMVP )
742       {
743         pu.refIdx[0] = affineMergeCtx.mvFieldNeighbours[( pu.mergeIdx() << 1 ) + 0][0].refIdx;
744         pu.refIdx[1] = affineMergeCtx.mvFieldNeighbours[( pu.mergeIdx() << 1 ) + 1][0].refIdx;
745       }
746       else
747       {
748         for( int i = 0; i < 2; ++i )
749         {
750           if( pu.slice->getNumRefIdx( RefPicList( i ) ) > 0 )
751           {
752             MvField* mvField = affineMergeCtx.mvFieldNeighbours[( pu.mergeIdx() << 1 ) + i];
753 
754             PU::setAllAffineMvField( pu, mvField, RefPicList( i ) );
755           }
756         }
757       }
758 
759       PU::spanMotionInfo( pu, mrgCtx );
760     }
761     else
762     {
763       if( CU::isIBC( pu ) )
764         PU::getIBCMergeCandidates  ( pu, mrgCtx, hist, pu.mergeIdx() );
765       else
766         PU::getInterMergeCandidates( pu, mrgCtx, hist, pu.mergeIdx() );
767 
768       mrgCtx.setMergeInfo         ( pu, pu.mergeIdx() );
769 
770       PU::spanMotionInfo          ( pu, mrgCtx );
771     }
772   }
773   else
774   {
775     if( pu.imv() && !pu.affineFlag() )
776     {
777       PU::applyImv      ( pu, hist );
778       PU::spanMotionInfo( pu );
779     }
780     else
781     {
782       if( pu.affineFlag() )
783       {
784         for ( uint32_t uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ )
785         {
786           RefPicList eRefList = RefPicList( uiRefListIdx );
787           if( pu.slice->getNumRefIdx( eRefList ) > 0 && ( pu.interDir() & ( 1 << uiRefListIdx ) ) )
788           {
789             AffineAMVPInfo affineAMVPInfo;
790             PU::fillAffineMvpCand( pu, eRefList, pu.refIdx[eRefList], affineAMVPInfo );
791 
792             const unsigned mvp_idx = pu.mvpIdx[eRefList];
793 
794             //    Mv mv[3];
795             CHECK( pu.refIdx[eRefList] < 0, "Unexpected negative refIdx." );
796             const int imvShift = pu.imv() == 2 ? MV_FRACTIONAL_BITS_DIFF : 0;
797             Mv mv0 = pu.mv[eRefList][0];
798             Mv mv1 = pu.mv[eRefList][1];
799 
800             mv0 <<= imvShift;
801             mv1 <<= imvShift;
802 
803             Mv mvLT = affineAMVPInfo.mvCandLT[mvp_idx] + mv0;
804             Mv mvRT = affineAMVPInfo.mvCandRT[mvp_idx] + mv1;
805             mvRT   += mv0;
806             if( pu.imv() != 1 )
807             {
808               mvLT.changePrecision( MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL );
809               mvRT.changePrecision( MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL );
810             }
811 
812             Mv mvLB;
813             if( pu.affineType() == AFFINEMODEL_6PARAM )
814             {
815               Mv mv2 = pu.mv[eRefList][2];
816               mv2 <<= imvShift;
817               mvLB = affineAMVPInfo.mvCandLB[mvp_idx] + mv2;
818               mvLB += mv0;
819               if ( pu.imv() != 1 )
820               {
821                 mvLB.changePrecision( MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL );
822               }
823             }
824             PU::setAllAffineMv( pu, mvLT, mvRT, mvLB, eRefList, true );
825           }
826         }
827       }
828       else if( CU::isIBC( pu ) && pu.interDir() == 1 )
829       {
830         AMVPInfo amvpInfo;
831         PU::fillIBCMvpCand( pu, amvpInfo, hist );
832         Mv mvd = pu.mv[REF_PIC_LIST_0][0];
833         mvd <<= 4;
834         if( pu.slice->getPicHeader()->getMaxNumIBCMergeCand() == 1 )
835         {
836           CHECK( pu.mvpIdx[REF_PIC_LIST_0], "mvpIdx for IBC mode should be 0" );
837         }
838         pu.mv[REF_PIC_LIST_0][0] = amvpInfo.mvCand[pu.mvpIdx[REF_PIC_LIST_0]] + mvd;
839         pu.mv[REF_PIC_LIST_0][0] . mvCliptoStorageBitDepth();
840       }
841       else
842       {
843         for( uint32_t uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ )
844         {
845           RefPicList eRefList = RefPicList( uiRefListIdx );
846           if( ( pu.slice->getNumRefIdx( eRefList ) > 0 || ( eRefList == REF_PIC_LIST_0 && CU::isIBC( pu ) ) ) && ( pu.interDir() & ( 1 << uiRefListIdx ) ) )
847           {
848             AMVPInfo amvpInfo;
849             PU::fillMvpCand( pu, eRefList, pu.refIdx[eRefList], amvpInfo, hist );
850 
851             Mv mvd              = pu.mv[eRefList][0];
852             mvd                 . changePrecisionAmvr( pu.imv(), MV_PRECISION_INTERNAL);
853             pu.mv [eRefList][0] = amvpInfo.mvCand[pu.mvpIdx[eRefList]] + mvd;
854             pu.mv [eRefList][0] . mvCliptoStorageBitDepth();
855           }
856         }
857       }
858       PU::spanMotionInfo( pu, mrgCtx );
859     }
860   }
861 
862   bool isIbcSmallBlk = CU::isIBC( cu ) && ( cu.lwidth() * cu.lheight() <= 16 );
863   if( !pu.affineFlag() && !pu.geoFlag() && !isIbcSmallBlk )
864   {
865     const unsigned log2ParallelMergeLevel = (pu.sps->getLog2ParallelMergeLevelMinus2() + 2);
866     const unsigned xBr = pu.Y().width  + pu.Y().x;
867     const unsigned yBr = pu.Y().height + pu.Y().y;
868     bool enableHmvp      = ((xBr >> log2ParallelMergeLevel) > (pu.Y().x >> log2ParallelMergeLevel)) && ((yBr >> log2ParallelMergeLevel) > (pu.Y().y >> log2ParallelMergeLevel));
869     bool enableInsertion = CU::isIBC( cu ) || enableHmvp;
870 
871     if( enableInsertion )
872     {
873       HPMVInfo mi( pu.getMotionInfo(), pu.interDir() == 3 ? pu.BcwIdx() : BCW_DEFAULT, pu.imv() == IMV_HPEL );
874       MotionHist::addMiToLut( CU::isIBC( cu ) ? hist.motionLutIbc : hist.motionLut, mi );
875     }
876   }
877 }
878 
879 }
880