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