Coverage Report

Created: 2026-10-28 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvenc/source/Lib/CommonLib/MatrixIntraPrediction.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     MatrixIntraPrediction.cpp
45
\brief    matrix-based intra prediction class
46
*/
47
48
49
#include "MatrixIntraPrediction.h"
50
#include "dtrace_next.h"
51
52
#include "UnitTools.h"
53
#include "MipData.h"
54
55
namespace vvenc {
56
57
static const int MIP_MAX_INPUT_SIZE             =  8;
58
static const int MIP_MAX_REDUCED_OUTPUT_SAMPLES = 64;
59
60
MatrixIntraPrediction::MatrixIntraPrediction()
61
5.97k
  : m_reducedBoundary       (nullptr)
62
5.97k
  , m_reducedBoundaryTransp (nullptr)
63
5.97k
  , m_inputOffset           ( 0 )
64
5.97k
  , m_inputOffsetTransp     ( 0 )
65
5.97k
  , m_refSamplesTop         (nullptr)
66
5.97k
  , m_refSamplesLeft        (nullptr)
67
5.97k
  , m_blockSize             ( 0, 0 )
68
5.97k
  , m_sizeId                ( 0 )
69
5.97k
  , m_reducedBdrySize       ( 0 )
70
5.97k
  , m_reducedPredSize       ( 0 )
71
5.97k
  , m_upsmpFactorHor        ( 0 )
72
5.97k
  , m_upsmpFactorVer        ( 0 )
73
5.97k
{
74
5.97k
  m_reducedBoundary       = (Pel*)xMalloc( Pel, MIP_MAX_INPUT_SIZE ); 
75
5.97k
  m_reducedBoundaryTransp = (Pel*)xMalloc( Pel, MIP_MAX_INPUT_SIZE );
76
5.97k
}
77
78
MatrixIntraPrediction::~MatrixIntraPrediction()
79
5.97k
{
80
5.97k
  xFree( m_reducedBoundary );       m_reducedBoundary = nullptr;
81
5.97k
  xFree( m_reducedBoundaryTransp ); m_reducedBoundaryTransp = nullptr;
82
5.97k
}
83
84
void MatrixIntraPrediction::prepareInputForPred(const CPelBuf &pSrc, const Area& block, const int bitDepth)
85
54.9k
{
86
  // Step 1: Save block size and calculate dependent values
87
54.9k
  initPredBlockParams(block);
88
89
54.9k
  m_refSamplesTop  = pSrc.bufAt(1, 0);
90
54.9k
  m_refSamplesLeft = pSrc.bufAt(1, 1);
91
92
  // Step 3: Compute the reduced boundary via Haar-downsampling (input for the prediction)
93
54.9k
  const int inputSize = 2 * m_reducedBdrySize;
94
95
54.9k
  Pel* const topReduced = m_reducedBoundary;
96
54.9k
  boundaryDownsampling1D( topReduced, m_refSamplesTop, block.width, m_reducedBdrySize );
97
98
54.9k
  Pel* const leftReduced = m_reducedBoundary + m_reducedBdrySize;
99
54.9k
  boundaryDownsampling1D( leftReduced, m_refSamplesLeft, block.height, m_reducedBdrySize );
100
101
54.9k
  Pel* const leftReducedTransposed = m_reducedBoundaryTransp;
102
54.9k
  Pel* const topReducedTransposed  = m_reducedBoundaryTransp + m_reducedBdrySize;
103
274k
  for( int x = 0; x < m_reducedBdrySize; x++ )
104
219k
  {
105
219k
    topReducedTransposed[x] = topReduced[x];
106
219k
  }
107
274k
  for( int y = 0; y < m_reducedBdrySize; y++ )
108
219k
  {
109
219k
    leftReducedTransposed[y] = leftReduced[y];
110
219k
  }
111
112
  // Step 4: Rebase the reduced boundary
113
54.9k
  m_inputOffset       = m_reducedBoundary[0];
114
54.9k
  m_inputOffsetTransp = m_reducedBoundaryTransp[0];
115
116
54.9k
  const bool hasFirstCol = (m_sizeId < 2);
117
54.9k
  m_reducedBoundary      [0] = hasFirstCol ? ((1 << (bitDepth - 1)) - m_inputOffset      ) : 0; // first column of matrix not needed for large blocks
118
54.9k
  m_reducedBoundaryTransp[0] = hasFirstCol ? ((1 << (bitDepth - 1)) - m_inputOffsetTransp) : 0;
119
439k
  for (int i = 1; i < inputSize; i++)
120
384k
  {
121
384k
    m_reducedBoundary      [i] -= m_inputOffset;
122
384k
    m_reducedBoundaryTransp[i] -= m_inputOffsetTransp;
123
384k
  }
124
54.9k
}
125
126
void MatrixIntraPrediction::predBlock(Pel* const result, const int modeIdx, const bool transpose, const int bitDepth)
127
330k
{
128
330k
  ALIGN_DATA( MEMORY_ALIGN_DEF_SIZE, Pel bufReducedPred[MIP_MAX_REDUCED_OUTPUT_SAMPLES] );
129
130
330k
  const bool       needUpsampling  = ( m_upsmpFactorHor > 1 ) || ( m_upsmpFactorVer > 1 );
131
330k
  Pel* const       reducedPred     = needUpsampling ? bufReducedPred : result;
132
330k
  const Pel* const reducedBoundary = transpose ? m_reducedBoundaryTransp : m_reducedBoundary;
133
134
330k
  {
135
330k
    const int outputSize = m_reducedPredSize;
136
330k
    const int inputSize  = 2 * m_reducedBdrySize;
137
330k
    const int offset     = transpose ? m_inputOffsetTransp : m_inputOffset;
138
330k
    const int maxVal     = ( 1 << bitDepth ) - 1;
139
140
330k
    if( outputSize == 8)
141
322k
    {
142
322k
      g_pelBufOP.mipMatrixMul_8_8( reducedPred, reducedBoundary, &mipMatrix16x16[modeIdx][0][0], maxVal, offset, transpose );
143
322k
    }
144
8.35k
    else
145
8.35k
    {
146
8.35k
      if( inputSize == 4)
147
0
      {
148
0
        g_pelBufOP.mipMatrixMul_4_4( reducedPred, reducedBoundary, &mipMatrix4x4[modeIdx][0][0], maxVal, offset, transpose );
149
0
      }
150
8.35k
      else
151
8.35k
      {
152
8.35k
        g_pelBufOP.mipMatrixMul_8_4( reducedPred, reducedBoundary, &mipMatrix8x8[modeIdx][0][0], maxVal, offset, transpose );
153
8.35k
      }
154
8.35k
    }
155
330k
  }
156
157
  // Reduced prediction is transposed if ( transpose && needUpsampling ).
158
330k
  if( needUpsampling )
159
330k
  {
160
330k
    const Pel* verSrc   = reducedPred;
161
330k
    SizeType verSrcStep = m_blockSize.width;
162
163
    // upsampling factors 2, 4 or 8: MIP blocks are at most 64x64 with an aspect ratio of at most 4
164
638k
    auto log2Factor = []( unsigned factor ) { return factor == 2 ? 1u : factor == 4 ? 2u : 3u; };
165
166
330k
    if( m_upsmpFactorHor > 1 )
167
319k
    {
168
319k
      Pel* const horDst = result + (m_upsmpFactorVer - 1) * m_blockSize.width;
169
319k
      verSrc = horDst;
170
319k
      verSrcStep *= m_upsmpFactorVer;
171
172
319k
      g_pelBufOP.mipUpsampleHor( horDst, reducedPred, &m_refSamplesLeft[0], verSrcStep, m_upsmpFactorVer, m_reducedPredSize, log2Factor( m_upsmpFactorHor ) );
173
319k
    }
174
175
330k
    if( m_upsmpFactorVer > 1 )
176
318k
    {
177
318k
      g_pelBufOP.mipUpsampleVer( result, verSrc, &m_refSamplesTop[0], m_blockSize.width, verSrcStep, m_reducedPredSize, log2Factor( m_upsmpFactorVer ) );
178
318k
    }
179
330k
  }
180
330k
}
181
182
void MatrixIntraPrediction::initPredBlockParams(const Size& block)
183
54.9k
{
184
54.9k
  m_blockSize = block;
185
  // init size index
186
54.9k
  m_sizeId = getMipSizeId( m_blockSize );
187
188
  // init reduced boundary size
189
54.9k
  m_reducedBdrySize = (m_sizeId == 0) ? 2 : 4;
190
191
  // init reduced prediction size
192
54.9k
  m_reducedPredSize = ( m_sizeId < 2 ) ? 4 : 8;
193
194
  // init upsampling factors
195
54.9k
  m_upsmpFactorHor = m_blockSize.width  / m_reducedPredSize;
196
54.9k
  m_upsmpFactorVer = m_blockSize.height / m_reducedPredSize;
197
198
54.9k
  CHECKD( (m_upsmpFactorHor < 1) || ((m_upsmpFactorHor & (m_upsmpFactorHor - 1)) != 0), "Need power of two horizontal upsampling factor." );
199
54.9k
  CHECKD( (m_upsmpFactorVer < 1) || ((m_upsmpFactorVer & (m_upsmpFactorVer - 1)) != 0), "Need power of two vertical upsampling factor." );
200
54.9k
}
201
202
void MatrixIntraPrediction::boundaryDownsampling1D(Pel* reducedDst, const Pel* const fullSrc, const SizeType srcLen, const SizeType dstLen)
203
109k
{
204
109k
  if (dstLen < srcLen)
205
109k
  {
206
    // Create reduced boundary by downsampling
207
109k
    const SizeType downsmpFactor = srcLen / dstLen;
208
109k
    const int log2DownsmpFactor = floorLog2(downsmpFactor);
209
109k
    const int roundingOffset = (1 << (log2DownsmpFactor - 1));
210
211
109k
    SizeType srcIdx = 0;
212
549k
    for( SizeType dstIdx = 0; dstIdx < dstLen; dstIdx++ )
213
439k
    {
214
439k
      int sum = 0;
215
4.39M
      for( int k = 0; k < downsmpFactor; k++ )
216
3.95M
      {
217
3.95M
        sum += fullSrc[srcIdx++];
218
3.95M
      }
219
439k
      reducedDst[dstIdx] = (sum + roundingOffset) >> log2DownsmpFactor;
220
439k
    }
221
109k
  }
222
0
  else
223
0
  {
224
    // Copy boundary if no downsampling is needed
225
0
    for (SizeType i = 0; i < dstLen; ++i)
226
0
    {
227
0
      reducedDst[i] = fullSrc[i];
228
0
    }
229
0
  }
230
109k
}
231
232
233
234
} // namespace vvenc
235
236
//! \}