/work/vvenc/source/Lib/CommonLib/IntraPrediction.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) 2019-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVenC Authors. |
10 | | All rights reserved. |
11 | | |
12 | | Redistribution and use in source and binary forms, with or without modification, |
13 | | are permitted (subject to the limitations in the disclaimer below) provided that |
14 | | the following conditions are met: |
15 | | |
16 | | * Redistributions of source code must retain the above copyright notice, |
17 | | this list of conditions and the following disclaimer. |
18 | | |
19 | | * Redistributions in binary form must reproduce the above copyright |
20 | | notice, this list of conditions and the following disclaimer in the |
21 | | documentation and/or other materials provided with the distribution. |
22 | | |
23 | | * Neither the name of the copyright holder nor the names of its |
24 | | contributors may be used to endorse or promote products derived from this |
25 | | software without specific prior written permission. |
26 | | |
27 | | NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY |
28 | | THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
29 | | CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
30 | | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
31 | | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
32 | | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
33 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
34 | | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
35 | | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER |
36 | | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
37 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
38 | | POSSIBILITY OF SUCH DAMAGE. |
39 | | |
40 | | |
41 | | ------------------------------------------------------------------------------------------- */ |
42 | | |
43 | | |
44 | | /** \file Prediction.cpp |
45 | | \brief prediction class |
46 | | */ |
47 | | |
48 | | #include "IntraPrediction.h" |
49 | | #include "Unit.h" |
50 | | #include "UnitTools.h" |
51 | | #include "Rom.h" |
52 | | #include "InterpolationFilter.h" |
53 | | #include "dtrace_next.h" |
54 | | |
55 | | #include <memory.h> |
56 | | |
57 | | //! \ingroup CommonLib |
58 | | //! \{ |
59 | | |
60 | | namespace vvenc { |
61 | | |
62 | | // ==================================================================================================================== |
63 | | // Tables |
64 | | // ==================================================================================================================== |
65 | | |
66 | | const uint8_t IntraPrediction::m_aucIntraFilter[MAX_INTRA_FILTER_DEPTHS] = |
67 | | { |
68 | | 24, // 1xn |
69 | | 24, // 2xn |
70 | | 24, // 4xn |
71 | | 14, // 8xn |
72 | | 2, // 16xn |
73 | | 0, // 32xn |
74 | | 0, // 64xn |
75 | | 0 // 128xn |
76 | | }; |
77 | | |
78 | | //NOTE: Bit-Limit - 24-bit source |
79 | | void xPredIntraPlanar_Core( PelBuf& pDst, const CPelBuf& pSrc ) |
80 | 152k | { |
81 | 152k | const uint32_t width = pDst.width; |
82 | 152k | const uint32_t height = pDst.height; |
83 | 152k | const uint32_t log2W = Log2(width); |
84 | 152k | const uint32_t log2H = Log2(height); |
85 | | |
86 | 152k | int leftColumn[MAX_TB_SIZEY + 1], topRow[MAX_TB_SIZEY + 1], bottomRow[MAX_TB_SIZEY], rightColumn[MAX_TB_SIZEY]; |
87 | 152k | const uint32_t offset = 1 << (log2W + log2H); |
88 | | |
89 | | // Get left and above reference column and row |
90 | 3.17M | for( int k = 0; k < width + 1; k++ ) |
91 | 3.01M | { |
92 | 3.01M | topRow[k] = pSrc.at( k + 1, 0 ); |
93 | 3.01M | } |
94 | | |
95 | 3.15M | for( int k = 0; k < height + 1; k++ ) |
96 | 3.00M | { |
97 | 3.00M | leftColumn[k] = pSrc.at( k + 1, 1 ); |
98 | 3.00M | } |
99 | | |
100 | | // Prepare intermediate variables used in interpolation |
101 | 152k | int bottomLeft = leftColumn[height]; |
102 | 152k | int topRight = topRow[width]; |
103 | | |
104 | | // with some optimizations gcc-8 gives spurious "-Wmaybe-uninitialized" warnings here (says leftColumn or topRow would be uninitialized here) |
105 | 152k | GCC_WARNING_DISABLE_maybe_uninitialized |
106 | 3.01M | for( int k = 0; k < width; k++ ) |
107 | 2.86M | { |
108 | 2.86M | bottomRow[k] = bottomLeft - topRow[k]; |
109 | 2.86M | topRow[k] = topRow[k] << log2H; |
110 | 2.86M | } |
111 | | |
112 | 3.00M | for( int k = 0; k < height; k++ ) |
113 | 2.85M | { |
114 | 2.85M | rightColumn[k] = topRight - leftColumn[k]; |
115 | 2.85M | leftColumn[k] = leftColumn[k] << log2W; |
116 | 2.85M | } |
117 | 152k | GCC_WARNING_RESET |
118 | | |
119 | 152k | const uint32_t finalShift = 1 + log2W + log2H; |
120 | 152k | const uint32_t stride = pDst.stride; |
121 | 152k | Pel* pred = pDst.buf; |
122 | 3.00M | for( int y = 0; y < height; y++, pred += stride ) |
123 | 2.85M | { |
124 | 2.85M | int horPred = leftColumn[y]; |
125 | | |
126 | 69.9M | for( int x = 0; x < width; x++ ) |
127 | 67.0M | { |
128 | 67.0M | horPred += rightColumn[y]; |
129 | 67.0M | topRow[x] += bottomRow[x]; |
130 | | |
131 | 67.0M | int vertPred = topRow[x]; |
132 | 67.0M | pred[x] = ( ( horPred << log2H ) + ( vertPred << log2W ) + offset ) >> finalShift; |
133 | 67.0M | } |
134 | 2.85M | } |
135 | 152k | } |
136 | | |
137 | | void IntraPredSampleFilter_Core(PelBuf& dstBuf, const CPelBuf& pSrc) |
138 | 457k | { |
139 | 457k | const int iWidth = dstBuf.width; |
140 | 457k | const int iHeight = dstBuf.height; |
141 | | |
142 | 457k | const int scale = ((Log2(iWidth*iHeight) - 2) >> 2); |
143 | 457k | CHECK(scale < 0 || scale > 31, "PDPC: scale < 0 || scale > 31"); |
144 | | |
145 | 8.41M | for (int y = 0; y < iHeight; y++) |
146 | 7.96M | { |
147 | 7.96M | const int wT = 32 >> std::min(31, ((y << 1) >> scale)); |
148 | 7.96M | const Pel left = pSrc.at(y + 1, 1); |
149 | 181M | for (int x = 0; x < iWidth; x++) |
150 | 173M | { |
151 | 173M | const int wL = 32 >> std::min(31, ((x << 1) >> scale)); |
152 | 173M | const Pel top = pSrc.at(x + 1, 0); |
153 | 173M | const Pel val = dstBuf.at(x, y); |
154 | 173M | dstBuf.at(x, y) = val + ((wL * (left - val) + wT * (top - val) + 32) >> 6); |
155 | 173M | } |
156 | 7.96M | } |
157 | 457k | } |
158 | | |
159 | | void IntraHorVerPDPC_Core(Pel* pDsty,const int dstStride,Pel* refSide,const int width,const int height,int scale,const Pel* refMain, const ClpRng& clpRng) |
160 | 502k | { |
161 | 502k | const Pel topLeft = refMain[0]; |
162 | | |
163 | 8.13M | for( int y = 0; y < height; y++ ) |
164 | 7.63M | { |
165 | 7.63M | memcpy(pDsty,&refMain[1],width*sizeof(Pel)); |
166 | 7.63M | const Pel left = refSide[1 + y]; |
167 | 60.1M | for (int x = 0; x < std::min(3 << scale, width); x++) |
168 | 52.5M | { |
169 | 52.5M | const int wL = 32 >> (2 * x >> scale); |
170 | 52.5M | const Pel val = pDsty[x]; |
171 | 52.5M | pDsty[x] = ClipPel(val + ((wL * (left - topLeft) + 32) >> 6), clpRng); |
172 | 52.5M | } |
173 | 7.63M | pDsty += dstStride; |
174 | 7.63M | } |
175 | 502k | } |
176 | | void IntraAnglePDPC_Core(Pel* pDsty,const int dstStride,Pel* refSide,const int width,const int height,int scale,int invAngle) |
177 | 550k | { |
178 | 12.6M | for (int y = 0; y<height; y++, pDsty += dstStride) |
179 | 12.1M | { |
180 | 12.1M | int invAngleSum = 256; |
181 | 130M | for (int x = 0; x < std::min(3 << scale, width); x++) |
182 | 118M | { |
183 | 118M | invAngleSum += invAngle; |
184 | 118M | int wL = 32 >> (2 * x >> scale); |
185 | 118M | Pel left = refSide[y + (invAngleSum >> 9) + 1]; |
186 | 118M | pDsty[x] = pDsty[x] + ((wL * (left - pDsty[x]) + 32) >> 6); |
187 | 118M | } |
188 | 12.1M | } |
189 | 550k | } |
190 | | |
191 | | void IntraPredAngleLuma_Core(Pel* pDstBuf,const ptrdiff_t dstStride,Pel* refMain,int width,int height,int deltaPos,int intraPredAngle,const TFilterCoeff *ff_unused,const bool useCubicFilter,const ClpRng& clpRng) |
192 | 710k | { |
193 | 21.3M | for (int y = 0; y<height; y++ ) |
194 | 20.6M | { |
195 | 20.6M | const int deltaInt = deltaPos >> 5; |
196 | 20.6M | const int deltaFract = deltaPos & ( 32 - 1 ); |
197 | | |
198 | 20.6M | const TFilterCoeff intraSmoothingFilter[4] = {TFilterCoeff(16 - (deltaFract >> 1)), TFilterCoeff(32 - (deltaFract >> 1)), TFilterCoeff(16 + (deltaFract >> 1)), TFilterCoeff(deltaFract >> 1)}; |
199 | 20.6M | const TFilterCoeff *f = useCubicFilter ? InterpolationFilter::getChromaFilterTable(deltaFract) : intraSmoothingFilter; |
200 | | |
201 | 20.6M | Pel p[4]; |
202 | | |
203 | 20.6M | int refMainIndex = deltaInt + 1; |
204 | | |
205 | | // const TFilterCoeff *f = &ff[deltaFract << 2]; |
206 | | |
207 | 861M | for( int x = 0; x < width; x++, refMainIndex++ ) |
208 | 840M | { |
209 | 840M | p[0] = refMain[refMainIndex - 1]; |
210 | 840M | p[1] = refMain[refMainIndex ]; |
211 | 840M | p[2] = refMain[refMainIndex + 1]; |
212 | 840M | p[3] = refMain[refMainIndex + 2]; |
213 | | |
214 | 840M | pDstBuf[y*dstStride + x] = static_cast<Pel>((static_cast<int>(f[0] * p[0]) + static_cast<int>(f[1] * p[1]) + static_cast<int>(f[2] * p[2]) + static_cast<int>(f[3] * p[3]) + 32) >> 6); |
215 | | |
216 | 840M | if( useCubicFilter ) // only cubic filter has negative coefficients and requires clipping |
217 | 111M | { |
218 | 111M | pDstBuf[y*dstStride + x] = ClipPel( pDstBuf[y*dstStride + x], clpRng ); |
219 | 111M | } |
220 | 840M | } |
221 | 20.6M | deltaPos += intraPredAngle; |
222 | 20.6M | } |
223 | 710k | } |
224 | | |
225 | | void IntraPredAngleChroma_Core(Pel* pDstBuf,const ptrdiff_t dstStride,int16_t* pBorder,int width,int height,int deltaPos,int intraPredAngle) |
226 | 72.2k | { |
227 | 616k | for (int y = 0; y<height; y++) |
228 | 543k | { |
229 | 543k | const int deltaInt = deltaPos >> 5; |
230 | 543k | const int deltaFract = deltaPos & (32 - 1); |
231 | | |
232 | | // Do linear filtering |
233 | 543k | const Pel* pRM = pBorder + deltaInt + 1; |
234 | 543k | int lastRefMainPel = *pRM++; |
235 | | |
236 | 14.5M | for( int x = 0; x < width; pRM++, x++ ) |
237 | 13.9M | { |
238 | 13.9M | int thisRefMainPel = *pRM; |
239 | 13.9M | pDstBuf[x + 0] = ( Pel ) ( ( ( 32 - deltaFract )*lastRefMainPel + deltaFract*thisRefMainPel + 16 ) >> 5 ); |
240 | 13.9M | lastRefMainPel = thisRefMainPel; |
241 | 13.9M | } |
242 | 543k | deltaPos += intraPredAngle; |
243 | 543k | pDstBuf += dstStride; |
244 | 543k | } |
245 | 72.2k | } |
246 | | |
247 | | // ==================================================================================================================== |
248 | | // Constructor / destructor / initialize |
249 | | // ==================================================================================================================== |
250 | | |
251 | | static void IntraFilterRefSamples_Core( const Pel* src, Pel* dst, const int length ) |
252 | 152k | { |
253 | 8.86M | for( int i = 1; i < length; i++ ) |
254 | 8.71M | { |
255 | 8.71M | dst[i] = ( src[i - 1] + 2 * src[i] + src[i + 1] + 2 ) >> 2; |
256 | 8.71M | } |
257 | 152k | } |
258 | | |
259 | | static void LMLumaDownsample420_Core( const Pel* src, const ptrdiff_t srcStride, Pel* dst, const ptrdiff_t dstStride, const int width, const int height, const bool leftAvailable ) |
260 | 129k | { |
261 | 1.44M | for( int y = 0; y < height; y++, src += 2 * srcStride, dst += dstStride ) |
262 | 1.31M | { |
263 | 22.1M | for( int i = 0; i < width; i++ ) |
264 | 20.8M | { |
265 | 20.8M | const int left = ( i == 0 && !leftAvailable ) ? 0 : 1; |
266 | | |
267 | 20.8M | int s = 4; |
268 | 20.8M | s += src[2 * i] * 2; |
269 | 20.8M | s += src[2 * i + 1]; |
270 | 20.8M | s += src[2 * i - left]; |
271 | 20.8M | s += src[2 * i + srcStride] * 2; |
272 | 20.8M | s += src[2 * i + 1 + srcStride]; |
273 | 20.8M | s += src[2 * i + srcStride - left]; |
274 | 20.8M | dst[i] = s >> 3; |
275 | 20.8M | } |
276 | 1.31M | } |
277 | 129k | } |
278 | | |
279 | | IntraPrediction::IntraPrediction( bool enableOpt ) |
280 | 5.97k | : m_pMdlmTemp( nullptr ) |
281 | 5.97k | , m_currChromaFormat( NUM_CHROMA_FORMAT ) |
282 | 5.97k | { |
283 | 5.97k | IntraPredAngleLuma = IntraPredAngleLuma_Core; |
284 | 5.97k | IntraPredAngleChroma = IntraPredAngleChroma_Core; |
285 | 5.97k | IntraAnglePDPC = IntraAnglePDPC_Core; |
286 | 5.97k | IntraHorVerPDPC = IntraHorVerPDPC_Core; |
287 | 5.97k | IntraPredSampleFilter = IntraPredSampleFilter_Core; |
288 | 5.97k | xPredIntraPlanar = xPredIntraPlanar_Core; |
289 | 5.97k | LMLumaDownsample420 = LMLumaDownsample420_Core; |
290 | 5.97k | IntraFilterRefSamples = IntraFilterRefSamples_Core; |
291 | | |
292 | 5.97k | #if ENABLE_SIMD_OPT_INTRAPRED |
293 | 5.97k | if( enableOpt ) |
294 | 5.97k | { |
295 | | #if defined( TARGET_SIMD_X86 ) |
296 | | initIntraPredictionX86(); |
297 | | #endif |
298 | | #if defined( TARGET_SIMD_ARM ) |
299 | | initIntraPredictionARM(); |
300 | | #endif |
301 | 5.97k | } |
302 | 5.97k | #endif // ENABLE_SIMD_OPT_INTRAPRED |
303 | 5.97k | } |
304 | | |
305 | | IntraPrediction::~IntraPrediction() |
306 | 5.97k | { |
307 | 5.97k | destroy(); |
308 | 5.97k | } |
309 | | |
310 | | void IntraPrediction::destroy() |
311 | 5.97k | { |
312 | 5.97k | delete[] m_pMdlmTemp; |
313 | 5.97k | m_pMdlmTemp = nullptr; |
314 | 5.97k | } |
315 | | |
316 | | void IntraPrediction::init(ChromaFormat chromaFormatIDC, const unsigned bitDepthY) |
317 | 5.97k | { |
318 | 5.97k | m_currChromaFormat = chromaFormatIDC; |
319 | | |
320 | 5.97k | if (m_pMdlmTemp == nullptr) |
321 | 5.97k | { |
322 | 5.97k | m_pMdlmTemp = new Pel[(2 * MAX_TB_SIZEY + 1)*(2 * MAX_TB_SIZEY + 1)];//MDLM will use top-above and left-below samples. |
323 | 5.97k | } |
324 | 5.97k | } |
325 | | |
326 | | // ==================================================================================================================== |
327 | | // Public member functions |
328 | | // ==================================================================================================================== |
329 | | |
330 | | // Function for calculating DC value of the reference samples used in Intra prediction |
331 | | //NOTE: Bit-Limit - 25-bit source |
332 | | Pel IntraPrediction::xGetPredValDc( const CPelBuf& pSrc, const Size& dstSize ) |
333 | 359k | { |
334 | 359k | CHECK( dstSize.width == 0 || dstSize.height == 0, "Empty area provided" ); |
335 | | |
336 | 359k | int idx, sum = 0; |
337 | 359k | Pel dcVal; |
338 | 359k | const int width = dstSize.width; |
339 | 359k | const int height = dstSize.height; |
340 | 359k | const auto denom = (width == height) ? (width << 1) : std::max(width,height); |
341 | 359k | const auto divShift = Log2(denom); |
342 | 359k | const auto divOffset = (denom >> 1); |
343 | 359k | const int off = m_ipaParam.multiRefIndex + 1; |
344 | | |
345 | | |
346 | 359k | if ( width >= height ) |
347 | 255k | { |
348 | 5.68M | for( idx = 0; idx < width; idx++ ) |
349 | 5.43M | { |
350 | 5.43M | sum += pSrc.at( off + idx, 0); |
351 | 5.43M | } |
352 | 255k | } |
353 | 359k | if ( width <= height ) |
354 | 244k | { |
355 | 5.62M | for( idx = 0; idx < height; idx++ ) |
356 | 5.38M | { |
357 | 5.38M | sum += pSrc.at( off + idx, 1); |
358 | 5.38M | } |
359 | 244k | } |
360 | | |
361 | 359k | dcVal = (sum + divOffset) >> divShift; |
362 | 359k | return dcVal; |
363 | 359k | } |
364 | | |
365 | | int IntraPrediction::getWideAngle( int width, int height, int predMode ) |
366 | 2.45M | { |
367 | 2.45M | if ( predMode > DC_IDX && predMode <= VDIA_IDX ) |
368 | 1.70M | { |
369 | 1.70M | int modeShift[] = { 0, 6, 10, 12, 14, 15 }; |
370 | 1.70M | int deltaSize = abs(Log2(width) - Log2(height)); |
371 | 1.70M | if (width > height && predMode < 2 + modeShift[deltaSize]) |
372 | 48.5k | { |
373 | 48.5k | predMode += (VDIA_IDX - 1); |
374 | 48.5k | } |
375 | 1.65M | else if (height > width && predMode > VDIA_IDX - modeShift[deltaSize]) |
376 | 85.2k | { |
377 | 85.2k | predMode -= (VDIA_IDX - 1); |
378 | 85.2k | } |
379 | 1.70M | } |
380 | 2.45M | return predMode; |
381 | 2.45M | } |
382 | | |
383 | | void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf& piPred, const CodingUnit& cu) |
384 | 2.18M | { |
385 | 2.18M | const ComponentID compID = compId; |
386 | 2.18M | const ChannelType channelType = toChannelType( compID ); |
387 | 2.18M | const uint32_t uiDirMode = cu.bdpcmM[channelType] ? BDPCM_IDX : CU::getFinalIntraMode(cu, channelType); |
388 | | |
389 | 2.18M | CHECK( Log2(piPred.width) > 7, "Size not allowed" ); |
390 | | |
391 | | // const int multiRefIdx = m_ipaParam.multiRefIndex; |
392 | 2.18M | const int srcStride = m_refBufferStride[compID]; |
393 | 2.18M | const int srcHStride = 2; |
394 | | |
395 | 2.18M | const CPelBuf& srcBuf = CPelBuf(getPredictorPtr(compID), srcStride, srcHStride); |
396 | 2.18M | const ClpRng& clpRng(cu.cs->slice->clpRngs[compID]); |
397 | | |
398 | 2.18M | switch (uiDirMode) |
399 | 2.18M | { |
400 | 152k | case(PLANAR_IDX): xPredIntraPlanar(piPred, srcBuf); break; |
401 | 359k | case(DC_IDX): xPredIntraDc ( piPred, srcBuf ); break; |
402 | 103k | case(BDPCM_IDX): xPredIntraBDPCM ( piPred, srcBuf, cu.bdpcmM[channelType], clpRng); break; |
403 | 1.56M | default: xPredIntraAng ( piPred, srcBuf, channelType, clpRng); break; |
404 | 2.18M | } |
405 | | |
406 | 2.18M | if (m_ipaParam.applyPDPC) |
407 | 1.60M | { |
408 | 1.60M | if (uiDirMode == PLANAR_IDX || uiDirMode == DC_IDX) |
409 | 457k | { |
410 | 457k | IntraPredSampleFilter(piPred, srcBuf); |
411 | 457k | } |
412 | 1.60M | } |
413 | 2.18M | } |
414 | | |
415 | | void IntraPrediction::predIntraChromaLM(const ComponentID compID, PelBuf& piPred, const CodingUnit& cu, const CompArea& chromaArea, int intraDir) |
416 | 258k | { |
417 | 258k | CHECK( piPred.width > MAX_TB_SIZEY || piPred.height > MAX_TB_SIZEY, "not enough memory"); |
418 | 258k | const int iLumaStride = 2 * MAX_TB_SIZEY + 1; |
419 | 258k | PelBuf Temp = PelBuf(m_pMdlmTemp + iLumaStride + 1, iLumaStride, Size(chromaArea)); |
420 | | |
421 | 258k | int a, b, iShift; |
422 | 258k | xGetLMParameters(cu, compID, chromaArea, a, b, iShift); // th shift result is unsigned |
423 | | |
424 | | ////// final prediction |
425 | 258k | piPred.copyFrom(Temp); |
426 | 258k | piPred.linearTransform(a, iShift, b, true, cu.cs->slice->clpRngs[compID]); |
427 | 258k | } |
428 | | |
429 | | /** Function for deriving planar intra prediction. This function derives the prediction samples for planar mode (intra coding). |
430 | | */ |
431 | | |
432 | | void IntraPrediction::xPredIntraDc( PelBuf& pDst, const CPelBuf& pSrc ) |
433 | 359k | { |
434 | 359k | const Pel dcval = xGetPredValDc( pSrc, pDst ); |
435 | 359k | pDst.fill( dcval ); |
436 | 359k | } |
437 | | |
438 | | // Function for initialization of intra prediction parameters |
439 | | void IntraPrediction::initPredIntraParams(const CodingUnit& cu, const CompArea area, const SPS& sps) |
440 | 2.45M | { |
441 | 2.45M | const ComponentID compId = area.compID; |
442 | 2.45M | const ChannelType chType = toChannelType(compId); |
443 | | |
444 | 2.45M | const bool useISP = NOT_INTRA_SUBPARTITIONS != cu.ispMode && isLuma( chType ); |
445 | | |
446 | 2.45M | const Size cuSize = Size( cu.blocks[compId].width, cu.blocks[compId].height ); |
447 | 2.45M | const Size puSize = Size( area.width, area.height ); |
448 | 2.45M | const Size& blockSize = useISP ? cuSize : puSize; |
449 | 2.45M | const int dirMode = CU::getFinalIntraMode(cu, chType); |
450 | 2.45M | const int predMode = getWideAngle( blockSize.width, blockSize.height, dirMode ); |
451 | | |
452 | 2.45M | m_ipaParam.isModeVer = predMode >= DIA_IDX; |
453 | 2.45M | m_ipaParam.multiRefIndex = isLuma (chType) ? cu.multiRefIdx : 0 ; |
454 | 2.45M | m_ipaParam.refFilterFlag = false; |
455 | 2.45M | m_ipaParam.interpolationFlag = false; |
456 | 2.45M | m_ipaParam.applyPDPC = (puSize.width >= MIN_TB_SIZEY && puSize.height >= MIN_TB_SIZEY) && m_ipaParam.multiRefIndex == 0; |
457 | | |
458 | 2.45M | const int intraPredAngleMode = (m_ipaParam.isModeVer) ? predMode - VER_IDX : -(predMode - HOR_IDX); |
459 | | |
460 | | |
461 | 2.45M | int absAng = 0; |
462 | 2.45M | if (dirMode > DC_IDX && dirMode < NUM_LUMA_MODE) // intraPredAngle for directional modes |
463 | 1.70M | { |
464 | 1.70M | static const int angTable[32] = { 0, 1, 2, 3, 4, 6, 8, 10, 12, 14, 16, 18, 20, 23, 26, 29, 32, 35, 39, 45, 51, 57, 64, 73, 86, 102, 128, 171, 256, 341, 512, 1024 }; |
465 | 1.70M | static const int invAngTable[32] = { |
466 | 1.70M | 0, 16384, 8192, 5461, 4096, 2731, 2048, 1638, 1365, 1170, 1024, 910, 819, 712, 630, 565, |
467 | 1.70M | 512, 468, 420, 364, 321, 287, 256, 224, 191, 161, 128, 96, 64, 48, 32, 16 |
468 | 1.70M | }; // (512 * 32) / Angle |
469 | | |
470 | 1.70M | const int absAngMode = abs(intraPredAngleMode); |
471 | 1.70M | const int signAng = intraPredAngleMode < 0 ? -1 : 1; |
472 | 1.70M | absAng = angTable [absAngMode]; |
473 | | |
474 | 1.70M | m_ipaParam.absInvAngle = invAngTable[absAngMode]; |
475 | 1.70M | m_ipaParam.intraPredAngle = signAng * absAng; |
476 | 1.70M | if (intraPredAngleMode < 0) |
477 | 305k | { |
478 | 305k | m_ipaParam.applyPDPC = false; |
479 | 305k | } |
480 | 1.39M | else if (intraPredAngleMode > 0) |
481 | 691k | { |
482 | 691k | const int sideSize = m_ipaParam.isModeVer ? puSize.height : puSize.width; |
483 | 691k | const int maxScale = 2; |
484 | | |
485 | 691k | m_ipaParam.angularScale = std::min(maxScale, floorLog2(sideSize) - (floorLog2(3 * m_ipaParam.absInvAngle - 2) - 8)); |
486 | 691k | m_ipaParam.applyPDPC &= m_ipaParam.angularScale >= 0; |
487 | 691k | } |
488 | 1.70M | } |
489 | | |
490 | | // high level conditions and DC intra prediction |
491 | 2.45M | if( !isLuma( chType ) |
492 | 1.01M | || useISP |
493 | 991k | || CU::isMIP( cu, chType ) //th remove this |
494 | 932k | || m_ipaParam.multiRefIndex |
495 | 735k | || DC_IDX == dirMode |
496 | 2.45M | ) |
497 | 1.75M | { |
498 | 1.75M | } |
499 | 699k | else if (cu.bdpcmM[chType]) |
500 | 8.65k | { |
501 | 8.65k | m_ipaParam.refFilterFlag = false; |
502 | 8.65k | } |
503 | 691k | else if (dirMode == PLANAR_IDX) // Planar intra prediction |
504 | 36.9k | { |
505 | 36.9k | m_ipaParam.refFilterFlag = puSize.width * puSize.height > 32 ? true : false; |
506 | 36.9k | } |
507 | 654k | else if (!useISP)// HOR, VER and angular modes (MDIS) |
508 | 654k | { |
509 | 654k | bool filterFlag = false; |
510 | 654k | { |
511 | 654k | const int diff = std::min<int>( abs( predMode - HOR_IDX ), abs( predMode - VER_IDX ) ); |
512 | 654k | const int log2Size = (Log2(puSize.width * puSize.height) >> 1); |
513 | 654k | CHECK( log2Size >= MAX_INTRA_FILTER_DEPTHS, "Size not supported" ); |
514 | 654k | filterFlag = (diff > m_aucIntraFilter[log2Size]); |
515 | 654k | } |
516 | | |
517 | | // Selelection of either ([1 2 1] / 4 ) refrence filter OR Gaussian 4-tap interpolation filter |
518 | 654k | if (filterFlag) |
519 | 531k | { |
520 | 531k | const bool isRefFilter = isIntegerSlope(absAng); |
521 | 531k | CHECK( puSize.width * puSize.height <= 32, "DCT-IF interpolation filter is always used for 4x4, 4x8, and 8x4 luma CB" ); |
522 | 531k | m_ipaParam.refFilterFlag = isRefFilter; |
523 | 531k | m_ipaParam.interpolationFlag = !isRefFilter; |
524 | 531k | } |
525 | 654k | } |
526 | 2.45M | } |
527 | | |
528 | | } // namespace vvenc |
529 | | |
530 | | #ifdef TARGET_SIMD_X86 |
531 | | #include "x86/CommonDefX86.h" |
532 | | #endif |
533 | | |
534 | | namespace vvenc { |
535 | | |
536 | | /** Function for deriving the simplified angular intra predictions. |
537 | | * |
538 | | * This function derives the prediction samples for the angular mode based on the prediction direction indicated by |
539 | | * the prediction mode index. The prediction direction is given by the displacement of the bottom row of the block and |
540 | | * the reference row above the block in the case of vertical prediction or displacement of the rightmost column |
541 | | * of the block and reference column left from the block in the case of the horizontal prediction. The displacement |
542 | | * is signalled at 1/32 pixel accuracy. When projection of the predicted pixel falls inbetween reference samples, |
543 | | * the predicted value for the pixel is linearly interpolated from the reference samples. All reference samples are taken |
544 | | * from the extended main reference. |
545 | | */ |
546 | | //NOTE: Bit-Limit - 25-bit source |
547 | | |
548 | | void IntraPrediction::xPredIntraAng( PelBuf& pDst, const CPelBuf& pSrc, const ChannelType channelType, const ClpRng& clpRng) |
549 | 1.56M | { |
550 | 1.56M | int width =int(pDst.width); |
551 | 1.56M | int height=int(pDst.height); |
552 | | |
553 | 1.56M | const bool bIsModeVer = m_ipaParam.isModeVer; |
554 | 1.56M | const int multiRefIdx = m_ipaParam.multiRefIndex; |
555 | 1.56M | const int intraPredAngle = m_ipaParam.intraPredAngle; |
556 | 1.56M | const int absInvAngle = m_ipaParam.absInvAngle; |
557 | | |
558 | 1.56M | Pel* refMain; |
559 | 1.56M | Pel* refSide; |
560 | | |
561 | 1.56M | Pel refAbove[2 * MAX_CU_SIZE + 3 + 33 * MAX_REF_LINE_IDX]; |
562 | 1.56M | Pel refLeft [2 * MAX_CU_SIZE + 3 + 33 * MAX_REF_LINE_IDX]; |
563 | | |
564 | | // Initialize the Main and Left reference array. |
565 | 1.56M | if (intraPredAngle < 0) |
566 | 304k | { |
567 | 304k | memcpy(&refAbove[height],pSrc.buf,(width + 2 + multiRefIdx)*sizeof(Pel)); |
568 | 10.2M | for (int y = 0; y <= height + 1 + multiRefIdx; y++) |
569 | 9.98M | { |
570 | 9.98M | refLeft[y + width] = pSrc.at(y, 1); |
571 | 9.98M | } |
572 | 304k | refMain = bIsModeVer ? refAbove + height : refLeft + width; |
573 | 304k | refSide = bIsModeVer ? refLeft + width : refAbove + height; |
574 | | |
575 | | // Extend the Main reference to the left. |
576 | 304k | int sizeSide = bIsModeVer ? height : width; |
577 | 9.59M | for (int k = -sizeSide; k <= -1; k++) |
578 | 9.29M | { |
579 | 9.29M | refMain[k] = refSide[std::min((-k * absInvAngle + 256) >> 9, sizeSide)]; |
580 | 9.29M | } |
581 | 304k | } |
582 | 1.26M | else |
583 | 1.26M | { |
584 | 1.26M | memcpy(&refAbove[0], pSrc.buf, ((m_topRefLength)+multiRefIdx + 1) * sizeof(Pel)); |
585 | 56.3M | for (int y = 0; y <= m_leftRefLength + multiRefIdx; y++) |
586 | 55.1M | { |
587 | 55.1M | refLeft[y] = pSrc.at(y, 1); |
588 | 55.1M | } |
589 | | |
590 | 1.26M | refMain = bIsModeVer ? refAbove : refLeft; |
591 | 1.26M | refSide = bIsModeVer ? refLeft : refAbove; |
592 | | |
593 | | // Extend main reference to right using replication |
594 | 1.26M | const int log2Ratio = Log2(width) - Log2(height); |
595 | 1.26M | const int s = std::max<int>(0, bIsModeVer ? log2Ratio : -log2Ratio); |
596 | 1.26M | const int maxIndex = (multiRefIdx << s) + 2; |
597 | 1.26M | const int refLength = bIsModeVer ? m_topRefLength : m_leftRefLength; |
598 | 1.26M | const Pel val = refMain[refLength + multiRefIdx]; |
599 | 4.07M | for (int z = 1; z <= maxIndex; z++) |
600 | 2.81M | { |
601 | 2.81M | refMain[refLength + multiRefIdx + z] = val; |
602 | 2.81M | } |
603 | 1.26M | } |
604 | | |
605 | | // swap width/height if we are doing a horizontal mode: |
606 | 1.56M | if (!bIsModeVer) |
607 | 761k | { |
608 | 761k | std::swap(width, height); |
609 | 761k | } |
610 | 1.56M | Pel tempArray[MAX_CU_SIZE*MAX_CU_SIZE]; |
611 | 1.56M | const int dstStride = bIsModeVer ? pDst.stride : MAX_CU_SIZE; |
612 | 1.56M | Pel* pDstBuf = bIsModeVer ? pDst.buf : tempArray; |
613 | | |
614 | | // compensate for line offset in reference line buffers |
615 | 1.56M | refMain += multiRefIdx; |
616 | 1.56M | refSide += multiRefIdx; |
617 | | |
618 | 1.56M | Pel* pDsty = pDstBuf; |
619 | | |
620 | 1.56M | if( intraPredAngle == 0 ) // pure vertical or pure horizontal |
621 | 599k | { |
622 | 599k | if (m_ipaParam.applyPDPC) |
623 | 502k | { |
624 | 502k | const int scale = (Log2(width * height) - 2) >> 2; |
625 | 502k | IntraHorVerPDPC(pDsty,dstStride,refSide,width,height,scale,refMain,clpRng); |
626 | 502k | } |
627 | 96.8k | else |
628 | 96.8k | { |
629 | 2.45M | for( int y = 0; y < height; y++ ) |
630 | 2.35M | { |
631 | 2.35M | memcpy(pDsty,&refMain[1],width*sizeof(Pel)); |
632 | 2.35M | pDsty += dstStride; |
633 | 2.35M | } |
634 | 96.8k | } |
635 | 599k | } |
636 | 970k | else |
637 | 970k | { |
638 | 970k | if( !isIntegerSlope( abs( intraPredAngle ) ) ) |
639 | 782k | { |
640 | 782k | int deltaPos = intraPredAngle * ( 1 + multiRefIdx ); |
641 | 782k | if( isLuma( channelType ) ) |
642 | 710k | { |
643 | 710k | if( width <= 2 ) |
644 | 0 | { |
645 | 0 | for( int y = 0, deltaPos = intraPredAngle * ( 1 + multiRefIdx ); |
646 | 0 | y < height; |
647 | 0 | y++, deltaPos += intraPredAngle, pDsty += dstStride ) |
648 | 0 | { |
649 | 0 | const int deltaInt = deltaPos >> 5; |
650 | 0 | const int deltaFract = deltaPos & 31; |
651 | |
|
652 | 0 | if( !isIntegerSlope( abs( intraPredAngle ) ) ) |
653 | 0 | { |
654 | 0 | const bool useCubicFilter = !m_ipaParam.interpolationFlag; |
655 | |
|
656 | 0 | const TFilterCoeff intraSmoothingFilter[4] = { TFilterCoeff( 16 - ( deltaFract >> 1 ) ), |
657 | 0 | TFilterCoeff( 32 - ( deltaFract >> 1 ) ), |
658 | 0 | TFilterCoeff( 16 + ( deltaFract >> 1 ) ), |
659 | 0 | TFilterCoeff( ( deltaFract >> 1 ) ) }; |
660 | 0 | const TFilterCoeff* const f = |
661 | 0 | ( useCubicFilter ) ? InterpolationFilter::getChromaFilterTable( deltaFract ) : intraSmoothingFilter; |
662 | |
|
663 | 0 | for( int x = 0; x < width; x++ ) |
664 | 0 | { |
665 | 0 | Pel p[4]; |
666 | |
|
667 | 0 | p[0] = refMain[deltaInt + x + 0]; |
668 | 0 | p[1] = refMain[deltaInt + x + 1]; |
669 | 0 | p[2] = refMain[deltaInt + x + 2]; |
670 | 0 | p[3] = refMain[deltaInt + x + 3]; |
671 | |
|
672 | 0 | Pel val = ( f[0] * p[0] + f[1] * p[1] + f[2] * p[2] + f[3] * p[3] + 32 ) >> 6; |
673 | |
|
674 | 0 | pDsty[x] = ClipPel( val, clpRng ); // always clip even though not always needed |
675 | 0 | } |
676 | 0 | } |
677 | 0 | } |
678 | 0 | } |
679 | 710k | else |
680 | 710k | { |
681 | 710k | IntraPredAngleLuma(pDstBuf, dstStride, refMain, width, height, deltaPos, intraPredAngle, nullptr, !m_ipaParam.interpolationFlag, clpRng); |
682 | 710k | } |
683 | 710k | } |
684 | 72.2k | else |
685 | 72.2k | { |
686 | 72.2k | IntraPredAngleChroma(pDstBuf,dstStride,refMain,width,height,deltaPos,intraPredAngle); |
687 | 72.2k | } |
688 | 782k | } |
689 | 188k | else |
690 | 188k | { |
691 | 2.88M | for (int y = 0, deltaPos = intraPredAngle * (1 + multiRefIdx); y<height; y++, deltaPos += intraPredAngle, pDsty += dstStride) |
692 | 2.69M | { |
693 | 2.69M | const int deltaInt = deltaPos >> 5; |
694 | | // Just copy the integer samples |
695 | 2.69M | memcpy(pDsty,refMain + deltaInt + 1,width*sizeof(Pel)); |
696 | 2.69M | } |
697 | 188k | } |
698 | | |
699 | 970k | if (m_ipaParam.applyPDPC) |
700 | 550k | { |
701 | 550k | pDsty = pDstBuf; |
702 | 550k | IntraAnglePDPC(pDsty,dstStride,refSide,width,height,m_ipaParam.angularScale,absInvAngle); |
703 | 550k | } |
704 | 970k | } // else |
705 | | |
706 | | // Flip the block if this is the horizontal mode |
707 | 1.56M | if( !bIsModeVer ) |
708 | 761k | { |
709 | 761k | pDst.transposedFrom( CPelBuf( pDstBuf, dstStride, width, height) ); |
710 | 761k | } |
711 | 1.56M | } |
712 | | |
713 | | void IntraPrediction::xPredIntraBDPCM(PelBuf& pDst, const CPelBuf& pSrc, const uint32_t dirMode, const ClpRng& clpRng) |
714 | 103k | { |
715 | 103k | const int wdt = pDst.width; |
716 | 103k | const int hgt = pDst.height; |
717 | | |
718 | 103k | const int strideP = pDst.stride; |
719 | 103k | const int strideS = pSrc.stride; |
720 | | |
721 | 103k | CHECK(!(dirMode == 1 || dirMode == 2), "Incorrect BDPCM mode parameter."); |
722 | | |
723 | 103k | Pel* pred = &pDst.buf[0]; |
724 | 103k | if (dirMode == 1) |
725 | 4.32k | { |
726 | 4.32k | Pel val; |
727 | 59.6k | for (int y = 0; y < hgt; y++) |
728 | 55.3k | { |
729 | 55.3k | val = pSrc.buf[(y + 1) + strideS]; |
730 | 793k | for (int x = 0; x < wdt; x++) |
731 | 738k | { |
732 | 738k | pred[x] = val; |
733 | 738k | } |
734 | 55.3k | pred += strideP; |
735 | 55.3k | } |
736 | 4.32k | } |
737 | 99.3k | else |
738 | 99.3k | { |
739 | 1.02M | for (int y = 0; y < hgt; y++) |
740 | 926k | { |
741 | 10.4M | for (int x = 0; x < wdt; x++) |
742 | 9.53M | { |
743 | 9.53M | pred[x] = pSrc.buf[x + 1]; |
744 | 9.53M | } |
745 | 926k | pred += strideP; |
746 | 926k | } |
747 | 99.3k | } |
748 | 103k | } |
749 | | |
750 | | inline bool isAboveLeftAvailable ( const CodingUnit &cu, const ChannelType& chType, const Position& posLT ); |
751 | | inline int isAboveAvailable ( const CodingUnit &cu, const ChannelType& chType, const Position& posLT, const uint32_t numUnits, const uint32_t unitWidth, bool *validFlags ); |
752 | | inline int isLeftAvailable ( const CodingUnit &cu, const ChannelType& chType, const Position& posLT, const uint32_t numUnits, const uint32_t unitWidth, bool *validFlags ); |
753 | | inline int isAboveRightAvailable ( const CodingUnit &cu, const ChannelType& chType, const Position& posRT, const uint32_t numUnits, const uint32_t unitHeight, bool *validFlags ); |
754 | | inline int isBelowLeftAvailable ( const CodingUnit &cu, const ChannelType& chType, const Position& posLB, const uint32_t numUnits, const uint32_t unitHeight, bool *validFlags ); |
755 | | |
756 | | void IntraPrediction::initIntraPatternChType(const CodingUnit &cu, const CompArea& area, const bool forceRefFilterFlag) |
757 | 1.01M | { |
758 | 1.01M | const CodingStructure& cs = *cu.cs; |
759 | | |
760 | 1.01M | if (!forceRefFilterFlag) |
761 | 941k | { |
762 | 941k | initPredIntraParams(cu, area, *cs.sps); |
763 | 941k | } |
764 | | |
765 | 1.01M | Pel *refBufUnfiltered = m_refBuffer[area.compID][PRED_BUF_UNFILTERED]; |
766 | 1.01M | Pel *refBufFiltered = m_refBuffer[area.compID][PRED_BUF_FILTERED]; |
767 | | |
768 | 1.01M | setReferenceArrayLengths(area); |
769 | | |
770 | | // ----- Step 1: unfiltered reference samples ----- |
771 | 1.01M | xFillReferenceSamples( cs.picture->getRecoBuf( area ), refBufUnfiltered, area, cu ); |
772 | | // ----- Step 2: filtered reference samples ----- |
773 | 1.01M | if( m_ipaParam.refFilterFlag || forceRefFilterFlag ) |
774 | 76.1k | { |
775 | 76.1k | xFilterReferenceSamples( refBufUnfiltered, refBufFiltered, area, *cs.sps, cu.multiRefIdx ); |
776 | 76.1k | } |
777 | 1.01M | } |
778 | | |
779 | | void IntraPrediction::reset() |
780 | 104k | { |
781 | 104k | m_lastCh = MAX_NUM_CH; |
782 | 104k | m_lastArea = Area(0,0,0,0); |
783 | 104k | } |
784 | | |
785 | | void IntraPrediction::xFillReferenceSamples( const CPelBuf& recoBuf, Pel* refBufUnfiltered, const CompArea& area, const CodingUnit &cu ) |
786 | 1.03M | { |
787 | 1.03M | const ChannelType chType = toChannelType( area.compID ); |
788 | 1.03M | const CodingStructure &cs = *cu.cs; |
789 | 1.03M | const SPS &sps = *cs.sps; |
790 | 1.03M | const PreCalcValues &pcv = *cs.pcv; |
791 | | |
792 | 1.03M | const int multiRefIdx = (area.compID == COMP_Y) ? cu.multiRefIdx : 0; |
793 | | |
794 | 1.03M | const int tuWidth = area.width; |
795 | 1.03M | const int tuHeight = area.height; |
796 | 1.03M | const int predSize = m_topRefLength; |
797 | 1.03M | const int predHSize = m_leftRefLength; |
798 | 1.03M | const int predStride = predSize + 1 + multiRefIdx; |
799 | 1.03M | m_refBufferStride[area.compID] = predStride; |
800 | | |
801 | 1.03M | const int unitWidth = tuWidth <= 2 && cu.ispMode && isLuma(area.compID) ? tuWidth : pcv.minCUSize >> getComponentScaleX(area.compID, sps.chromaFormatIdc); |
802 | 1.03M | const int unitHeight = tuHeight <= 2 && cu.ispMode && isLuma(area.compID) ? tuHeight : pcv.minCUSize >> getComponentScaleY(area.compID, sps.chromaFormatIdc); |
803 | | |
804 | 1.03M | const int totalAboveUnits = (predSize + (unitWidth - 1)) / unitWidth; |
805 | 1.03M | const int totalLeftUnits = (predHSize + (unitHeight - 1)) / unitHeight; |
806 | 1.03M | const int totalUnits = totalAboveUnits + totalLeftUnits + 1; //+1 for top-left |
807 | | |
808 | 1.03M | if( m_lastArea != area || m_lastCh != chType ) |
809 | 104k | { |
810 | 104k | m_lastCh = chType; |
811 | 104k | m_lastArea = area; |
812 | 104k | const int numAboveUnits = std::max<int>( tuWidth / unitWidth, 1 ); |
813 | 104k | const int numLeftUnits = std::max<int>( tuHeight / unitHeight, 1 ); |
814 | 104k | const int numAboveRightUnits = totalAboveUnits - numAboveUnits; |
815 | 104k | const int numLeftBelowUnits = totalLeftUnits - numLeftUnits; |
816 | | |
817 | 104k | CHECK( numAboveUnits <= 0 || numLeftUnits <= 0 || numAboveRightUnits <= 0 || numLeftBelowUnits <= 0, "Size not supported" ); |
818 | | |
819 | | // ----- Step 1: analyze neighborhood ----- |
820 | 104k | const Position posLT = area; |
821 | 104k | const Position posRT = area.topRight(); |
822 | 104k | const Position posLB = area.bottomLeft(); |
823 | | |
824 | 104k | m_numIntraNeighbor = 0; |
825 | | |
826 | 104k | memset( m_neighborFlags, 0, totalUnits ); |
827 | | |
828 | 104k | m_neighborFlags[totalLeftUnits] = isAboveLeftAvailable( cu, chType, posLT ); |
829 | 104k | m_numIntraNeighbor += m_neighborFlags[totalLeftUnits] ? 1 : 0; |
830 | 104k | m_numIntraNeighbor += isAboveAvailable ( cu, chType, posLT, numAboveUnits, unitWidth, (m_neighborFlags + totalLeftUnits + 1) ); |
831 | 104k | m_numIntraNeighbor += isAboveRightAvailable( cu, chType, posRT, numAboveRightUnits, unitWidth, (m_neighborFlags + totalLeftUnits + 1 + numAboveUnits) ); |
832 | 104k | m_numIntraNeighbor += isLeftAvailable ( cu, chType, posLT, numLeftUnits, unitHeight, (m_neighborFlags + totalLeftUnits - 1) ); |
833 | 104k | m_numIntraNeighbor += isBelowLeftAvailable ( cu, chType, posLB, numLeftBelowUnits, unitHeight, (m_neighborFlags + totalLeftUnits - 1 - numLeftUnits) ); |
834 | 104k | } |
835 | | // ----- Step 2: fill reference samples (depending on neighborhood) ----- |
836 | | |
837 | 1.03M | const Pel* srcBuf = recoBuf.buf; |
838 | 1.03M | const int srcStride = recoBuf.stride; |
839 | 1.03M | Pel* ptrDst = refBufUnfiltered; |
840 | 1.03M | const Pel* ptrSrc; |
841 | 1.03M | const Pel valueDC = 1 << (sps.bitDepths[ chType ] - 1); |
842 | | |
843 | | |
844 | 1.03M | if( m_numIntraNeighbor == 0 ) |
845 | 327k | { |
846 | | // Fill border with DC value |
847 | 9.99M | for (int j = 0; j <= predSize + multiRefIdx; j++) { ptrDst[j] = valueDC; } |
848 | 9.70M | for (int i = 0; i <= predHSize + multiRefIdx; i++) { ptrDst[i+predStride] = valueDC; } |
849 | 327k | } |
850 | 703k | else if( m_numIntraNeighbor == totalUnits ) |
851 | 1.69k | { |
852 | | // Fill top-left border and top and top right with rec. samples |
853 | 1.69k | ptrSrc = srcBuf - (1 + multiRefIdx) * srcStride - (1 + multiRefIdx); |
854 | 136k | for (int j = 0; j <= predSize + multiRefIdx; j++) { ptrDst[j] = ptrSrc[j]; } |
855 | 136k | for (int i = 0; i <= predHSize + multiRefIdx; i++) |
856 | 134k | { |
857 | 134k | ptrDst[i + predStride] = ptrSrc[i * srcStride]; |
858 | 134k | } |
859 | 1.69k | } |
860 | 702k | else // reference samples are partially available |
861 | 702k | { |
862 | | // Fill top-left sample(s) if available |
863 | 702k | ptrSrc = srcBuf - (1 + multiRefIdx) * srcStride - (1 + multiRefIdx); |
864 | 702k | ptrDst = refBufUnfiltered; |
865 | 702k | if (m_neighborFlags[totalLeftUnits]) |
866 | 243k | { |
867 | 243k | ptrDst[0] = ptrSrc[0]; |
868 | 243k | ptrDst[predStride] = ptrSrc[0]; |
869 | 291k | for (int i = 1; i <= multiRefIdx; i++) |
870 | 48.3k | { |
871 | 48.3k | ptrDst[i] = ptrSrc[i]; |
872 | 48.3k | ptrDst[i + predStride] = ptrSrc[i * srcStride]; |
873 | 48.3k | } |
874 | 243k | } |
875 | | |
876 | | // Fill left & below-left samples if available (downwards) |
877 | 702k | ptrSrc += (1 + multiRefIdx) * srcStride; |
878 | 702k | ptrDst += (1 + multiRefIdx) + predStride; |
879 | 10.4M | for (int unitIdx = totalLeftUnits - 1; unitIdx > 0; unitIdx--) |
880 | 9.76M | { |
881 | 9.76M | if (m_neighborFlags[unitIdx]) |
882 | 4.26M | { |
883 | 14.6M | for (int i = 0; i < unitHeight; i++) |
884 | 10.3M | { |
885 | 10.3M | ptrDst[i] = ptrSrc[i*srcStride]; |
886 | 10.3M | } |
887 | 4.26M | } |
888 | 9.76M | ptrSrc += unitHeight * srcStride; |
889 | 9.76M | ptrDst += unitHeight; |
890 | 9.76M | } |
891 | | // Fill last below-left sample(s) |
892 | 702k | if (m_neighborFlags[0]) |
893 | 23.3k | { |
894 | 23.3k | int lastSample = (predHSize % unitHeight == 0) ? unitHeight : predHSize % unitHeight; |
895 | 93.5k | for (int i = 0; i < lastSample; i++) |
896 | 70.2k | { |
897 | 70.2k | ptrDst[i] = ptrSrc[i*srcStride]; |
898 | 70.2k | } |
899 | 23.3k | } |
900 | | |
901 | | // Fill above & above-right samples if available (left-to-right) |
902 | 702k | ptrSrc = srcBuf - srcStride * (1 + multiRefIdx); |
903 | 702k | ptrDst = refBufUnfiltered + 1 + multiRefIdx; |
904 | 10.4M | for (int unitIdx = totalLeftUnits + 1; unitIdx < totalUnits - 1; unitIdx++) |
905 | 9.76M | { |
906 | 9.76M | if (m_neighborFlags[unitIdx]) |
907 | 5.37M | { |
908 | 5.37M | memcpy(ptrDst,ptrSrc,unitWidth*sizeof(Pel)); |
909 | 5.37M | } |
910 | 9.76M | ptrSrc += unitWidth; |
911 | 9.76M | ptrDst += unitWidth; |
912 | 9.76M | } |
913 | | // Fill last above-right sample(s) |
914 | 702k | if (m_neighborFlags[totalUnits - 1]) |
915 | 86.8k | { |
916 | 86.8k | int lastSample = (predSize % unitWidth == 0) ? unitWidth : predSize % unitWidth; |
917 | 86.8k | memcpy(ptrDst,ptrSrc,lastSample*sizeof(Pel)); |
918 | 86.8k | } |
919 | | |
920 | | // pad from first available down to the last below-left |
921 | 702k | ptrDst = refBufUnfiltered; |
922 | 702k | int lastAvailUnit = 0; |
923 | 702k | if (!m_neighborFlags[0]) |
924 | 678k | { |
925 | 678k | int firstAvailUnit = 1; |
926 | 6.42M | while (firstAvailUnit < totalUnits && !m_neighborFlags[firstAvailUnit]) |
927 | 5.75M | { |
928 | 5.75M | firstAvailUnit++; |
929 | 5.75M | } |
930 | | |
931 | | // first available sample |
932 | 678k | int firstAvailRow = -1; |
933 | 678k | int firstAvailCol = 0; |
934 | 678k | if (firstAvailUnit < totalLeftUnits) |
935 | 427k | { |
936 | 427k | firstAvailRow = (totalLeftUnits - firstAvailUnit) * unitHeight + multiRefIdx; |
937 | 427k | } |
938 | 251k | else if (firstAvailUnit == totalLeftUnits) |
939 | 0 | { |
940 | 0 | firstAvailRow = multiRefIdx; |
941 | 0 | } |
942 | 251k | else |
943 | 251k | { |
944 | 251k | firstAvailCol = (firstAvailUnit - totalLeftUnits - 1) * unitWidth + 1 + multiRefIdx; |
945 | 251k | } |
946 | 678k | const Pel firstAvailSample = ptrDst[firstAvailRow < 0 ? firstAvailCol : firstAvailRow + predStride]; |
947 | | |
948 | | // last sample below-left (n.a.) |
949 | 678k | int lastRow = predHSize + multiRefIdx; |
950 | | |
951 | | // fill left column |
952 | 15.7M | for (int i = lastRow; i > firstAvailRow; i--) |
953 | 15.0M | { |
954 | 15.0M | ptrDst[i + predStride] = firstAvailSample; |
955 | 15.0M | } |
956 | | // fill top row |
957 | 678k | if (firstAvailCol > 0) |
958 | 251k | { |
959 | 515k | for (int j = 0; j < firstAvailCol; j++) |
960 | 264k | { |
961 | 264k | ptrDst[j] = firstAvailSample; |
962 | 264k | } |
963 | 251k | } |
964 | 678k | lastAvailUnit = firstAvailUnit; |
965 | 678k | } |
966 | | |
967 | | // pad all other reference samples. |
968 | 702k | int currUnit = lastAvailUnit + 1; |
969 | 15.1M | while (currUnit < totalUnits) |
970 | 14.4M | { |
971 | 14.4M | if (!m_neighborFlags[currUnit]) // samples not available |
972 | 5.20M | { |
973 | | // last available sample |
974 | 5.20M | int lastAvailRow = -1; |
975 | 5.20M | int lastAvailCol = 0; |
976 | 5.20M | if (lastAvailUnit < totalLeftUnits) |
977 | 207k | { |
978 | 207k | lastAvailRow = (totalLeftUnits - lastAvailUnit - 1) * unitHeight + multiRefIdx + 1; |
979 | 207k | } |
980 | 4.99M | else if (lastAvailUnit == totalLeftUnits) |
981 | 207k | { |
982 | 207k | lastAvailCol = multiRefIdx; |
983 | 207k | } |
984 | 4.79M | else |
985 | 4.79M | { |
986 | 4.79M | lastAvailCol = (lastAvailUnit - totalLeftUnits) * unitWidth + multiRefIdx; |
987 | 4.79M | } |
988 | 5.20M | const Pel lastAvailSample = ptrDst[lastAvailRow < 0 ? lastAvailCol : lastAvailRow + predStride]; |
989 | | |
990 | | // fill current unit with last available sample |
991 | 5.20M | if (currUnit < totalLeftUnits) |
992 | 0 | { |
993 | 0 | for (int i = lastAvailRow - 1; i >= lastAvailRow - unitHeight; i--) |
994 | 0 | { |
995 | 0 | ptrDst[i + predStride] = lastAvailSample; |
996 | 0 | } |
997 | 0 | } |
998 | 5.20M | else if (currUnit == totalLeftUnits) |
999 | 207k | { |
1000 | 414k | for (int i = 0; i < multiRefIdx + 1; i++) |
1001 | 207k | { |
1002 | 207k | ptrDst[i + predStride] = lastAvailSample; |
1003 | 207k | } |
1004 | 414k | for (int j = 0; j < multiRefIdx + 1; j++) |
1005 | 207k | { |
1006 | 207k | ptrDst[j] = lastAvailSample; |
1007 | 207k | } |
1008 | 207k | } |
1009 | 4.99M | else |
1010 | 4.99M | { |
1011 | 4.99M | int numSamplesInUnit = (currUnit == totalUnits - 1) ? ((predSize % unitWidth == 0) ? unitWidth : predSize % unitWidth) : unitWidth; |
1012 | 16.4M | for (int j = lastAvailCol + 1; j <= lastAvailCol + numSamplesInUnit; j++) |
1013 | 11.4M | { |
1014 | 11.4M | ptrDst[j] = lastAvailSample; |
1015 | 11.4M | } |
1016 | 4.99M | } |
1017 | 5.20M | } |
1018 | 14.4M | lastAvailUnit = currUnit; |
1019 | 14.4M | currUnit++; |
1020 | 14.4M | } |
1021 | 702k | } |
1022 | 1.03M | } |
1023 | | |
1024 | | void IntraPrediction::xFilterReferenceSamples( const Pel* refBufUnfiltered, Pel* refBufFiltered, const CompArea& area, const SPS &sps |
1025 | | , int multiRefIdx |
1026 | | , int stride |
1027 | | ) |
1028 | 76.1k | { |
1029 | 76.1k | if (area.compID != COMP_Y) |
1030 | 0 | { |
1031 | 0 | multiRefIdx = 0; |
1032 | 0 | } |
1033 | 76.1k | const int predSize = m_topRefLength + multiRefIdx; |
1034 | 76.1k | const int predHSize = m_leftRefLength + multiRefIdx; |
1035 | 76.1k | const int predStride = stride == 0 ? predSize + 1 : stride; |
1036 | | |
1037 | | |
1038 | 76.1k | const Pel topLeft = |
1039 | 76.1k | (refBufUnfiltered[0] + refBufUnfiltered[1] + refBufUnfiltered[predStride] + refBufUnfiltered[predStride + 1] + 2) |
1040 | 76.1k | >> 2; |
1041 | | |
1042 | 76.1k | refBufFiltered[0] = topLeft; |
1043 | | |
1044 | 76.1k | IntraFilterRefSamples( refBufUnfiltered, refBufFiltered, predSize ); |
1045 | 76.1k | refBufFiltered[predSize] = refBufUnfiltered[predSize]; |
1046 | | |
1047 | 76.1k | refBufFiltered += predStride; |
1048 | 76.1k | refBufUnfiltered += predStride; |
1049 | | |
1050 | 76.1k | refBufFiltered[0] = topLeft; |
1051 | | |
1052 | 76.1k | IntraFilterRefSamples( refBufUnfiltered, refBufFiltered, predHSize ); |
1053 | 76.1k | refBufFiltered[predHSize] = refBufUnfiltered[predHSize]; |
1054 | 76.1k | } |
1055 | | |
1056 | | bool isAboveLeftAvailable(const CodingUnit &cu, const ChannelType& chType, const Position& posLT) |
1057 | 104k | { |
1058 | 104k | const CodingStructure& cs = *cu.cs; |
1059 | 104k | const Position refPos = posLT.offset(-1, -1); |
1060 | | |
1061 | 104k | return (cs.getCURestricted(refPos, cu, chType) != NULL); |
1062 | 104k | } |
1063 | | |
1064 | | int isAboveAvailable(const CodingUnit &cu, const ChannelType& chType, const Position& posLT, const uint32_t numUnits, const uint32_t unitWidth, bool *bValidFlags) |
1065 | 462k | { |
1066 | 462k | const CodingStructure& cs = *cu.cs; |
1067 | | |
1068 | 462k | bool * validFlags = bValidFlags; |
1069 | 462k | int numIntra = 0; |
1070 | 462k | const int maxDx = numUnits * unitWidth; |
1071 | 462k | unsigned checkPosX = 0; |
1072 | 462k | bool valid = false; |
1073 | | |
1074 | 1.99M | for (int dx = 0; dx < maxDx; dx += unitWidth) |
1075 | 1.80M | { |
1076 | 1.80M | if( dx >= checkPosX ) |
1077 | 464k | { |
1078 | 464k | const Position refPos = posLT.offset(dx, -1); |
1079 | | |
1080 | 464k | const CodingUnit* cuN = cs.getCURestricted(refPos, cu, chType); |
1081 | 464k | valid = (cuN != NULL); |
1082 | 464k | if( cuN ) checkPosX = chType == CH_C ? (cuN->Cb().x + cuN->Cb().width - posLT.x) : (cuN->Y().x + cuN->Y().width - posLT.x); |
1083 | 273k | else break; |
1084 | 464k | } |
1085 | | |
1086 | 1.53M | numIntra += valid ? 1 : 0; |
1087 | 1.53M | *validFlags = valid; |
1088 | | |
1089 | 1.53M | validFlags++; |
1090 | 1.53M | } |
1091 | | |
1092 | 462k | return numIntra; |
1093 | 462k | } |
1094 | | |
1095 | | int isLeftAvailable(const CodingUnit &cu, const ChannelType& chType, const Position& posLT, const uint32_t numUnits, const uint32_t unitHeight, bool *bValidFlags) |
1096 | 462k | { |
1097 | 462k | const CodingStructure& cs = *cu.cs; |
1098 | | |
1099 | 462k | bool * validFlags = bValidFlags; |
1100 | 462k | int numIntra = 0; |
1101 | 462k | const int maxDy = numUnits * unitHeight; |
1102 | 462k | unsigned checkPosY = 0; |
1103 | 462k | bool valid = false; |
1104 | | |
1105 | 1.87M | for (int dy = 0; dy < maxDy; dy += unitHeight) |
1106 | 1.69M | { |
1107 | 1.69M | if( dy >= checkPosY ) |
1108 | 466k | { |
1109 | 466k | const Position refPos = posLT.offset(-1, dy); |
1110 | | |
1111 | 466k | const CodingUnit* cuN = cs.getCURestricted(refPos, cu, chType); |
1112 | 466k | valid = (cuN != NULL); |
1113 | 466k | if( cuN ) checkPosY = chType == CH_C ? (cuN->Cb().y + cuN->Cb().height - posLT.y) : (cuN->Y().y + cuN->Y().height - posLT.y); |
1114 | 288k | else break; |
1115 | 466k | } |
1116 | | |
1117 | 18.4E | numIntra += valid ? 1 : 0; |
1118 | 1.40M | *validFlags = valid; |
1119 | | |
1120 | 1.40M | validFlags--; |
1121 | 1.40M | } |
1122 | | |
1123 | 462k | return numIntra; |
1124 | 462k | } |
1125 | | |
1126 | | int isAboveRightAvailable(const CodingUnit &cu, const ChannelType& chType, const Position& posRT, const uint32_t numUnits, const uint32_t unitWidth, bool *bValidFlags ) |
1127 | 236k | { |
1128 | 236k | const CodingStructure& cs = *cu.cs; |
1129 | | |
1130 | 236k | bool * validFlags = bValidFlags; |
1131 | 236k | int numIntra = 0; |
1132 | 236k | const int maxDx = numUnits * unitWidth; |
1133 | 236k | unsigned checkPosX = 0; |
1134 | 236k | bool valid = false; |
1135 | | |
1136 | 787k | for (int dx = 0; dx < maxDx; dx += unitWidth) |
1137 | 751k | { |
1138 | 751k | if( dx >= checkPosX ) |
1139 | 276k | { |
1140 | 276k | const Position refPos = posRT.offset(unitWidth + dx, -1); |
1141 | | |
1142 | 276k | const CodingUnit* cuN = cs.getCURestricted(refPos, cu, chType); |
1143 | 276k | valid = (cuN != NULL); |
1144 | 276k | if(cuN) checkPosX = chType == CH_C ? (cuN->Cb().x + cuN->Cb().width - (posRT.x + unitWidth)) : (cuN->Y().x + cuN->Y().width - (posRT.x + unitWidth)); |
1145 | 201k | else break; |
1146 | 276k | } |
1147 | | |
1148 | 550k | numIntra += valid ? 1 : 0; |
1149 | 550k | *validFlags = valid; |
1150 | | |
1151 | 550k | validFlags++; |
1152 | 550k | } |
1153 | | |
1154 | 236k | return numIntra; |
1155 | 236k | } |
1156 | | |
1157 | | int isBelowLeftAvailable(const CodingUnit &cu, const ChannelType& chType, const Position& posLB, const uint32_t numUnits, const uint32_t unitHeight, bool *bValidFlags ) |
1158 | 224k | { |
1159 | 224k | const CodingStructure& cs = *cu.cs; |
1160 | | |
1161 | 224k | bool * validFlags = bValidFlags; |
1162 | 224k | int numIntra = 0; |
1163 | 224k | const int maxDy = numUnits * unitHeight; |
1164 | 224k | unsigned checkPosY = 0; |
1165 | 224k | bool valid = false; |
1166 | | |
1167 | 398k | for (int dy = 0; dy < maxDy; dy += unitHeight) |
1168 | 390k | { |
1169 | 390k | if( dy >= checkPosY ) |
1170 | 246k | { |
1171 | 246k | const Position refPos = posLB.offset(-1, unitHeight + dy); |
1172 | | |
1173 | 246k | const CodingUnit* cuN = cs.getCURestricted(refPos, cu, chType); |
1174 | 246k | valid = (cuN != NULL); |
1175 | 246k | if( cuN ) checkPosY = chType == CH_C ? (cuN->Cb().y + cuN->Cb().height - (posLB.y + unitHeight)) : (cuN->Y().y + cuN->Y().height - (posLB.y + unitHeight)); |
1176 | 216k | else break; |
1177 | 246k | } |
1178 | | |
1179 | 174k | numIntra += valid ? 1 : 0; |
1180 | 174k | *validFlags = valid; |
1181 | | |
1182 | 174k | validFlags--; |
1183 | 174k | } |
1184 | | |
1185 | 224k | return numIntra; |
1186 | 224k | } |
1187 | | |
1188 | | // LumaRecPixels |
1189 | | void IntraPrediction::loadLMLumaRecPels(const CodingUnit& cu, const CompArea& chromaArea ) |
1190 | 98.5k | { |
1191 | 98.5k | int iDstStride = 2 * MAX_TB_SIZEY + 1; |
1192 | 98.5k | Pel* pDst0 = m_pMdlmTemp + iDstStride + 1; |
1193 | | //assert 420 chroma subsampling |
1194 | 98.5k | CompArea lumaArea = CompArea( COMP_Y, cu.chromaFormat, chromaArea.lumaPos(), recalcSize( cu.chromaFormat, CH_C, CH_L, chromaArea.size() ) );//needed for correct pos/size (4x4 Tus) |
1195 | | |
1196 | 98.5k | CHECK(lumaArea.width == chromaArea.width && CHROMA_444 != cu.chromaFormat, ""); |
1197 | 98.5k | CHECK(lumaArea.height == chromaArea.height && CHROMA_444 != cu.chromaFormat && CHROMA_422 != cu.chromaFormat, ""); |
1198 | | |
1199 | 98.5k | const SizeType uiCWidth = chromaArea.width; |
1200 | 98.5k | const SizeType uiCHeight = chromaArea.height; |
1201 | | |
1202 | 98.5k | const CPelBuf Src = cu.cs->picture->getRecoBuf( lumaArea ); |
1203 | 98.5k | Pel const* pRecSrc0 = Src.bufAt( 0, 0 ); |
1204 | 98.5k | int iRecStride = Src.stride; |
1205 | 98.5k | int logSubWidthC = getChannelTypeScaleX(CH_C, cu.chromaFormat); |
1206 | 98.5k | int logSubHeightC = getChannelTypeScaleY(CH_C, cu.chromaFormat); |
1207 | | |
1208 | 98.5k | int iRecStride2 = iRecStride << logSubHeightC; |
1209 | | |
1210 | 98.5k | const CompArea& area = isChroma( cu.chType ) ? chromaArea : lumaArea; |
1211 | | |
1212 | 98.5k | const uint32_t uiTuWidth = area.width; |
1213 | 98.5k | const uint32_t uiTuHeight = area.height; |
1214 | | |
1215 | 98.5k | const int unitWidthLog2 = MIN_CU_LOG2 - getComponentScaleX( area.compID, area.chromaFormat ); |
1216 | 98.5k | const int unitHeightLog2 = MIN_CU_LOG2 - getComponentScaleY( area.compID, area.chromaFormat ); |
1217 | 98.5k | const int unitWidth = 1<<unitWidthLog2; |
1218 | 98.5k | const int unitHeight = 1<<unitHeightLog2; |
1219 | | |
1220 | 98.5k | const int iTUWidthInUnits = uiTuWidth >> unitWidthLog2; |
1221 | 98.5k | const int iTUHeightInUnits = uiTuHeight >> unitHeightLog2; |
1222 | 98.5k | const int iAboveUnits = iTUWidthInUnits; |
1223 | 98.5k | const int iLeftUnits = iTUHeightInUnits; |
1224 | | |
1225 | 98.5k | const int chromaUnitWidthLog2 = MIN_CU_LOG2 - logSubWidthC; |
1226 | 98.5k | const int chromaUnitHeightLog2 = MIN_CU_LOG2 - logSubHeightC; |
1227 | 98.5k | const int chromaUnitWidth = 1<<chromaUnitWidthLog2; |
1228 | 98.5k | const int chromaUnitHeight = 1<<chromaUnitHeightLog2; |
1229 | 98.5k | const int topTemplateSampNum = 2 * uiCWidth; // for MDLM, the number of template samples is 2W or 2H. |
1230 | 98.5k | const int leftTemplateSampNum = 2 * uiCHeight; |
1231 | 98.5k | const int totalAboveUnits = (topTemplateSampNum + (chromaUnitWidth - 1)) >> chromaUnitWidthLog2; |
1232 | 98.5k | const int totalLeftUnits = (leftTemplateSampNum + (chromaUnitHeight - 1)) >> chromaUnitHeightLog2; |
1233 | 98.5k | const int totalUnits = totalLeftUnits + totalAboveUnits + 1; |
1234 | 98.5k | const int aboveRightUnits = totalAboveUnits - iAboveUnits; |
1235 | 98.5k | const int leftBelowUnits = totalLeftUnits - iLeftUnits; |
1236 | | |
1237 | 98.5k | int avaiAboveRightUnits = 0; |
1238 | 98.5k | int avaiLeftBelowUnits = 0; |
1239 | 98.5k | bool bNeighborFlags[4 * MAX_NUM_PART_IDXS_IN_CTU_WIDTH + 1]; |
1240 | 98.5k | memset(bNeighborFlags, 0, totalUnits); |
1241 | 98.5k | bool aboveIsAvailable, leftIsAvailable; |
1242 | 98.5k | const ChannelType areaCh = toChannelType( area.compID ); |
1243 | | |
1244 | 98.5k | int availlableUnit = isLeftAvailable(cu, areaCh, area.pos(), iLeftUnits, unitHeight, (bNeighborFlags + iLeftUnits + leftBelowUnits - 1)); |
1245 | | |
1246 | 98.5k | leftIsAvailable = availlableUnit == iTUHeightInUnits; |
1247 | | |
1248 | 98.5k | availlableUnit = isAboveAvailable(cu, areaCh, area.pos(), iAboveUnits, unitWidth, (bNeighborFlags + iLeftUnits + leftBelowUnits + 1)); |
1249 | | |
1250 | 98.5k | aboveIsAvailable = availlableUnit == iTUWidthInUnits; |
1251 | | |
1252 | 98.5k | if (leftIsAvailable) // if left is not available, then the below left is not available |
1253 | 33.0k | { |
1254 | 33.0k | avaiLeftBelowUnits = isBelowLeftAvailable(cu, areaCh, area.bottomLeftComp(area.compID), leftBelowUnits, unitHeight, (bNeighborFlags + leftBelowUnits - 1)); |
1255 | 33.0k | } |
1256 | | |
1257 | 98.5k | if (aboveIsAvailable) // if above is not available, then the above right is not available. |
1258 | 35.9k | { |
1259 | 35.9k | avaiAboveRightUnits = isAboveRightAvailable(cu, areaCh, area.topRightComp(area.compID), aboveRightUnits, unitWidth, (bNeighborFlags + iLeftUnits + leftBelowUnits + iAboveUnits + 1)); |
1260 | 35.9k | } |
1261 | | |
1262 | 98.5k | Pel* pDst = nullptr; |
1263 | 98.5k | Pel const* piSrc = nullptr; |
1264 | | |
1265 | 98.5k | bool isFirstRowOfCtu = (lumaArea.y & ((cu.cs->sps)->CTUSize - 1)) == 0; |
1266 | | |
1267 | 98.5k | if (aboveIsAvailable) |
1268 | 35.9k | { |
1269 | 35.9k | pDst = pDst0 - iDstStride; |
1270 | 35.9k | int addedAboveRight = 0; |
1271 | 35.9k | if ((cu.intraDir[1] == MDLM_L_IDX) || (cu.intraDir[1] == MDLM_T_IDX)) |
1272 | 31.4k | { |
1273 | 31.4k | addedAboveRight = avaiAboveRightUnits*chromaUnitWidth; |
1274 | 31.4k | } |
1275 | 35.9k | if( cu.chromaFormat == CHROMA_420 && !isFirstRowOfCtu && !cu.cs->sps->verCollocatedChroma ) |
1276 | 31.2k | { |
1277 | 31.2k | LMLumaDownsample420( pRecSrc0 - iRecStride2, iRecStride, pDst, 0, uiCWidth + addedAboveRight, 1, leftIsAvailable ); |
1278 | 31.2k | } |
1279 | 4.71k | else |
1280 | 4.71k | { |
1281 | 184k | for (int i = 0; i < uiCWidth + addedAboveRight; i++) |
1282 | 179k | { |
1283 | 179k | const bool leftPadding = i == 0 && !leftIsAvailable; |
1284 | 179k | if (cu.chromaFormat == CHROMA_444) |
1285 | 0 | { |
1286 | 0 | piSrc = pRecSrc0 - iRecStride; |
1287 | 0 | pDst[i] = piSrc[i]; |
1288 | 0 | } |
1289 | 179k | else if (isFirstRowOfCtu) |
1290 | 179k | { |
1291 | 179k | piSrc = pRecSrc0 - iRecStride; |
1292 | 179k | pDst[i] = (piSrc[2 * i] * 2 + piSrc[2 * i - (leftPadding ? 0 : 1)] + piSrc[2 * i + 1] + 2) >> 2; |
1293 | 179k | } |
1294 | 0 | else if (cu.chromaFormat == CHROMA_422) |
1295 | 0 | { |
1296 | 0 | piSrc = pRecSrc0 - iRecStride2; |
1297 | |
|
1298 | 0 | int s = 2; |
1299 | 0 | s += piSrc[2 * i] * 2; |
1300 | 0 | s += piSrc[2 * i - (leftPadding ? 0 : 1)]; |
1301 | 0 | s += piSrc[2 * i + 1]; |
1302 | 0 | pDst[i] = s >> 2; |
1303 | 0 | } |
1304 | 0 | else |
1305 | 0 | { |
1306 | 0 | CHECKD( !cu.cs->sps->verCollocatedChroma, "the 4:2:0 6-tap case is handled by LMLumaDownsample420" ); |
1307 | 0 | piSrc = pRecSrc0 - iRecStride2; |
1308 | |
|
1309 | 0 | int s = 4; |
1310 | 0 | s += piSrc[2 * i - iRecStride]; |
1311 | 0 | s += piSrc[2 * i] * 4; |
1312 | 0 | s += piSrc[2 * i - (leftPadding ? 0 : 1)]; |
1313 | 0 | s += piSrc[2 * i + 1]; |
1314 | 0 | s += piSrc[2 * i + iRecStride]; |
1315 | 0 | pDst[i] = s >> 3; |
1316 | 0 | } |
1317 | 179k | } |
1318 | 4.71k | } |
1319 | 35.9k | } |
1320 | | |
1321 | 98.5k | if (leftIsAvailable) |
1322 | 33.0k | { |
1323 | 33.0k | pDst = pDst0 - 1; |
1324 | 33.0k | piSrc = pRecSrc0 - 1 - logSubWidthC; |
1325 | | |
1326 | 33.0k | int addedLeftBelow = 0; |
1327 | 33.0k | if ((cu.intraDir[1] == MDLM_L_IDX) || (cu.intraDir[1] == MDLM_T_IDX)) |
1328 | 29.3k | { |
1329 | 29.3k | addedLeftBelow = avaiLeftBelowUnits*chromaUnitHeight; |
1330 | 29.3k | } |
1331 | | |
1332 | 671k | for (int j = 0; j < uiCHeight + addedLeftBelow; j++) |
1333 | 638k | { |
1334 | 638k | if (cu.chromaFormat == CHROMA_444) |
1335 | 0 | { |
1336 | 0 | pDst[0] = piSrc[0]; |
1337 | 0 | } |
1338 | 638k | else if (cu.chromaFormat == CHROMA_422) |
1339 | 0 | { |
1340 | 0 | int s = 2; |
1341 | 0 | s += piSrc[0] * 2; |
1342 | 0 | s += piSrc[-1]; |
1343 | 0 | s += piSrc[1]; |
1344 | 0 | pDst[0] = s >> 2; |
1345 | 0 | } |
1346 | 638k | else if (cu.cs->sps->verCollocatedChroma) |
1347 | 0 | { |
1348 | 0 | const bool abovePadding = j == 0 && !aboveIsAvailable; |
1349 | |
|
1350 | 0 | int s = 4; |
1351 | 0 | s += piSrc[-(abovePadding ? 0 : iRecStride)]; |
1352 | 0 | s += piSrc[0] * 4; |
1353 | 0 | s += piSrc[-1]; |
1354 | 0 | s += piSrc[1]; |
1355 | 0 | s += piSrc[iRecStride]; |
1356 | 0 | pDst[0] = s >> 3; |
1357 | 0 | } |
1358 | 638k | else |
1359 | 638k | { |
1360 | 638k | int s = 4; |
1361 | 638k | s += piSrc[0] * 2; |
1362 | 638k | s += piSrc[1]; |
1363 | 638k | s += piSrc[-1]; |
1364 | 638k | s += piSrc[iRecStride] * 2; |
1365 | 638k | s += piSrc[iRecStride + 1]; |
1366 | 638k | s += piSrc[iRecStride - 1]; |
1367 | 638k | pDst[0] = s >> 3; |
1368 | 638k | } |
1369 | | |
1370 | 638k | piSrc += iRecStride2; |
1371 | 638k | pDst += iDstStride; |
1372 | 638k | } |
1373 | 33.0k | } |
1374 | | |
1375 | | // inner part from reconstructed picture buffer |
1376 | 98.5k | if( cu.chromaFormat == CHROMA_420 && !cu.cs->sps->verCollocatedChroma ) |
1377 | 98.5k | { |
1378 | 98.5k | LMLumaDownsample420( pRecSrc0, iRecStride, pDst0, iDstStride, uiCWidth, uiCHeight, leftIsAvailable ); |
1379 | 98.5k | } |
1380 | 0 | else |
1381 | 0 | { |
1382 | 0 | for( int j = 0; j < uiCHeight; j++ ) |
1383 | 0 | { |
1384 | 0 | for( int i = 0; i < uiCWidth; i++ ) |
1385 | 0 | { |
1386 | 0 | if (cu.chromaFormat == CHROMA_444) |
1387 | 0 | { |
1388 | 0 | pDst0[i] = pRecSrc0[i]; |
1389 | 0 | } |
1390 | 0 | else if (cu.chromaFormat == CHROMA_422) |
1391 | 0 | { |
1392 | 0 | const bool leftPadding = i == 0 && !leftIsAvailable; |
1393 | |
|
1394 | 0 | int s = 2; |
1395 | 0 | s += pRecSrc0[2 * i] * 2; |
1396 | 0 | s += pRecSrc0[2 * i - (leftPadding ? 0 : 1)]; |
1397 | 0 | s += pRecSrc0[2 * i + 1]; |
1398 | 0 | pDst0[i] = s >> 2; |
1399 | 0 | } |
1400 | 0 | else |
1401 | 0 | { |
1402 | 0 | CHECKD( !cu.cs->sps->verCollocatedChroma, "the 4:2:0 6-tap case is handled by LMLumaDownsample420" ); |
1403 | 0 | const bool leftPadding = i == 0 && !leftIsAvailable; |
1404 | 0 | const bool abovePadding = j == 0 && !aboveIsAvailable; |
1405 | |
|
1406 | 0 | int s = 4; |
1407 | 0 | s += pRecSrc0[2 * i - (abovePadding ? 0 : iRecStride)]; |
1408 | 0 | s += pRecSrc0[2 * i] * 4; |
1409 | 0 | s += pRecSrc0[2 * i - (leftPadding ? 0 : 1)]; |
1410 | 0 | s += pRecSrc0[2 * i + 1]; |
1411 | 0 | s += pRecSrc0[2 * i + iRecStride]; |
1412 | 0 | pDst0[i] = s >> 3; |
1413 | 0 | } |
1414 | 0 | } |
1415 | | |
1416 | 0 | pDst0 += iDstStride; |
1417 | 0 | pRecSrc0 += iRecStride2; |
1418 | 0 | } |
1419 | 0 | } |
1420 | 98.5k | } |
1421 | | |
1422 | | void IntraPrediction::xGetLMParameters(const CodingUnit& cu, const ComponentID compID, |
1423 | | const CompArea& chromaArea, |
1424 | | int& a, int& b, int& iShift) |
1425 | 258k | { |
1426 | 258k | CHECK(compID == COMP_Y, ""); |
1427 | | |
1428 | 258k | const SizeType cWidth = chromaArea.width; |
1429 | 258k | const SizeType cHeight = chromaArea.height; |
1430 | | |
1431 | 258k | const Position posLT = chromaArea; |
1432 | | |
1433 | 258k | CodingStructure & cs = *(cu.cs); |
1434 | | |
1435 | 258k | const SPS & sps = *cs.sps; |
1436 | 258k | const uint32_t tuWidth = chromaArea.width; |
1437 | 258k | const uint32_t tuHeight = chromaArea.height; |
1438 | 258k | const ChromaFormat nChromaFormat = sps.chromaFormatIdc; |
1439 | | |
1440 | 258k | const int unitWidthLog2 = MIN_CU_LOG2 - getComponentScaleX(chromaArea.compID, nChromaFormat); |
1441 | 258k | const int unitHeightLog2 = MIN_CU_LOG2 - getComponentScaleY(chromaArea.compID, nChromaFormat); |
1442 | 258k | const int unitWidth = 1<<unitWidthLog2; |
1443 | 258k | const int unitHeight = 1<<unitHeightLog2; |
1444 | | |
1445 | 258k | const int tuWidthInUnits = tuWidth >> unitWidthLog2; |
1446 | 258k | const int tuHeightInUnits = tuHeight >> unitHeightLog2; |
1447 | 258k | const int aboveUnits = tuWidthInUnits; |
1448 | 258k | const int leftUnits = tuHeightInUnits; |
1449 | 258k | int topTemplateSampNum = 2 * cWidth; // for MDLM, the template sample number is 2W or 2H; |
1450 | 258k | int leftTemplateSampNum = 2 * cHeight; |
1451 | 258k | int totalAboveUnits = (topTemplateSampNum + (unitWidth - 1)) >> unitWidthLog2; |
1452 | 258k | int totalLeftUnits = (leftTemplateSampNum + (unitHeight - 1)) >> unitHeightLog2; |
1453 | 258k | int totalUnits = totalLeftUnits + totalAboveUnits + 1; |
1454 | 258k | int aboveRightUnits = totalAboveUnits - aboveUnits; |
1455 | 258k | int leftBelowUnits = totalLeftUnits - leftUnits; |
1456 | 258k | int avaiAboveRightUnits = 0; |
1457 | 258k | int avaiLeftBelowUnits = 0; |
1458 | 258k | int avaiAboveUnits = 0; |
1459 | 258k | int avaiLeftUnits = 0; |
1460 | | |
1461 | 258k | const int curChromaMode = cu.intraDir[1]; |
1462 | 258k | bool neighborFlags[4 * MAX_NUM_PART_IDXS_IN_CTU_WIDTH + 1]; |
1463 | 258k | memset(neighborFlags, 0, totalUnits); |
1464 | | |
1465 | 258k | bool aboveAvailable, leftAvailable; |
1466 | | |
1467 | 258k | int availableUnit = isAboveAvailable(cu, CH_C, posLT, aboveUnits, unitWidth, |
1468 | 258k | (neighborFlags + leftUnits + leftBelowUnits + 1)); |
1469 | 258k | aboveAvailable = availableUnit == tuWidthInUnits; |
1470 | | |
1471 | 258k | availableUnit = isLeftAvailable(cu, CH_C, posLT, leftUnits, unitHeight, |
1472 | 258k | (neighborFlags + leftUnits + leftBelowUnits - 1)); |
1473 | 258k | leftAvailable = availableUnit == tuHeightInUnits; |
1474 | 258k | if (leftAvailable) // if left is not available, then the below left is not available |
1475 | 86.6k | { |
1476 | 86.6k | avaiLeftUnits = tuHeightInUnits; |
1477 | 86.6k | avaiLeftBelowUnits = isBelowLeftAvailable(cu, CH_C, chromaArea.bottomLeftComp(chromaArea.compID), leftBelowUnits, unitHeight, (neighborFlags + leftBelowUnits - 1)); |
1478 | 86.6k | } |
1479 | 258k | if (aboveAvailable) // if above is not available, then the above right is not available. |
1480 | 96.0k | { |
1481 | 96.0k | avaiAboveUnits = tuWidthInUnits; |
1482 | 96.0k | avaiAboveRightUnits = isAboveRightAvailable(cu, CH_C, chromaArea.topRightComp(chromaArea.compID), aboveRightUnits, unitWidth, (neighborFlags + leftUnits + leftBelowUnits + aboveUnits + 1)); |
1483 | 96.0k | } |
1484 | | |
1485 | 258k | const int srcStride = 2 * MAX_TB_SIZEY + 1; |
1486 | 258k | Pel* srcColor0 = m_pMdlmTemp + srcStride + 1; |
1487 | | |
1488 | 258k | Pel* curChroma0 = getPredictorPtr(compID); |
1489 | | |
1490 | 258k | unsigned internalBitDepth = sps.bitDepths[CH_C]; |
1491 | | |
1492 | 258k | int minLuma[2] = { MAX_INT, 0 }; |
1493 | 258k | int maxLuma[2] = { -MAX_INT, 0 }; |
1494 | | |
1495 | 258k | Pel* src = srcColor0 - srcStride; |
1496 | 258k | int actualTopTemplateSampNum = 0; |
1497 | 258k | int actualLeftTemplateSampNum = 0; |
1498 | 258k | if (curChromaMode == MDLM_T_IDX) |
1499 | 103k | { |
1500 | 103k | leftAvailable = 0; |
1501 | 103k | avaiAboveRightUnits = avaiAboveRightUnits > (cHeight>>unitWidthLog2) ? cHeight>>unitWidthLog2 : avaiAboveRightUnits; |
1502 | 103k | actualTopTemplateSampNum = unitWidth*(avaiAboveUnits + avaiAboveRightUnits); |
1503 | 103k | } |
1504 | 155k | else if (curChromaMode == MDLM_L_IDX) |
1505 | 103k | { |
1506 | 103k | aboveAvailable = 0; |
1507 | 103k | avaiLeftBelowUnits = avaiLeftBelowUnits > (cWidth>>unitHeightLog2) ? cWidth>>unitHeightLog2 : avaiLeftBelowUnits; |
1508 | 103k | actualLeftTemplateSampNum = unitHeight*(avaiLeftUnits + avaiLeftBelowUnits); |
1509 | 103k | } |
1510 | 52.1k | else if (curChromaMode == LM_CHROMA_IDX) |
1511 | 52.1k | { |
1512 | 52.1k | actualTopTemplateSampNum = cWidth; |
1513 | 52.1k | actualLeftTemplateSampNum = cHeight; |
1514 | 52.1k | } |
1515 | 258k | int startPos[2]; //0:Above, 1: Left |
1516 | 258k | int pickStep[2]; |
1517 | | |
1518 | 258k | int aboveIs4 = leftAvailable ? 0 : 1; |
1519 | 258k | int leftIs4 = aboveAvailable ? 0 : 1; |
1520 | | |
1521 | 258k | startPos[0] = actualTopTemplateSampNum >> (2 + aboveIs4); |
1522 | 258k | pickStep[0] = std::max(1, actualTopTemplateSampNum >> (1 + aboveIs4)); |
1523 | | |
1524 | 258k | startPos[1] = actualLeftTemplateSampNum >> (2 + leftIs4); |
1525 | 258k | pickStep[1] = std::max(1, actualLeftTemplateSampNum >> (1 + leftIs4)); |
1526 | | |
1527 | 258k | Pel selectLumaPix[4] = { 0, 0, 0, 0 }; |
1528 | 258k | Pel selectChromaPix[4] = { 0, 0, 0, 0 }; |
1529 | | |
1530 | 258k | int cntT, cntL; |
1531 | 258k | cntT = cntL = 0; |
1532 | 258k | int cnt = 0; |
1533 | 258k | if (aboveAvailable) |
1534 | 52.5k | { |
1535 | 52.5k | cntT = std::min(actualTopTemplateSampNum, (1 + aboveIs4) << 1); |
1536 | 52.5k | src = srcColor0 - srcStride; |
1537 | 52.5k | const Pel *cur = curChroma0 + 1; |
1538 | 259k | for (int pos = startPos[0]; cnt < cntT; pos += pickStep[0], cnt++) |
1539 | 207k | { |
1540 | 207k | selectLumaPix[cnt] = src[pos]; |
1541 | 207k | selectChromaPix[cnt] = cur[pos]; |
1542 | 207k | } |
1543 | 52.5k | } |
1544 | | |
1545 | 258k | if (leftAvailable) |
1546 | 46.9k | { |
1547 | 46.9k | cntL = std::min(actualLeftTemplateSampNum, ( 1 + leftIs4 ) << 1 ); |
1548 | 46.9k | src = srcColor0 - 1; |
1549 | 46.9k | const Pel *cur = curChroma0 + m_refBufferStride[compID] + 1; |
1550 | 231k | for (int pos = startPos[1], cnt = 0; cnt < cntL; pos += pickStep[1], cnt++) |
1551 | 184k | { |
1552 | 184k | selectLumaPix[cnt + cntT] = src[pos * srcStride]; |
1553 | 184k | selectChromaPix[cnt + cntT] = cur[pos]; |
1554 | 184k | } |
1555 | 46.9k | } |
1556 | 258k | cnt = cntL + cntT; |
1557 | | |
1558 | 258k | if (cnt == 2) |
1559 | 16 | { |
1560 | 16 | selectLumaPix[3] = selectLumaPix[0]; selectChromaPix[3] = selectChromaPix[0]; |
1561 | 16 | selectLumaPix[2] = selectLumaPix[1]; selectChromaPix[2] = selectChromaPix[1]; |
1562 | 16 | selectLumaPix[0] = selectLumaPix[1]; selectChromaPix[0] = selectChromaPix[1]; |
1563 | 16 | selectLumaPix[1] = selectLumaPix[3]; selectChromaPix[1] = selectChromaPix[3]; |
1564 | 16 | } |
1565 | | |
1566 | 258k | int minGrpIdx[2] = { 0, 2 }; |
1567 | 258k | int maxGrpIdx[2] = { 1, 3 }; |
1568 | 258k | int *tmpMinGrp = minGrpIdx; |
1569 | 258k | int *tmpMaxGrp = maxGrpIdx; |
1570 | 258k | if (selectLumaPix[tmpMinGrp[0]] > selectLumaPix[tmpMinGrp[1]]) std::swap(tmpMinGrp[0], tmpMinGrp[1]); |
1571 | 258k | if (selectLumaPix[tmpMaxGrp[0]] > selectLumaPix[tmpMaxGrp[1]]) std::swap(tmpMaxGrp[0], tmpMaxGrp[1]); |
1572 | 258k | if (selectLumaPix[tmpMinGrp[0]] > selectLumaPix[tmpMaxGrp[1]]) std::swap(tmpMinGrp, tmpMaxGrp); |
1573 | 258k | if (selectLumaPix[tmpMinGrp[1]] > selectLumaPix[tmpMaxGrp[0]]) std::swap(tmpMinGrp[1], tmpMaxGrp[0]); |
1574 | | |
1575 | 258k | minLuma[0] = (selectLumaPix[tmpMinGrp[0]] + selectLumaPix[tmpMinGrp[1]] + 1 )>>1; |
1576 | 258k | minLuma[1] = (selectChromaPix[tmpMinGrp[0]] + selectChromaPix[tmpMinGrp[1]] + 1) >> 1; |
1577 | 258k | maxLuma[0] = (selectLumaPix[tmpMaxGrp[0]] + selectLumaPix[tmpMaxGrp[1]] + 1 )>>1; |
1578 | 258k | maxLuma[1] = (selectChromaPix[tmpMaxGrp[0]] + selectChromaPix[tmpMaxGrp[1]] + 1) >> 1; |
1579 | | |
1580 | 258k | if (leftAvailable || aboveAvailable) |
1581 | 98.0k | { |
1582 | 98.0k | int diff = maxLuma[0] - minLuma[0]; |
1583 | 98.0k | if (diff > 0) |
1584 | 530 | { |
1585 | 530 | int diffC = maxLuma[1] - minLuma[1]; |
1586 | 530 | int x = floorLog2( diff ); |
1587 | 530 | static const uint8_t DivSigTable[1 << 4] = { |
1588 | | // 4bit significands - 8 ( MSB is omitted ) |
1589 | 530 | 0, 7, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 0 |
1590 | 530 | }; |
1591 | 530 | int normDiff = (diff << 4 >> x) & 15; |
1592 | 530 | int v = DivSigTable[normDiff] | 8; |
1593 | 530 | x += normDiff != 0; |
1594 | | |
1595 | 530 | int y = diffC == 0 ? 0 : floorLog2( abs( diffC ) ) + 1; |
1596 | 530 | int add = 1 << y >> 1; |
1597 | 530 | a = (diffC * v + add) >> y; |
1598 | 530 | iShift = 3 + x - y; |
1599 | 530 | if ( iShift < 1 ) |
1600 | 0 | { |
1601 | 0 | iShift = 1; |
1602 | 0 | a = ( (a == 0)? 0: (a < 0)? -15 : 15 ); // a=Sign(a)*15 |
1603 | 0 | } |
1604 | 530 | b = minLuma[1] - ((a * minLuma[0]) >> iShift); |
1605 | 530 | } |
1606 | 97.5k | else |
1607 | 97.5k | { |
1608 | 97.5k | a = 0; |
1609 | 97.5k | b = minLuma[1]; |
1610 | 97.5k | iShift = 0; |
1611 | 97.5k | } |
1612 | 98.0k | } |
1613 | 160k | else |
1614 | 160k | { |
1615 | 160k | a = 0; |
1616 | 160k | b = 1 << (internalBitDepth - 1); |
1617 | 160k | iShift = 0; |
1618 | 160k | } |
1619 | 258k | } |
1620 | | |
1621 | | void IntraPrediction::initIntraMip( const CodingUnit& cu ) |
1622 | 54.9k | { |
1623 | 54.9k | CHECK( cu.lwidth() > cu.cs->sps->getMaxTbSize() || cu.lheight() > cu.cs->sps->getMaxTbSize(), "Error: block size not supported for MIP" ); |
1624 | | |
1625 | | // prepare input (boundary) data for prediction |
1626 | 54.9k | CHECK(m_ipaParam.refFilterFlag, "ERROR: unfiltered refs expected for MIP"); |
1627 | 54.9k | Pel *ptrSrc = getPredictorPtr(COMP_Y); |
1628 | 54.9k | const int srcStride = m_refBufferStride[COMP_Y]; |
1629 | 54.9k | const int srcHStride = 2; |
1630 | | |
1631 | 54.9k | m_matrixIntraPred.prepareInputForPred(CPelBuf(ptrSrc, srcStride, srcHStride), cu.Y(), cu.slice->sps->bitDepths[CH_L]); |
1632 | 54.9k | } |
1633 | | |
1634 | | void IntraPrediction::predIntraMip( PelBuf &piPred, const CodingUnit& cu ) |
1635 | 330k | { |
1636 | 330k | CHECK( cu.lwidth() > cu.cs->sps->getMaxTbSize() || cu.lheight() > cu.cs->sps->getMaxTbSize(), "Error: block size not supported for MIP" ); |
1637 | 330k | CHECK( cu.lwidth() != (1 << floorLog2(cu.lwidth())) || cu.lheight() != (1 << floorLog2(cu.lheight())), "Error: expecting blocks of size 2^M x 2^N" ); |
1638 | | |
1639 | | // generate mode-specific prediction |
1640 | 330k | const int bitDepth = cu.slice->sps->bitDepths[CH_L]; |
1641 | | |
1642 | 330k | CHECK( cu.lwidth() != piPred.stride, " no support yet" ); |
1643 | | |
1644 | 330k | m_matrixIntraPred.predBlock(piPred.buf, cu.intraDir[CH_L], cu.mipTransposedFlag, bitDepth); |
1645 | 330k | } |
1646 | | |
1647 | | void IntraPrediction::initIntraPatternChTypeISP(const CodingUnit& cu, const CompArea& area, PelBuf& recBuf, |
1648 | | const bool forceRefFilterFlag) |
1649 | 23.7k | { |
1650 | 23.7k | const CodingStructure& cs = *cu.cs; |
1651 | | |
1652 | 23.7k | if (!forceRefFilterFlag) |
1653 | 23.7k | { |
1654 | 23.7k | initPredIntraParams(cu, area, *cs.sps); |
1655 | 23.7k | } |
1656 | | |
1657 | 23.7k | const Position posLT = area; |
1658 | 23.7k | bool isLeftAvail = |
1659 | 23.7k | (cs.getCURestricted(posLT.offset(-1, 0), cu, CH_L) != NULL); |
1660 | 23.7k | bool isAboveAvail = |
1661 | 23.7k | (cs.getCURestricted(posLT.offset(0, -1), cu, CH_L) != NULL); |
1662 | | // ----- Step 1: unfiltered reference samples ----- |
1663 | 23.7k | if (cu.blocks[area.compID].x == area.x && cu.blocks[area.compID].y == area.y) |
1664 | 19.0k | { |
1665 | 19.0k | Pel* refBufUnfiltered = m_refBuffer[area.compID][PRED_BUF_UNFILTERED]; |
1666 | | // With the first subpartition all the CU reference samples are fetched at once in a single call to |
1667 | | // xFillReferenceSamples |
1668 | 19.0k | if (cu.ispMode == HOR_INTRA_SUBPARTITIONS) |
1669 | 9.18k | { |
1670 | 9.18k | m_leftRefLength = cu.Y().height << 1; |
1671 | 9.18k | m_topRefLength = cu.Y().width + area.width; |
1672 | 9.18k | } |
1673 | 9.86k | else // if (cu.ispMode == VER_INTRA_SUBPARTITIONS) |
1674 | 9.86k | { |
1675 | 9.86k | m_leftRefLength = cu.Y().height + area.height; |
1676 | 9.86k | m_topRefLength = cu.Y().width << 1; |
1677 | 9.86k | } |
1678 | | |
1679 | 19.0k | xFillReferenceSamples(cs.picture->getRecoBuf(cu.Y()), refBufUnfiltered, cu.Y(), cu); |
1680 | | |
1681 | | // After having retrieved all the CU reference samples, the number of reference samples is now adjusted for the |
1682 | | // current subpartition |
1683 | 19.0k | m_topRefLength = cu.blocks[area.compID].width + area.width; |
1684 | 19.0k | m_leftRefLength = cu.blocks[area.compID].height + area.height; |
1685 | 19.0k | } |
1686 | 4.71k | else |
1687 | 4.71k | { |
1688 | 4.71k | m_topRefLength = cu.blocks[area.compID].width + area.width; |
1689 | 4.71k | m_leftRefLength = cu.blocks[area.compID].height + area.height; |
1690 | | |
1691 | 4.71k | const int predSizeHor = m_topRefLength; |
1692 | 4.71k | const int predSizeVer = m_leftRefLength; |
1693 | 4.71k | if (cu.ispMode == HOR_INTRA_SUBPARTITIONS) |
1694 | 3.61k | { |
1695 | 3.61k | Pel* src = recBuf.bufAt(0, -1); |
1696 | 3.61k | Pel* ref = m_refBuffer[area.compID][PRED_BUF_UNFILTERED] + m_refBufferStride[area.compID]; |
1697 | 3.61k | if (isLeftAvail) |
1698 | 0 | { |
1699 | 0 | for (int i = 0; i <= 2 * cu.blocks[area.compID].height - area.height; i++) |
1700 | 0 | { |
1701 | 0 | ref[i] = ref[i + area.height]; |
1702 | 0 | } |
1703 | 0 | } |
1704 | 3.61k | else |
1705 | 3.61k | { |
1706 | 75.6k | for (int i = 0; i <= predSizeVer; i++) |
1707 | 72.0k | { |
1708 | 72.0k | ref[i] = src[0]; |
1709 | 72.0k | } |
1710 | 3.61k | } |
1711 | 3.61k | Pel* dst = m_refBuffer[area.compID][PRED_BUF_UNFILTERED] + 1; |
1712 | 3.61k | dst[-1] = ref[0]; |
1713 | 74.7k | for (int i = 0; i < area.width; i++) |
1714 | 71.0k | { |
1715 | 71.0k | dst[i] = src[i]; |
1716 | 71.0k | } |
1717 | 3.61k | Pel sample = src[area.width - 1]; |
1718 | 3.61k | dst += area.width; |
1719 | 74.7k | for (int i = 0; i < predSizeHor - area.width; i++) |
1720 | 71.0k | { |
1721 | 71.0k | dst[i] = sample; |
1722 | 71.0k | } |
1723 | 3.61k | } |
1724 | 1.10k | else |
1725 | 1.10k | { |
1726 | 1.10k | Pel* src = recBuf.bufAt(-1, 0); |
1727 | 1.10k | Pel* ref = m_refBuffer[area.compID][PRED_BUF_UNFILTERED]; |
1728 | 1.10k | if (isAboveAvail) |
1729 | 0 | { |
1730 | 0 | for (int i = 0; i <= 2 * cu.blocks[area.compID].width - area.width; i++) |
1731 | 0 | { |
1732 | 0 | ref[i] = ref[i + area.width]; |
1733 | 0 | } |
1734 | 0 | } |
1735 | 1.10k | else |
1736 | 1.10k | { |
1737 | 24.2k | for (int i = 0; i <= predSizeHor; i++) |
1738 | 23.1k | { |
1739 | 23.1k | ref[i] = src[0]; |
1740 | 23.1k | } |
1741 | 1.10k | } |
1742 | 1.10k | Pel* dst = m_refBuffer[area.compID][PRED_BUF_UNFILTERED] + m_refBufferStride[area.compID] + 1; |
1743 | 1.10k | dst[-1] = ref[0]; |
1744 | 24.9k | for (int i = 0; i < area.height; i++) |
1745 | 23.8k | { |
1746 | 23.8k | *dst = *src; |
1747 | 23.8k | src += recBuf.stride; |
1748 | 23.8k | dst++; |
1749 | 23.8k | } |
1750 | 1.10k | Pel sample = src[-recBuf.stride]; |
1751 | 24.9k | for (int i = 0; i < predSizeVer - area.height; i++) |
1752 | 23.8k | { |
1753 | 23.8k | *dst = sample; |
1754 | 23.8k | dst++; |
1755 | 23.8k | } |
1756 | 1.10k | } |
1757 | 4.71k | } |
1758 | | // ----- Step 2: filtered reference samples ----- |
1759 | 23.7k | if (m_ipaParam.refFilterFlag || forceRefFilterFlag) |
1760 | 0 | { |
1761 | 0 | Pel* refBufUnfiltered = m_refBuffer[area.compID][PRED_BUF_UNFILTERED]; |
1762 | 0 | Pel* refBufFiltered = m_refBuffer[area.compID][PRED_BUF_FILTERED]; |
1763 | 0 | xFilterReferenceSamples(refBufUnfiltered, refBufFiltered, area, *cs.sps, cu.multiRefIdx); |
1764 | 0 | } |
1765 | 23.7k | } |
1766 | | |
1767 | | void IntraPrediction::setReferenceArrayLengths(const CompArea& area) |
1768 | 1.01M | { |
1769 | | // set Top and Left reference samples length |
1770 | 1.01M | const int width = area.width; |
1771 | 1.01M | const int height = area.height; |
1772 | | |
1773 | 1.01M | m_leftRefLength = (height << 1); |
1774 | 1.01M | m_topRefLength = (width << 1); |
1775 | 1.01M | } |
1776 | | |
1777 | | } // namespace vvenc |
1778 | | |
1779 | | //! \} |
1780 | | |