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